Skip to content

Commit

Permalink
Implement responsive design
Browse files Browse the repository at this point in the history
  • Loading branch information
mogproject committed Dec 28, 2024
1 parent d210655 commit 0890ac0
Show file tree
Hide file tree
Showing 9 changed files with 240 additions and 156 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "feign-discord",
"version": "0.0.3",
"version": "0.0.4",
"private": true,
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.7.2",
Expand Down
9 changes: 4 additions & 5 deletions src/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function Header() {
<Container>
<Navbar.Brand href='#'>Feign-Discord CSS Generator</Navbar.Brand>

<Nav className="me-auto">
<Nav className="me-auto d-none d-xl-flex">
<Nav.Link href="#features">{t('features.features')}</Nav.Link>
<Nav.Link href="#settings">{t('settings.settings')}</Nav.Link>
<Nav.Link href="#preview">{t('preview.preview')}</Nav.Link>
Expand All @@ -34,15 +34,14 @@ function Header() {
size="sm"
onChange={(e) => i18n.changeLanguage(e.target.value)}
value={i18n.resolvedLanguage}
className="me-3"
>
{languages.map(({ key, nativeName }) => (<option key={key} value={key}>{nativeName}</option>))}

</Form.Select>
<a className="nav-link me-3" href="https://www.youtube.com/@mogproject" target="_blank" rel="noreferrer">

<a className="nav-link d-none d-md-block ms-3 me-3" href="https://www.youtube.com/@mogproject" target="_blank" rel="noreferrer">
<FontAwesomeIcon icon={faYoutube} size="2x" />
</a>
<a className="nav-link" href="https://github.com/mogproject/feign-discord-css-generator/" target="_blank" rel="noreferrer">
<a className="nav-link d-none d-md-block" href="https://github.com/mogproject/feign-discord-css-generator/" target="_blank" rel="noreferrer">
<FontAwesomeIcon icon={faGithub} size="2x" />
</a>
</Container>
Expand Down
21 changes: 10 additions & 11 deletions src/components/buttons/AnimationSettingButtonGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from "react";
import { ButtonGroup, Form, InputGroup } from "react-bootstrap";
import { ButtonGroup, Col, Form, InputGroup, Row } from "react-bootstrap";
import { AnimationSettings } from "../../models/ViewSettings";
import { ColorPicker } from "./ColorPicker";
import { useTranslation } from "react-i18next";
Expand All @@ -15,7 +15,7 @@ export function AnimationSettingButtonGroup(
const tt = (k: string) => { return t(k, { keyPrefix: '' }) };

const jsxJump = (
<ButtonGroup className="me-5">
<ButtonGroup>
<Form.Control
type="checkbox"
id={`${prefix}-jump`}
Expand All @@ -38,16 +38,15 @@ export function AnimationSettingButtonGroup(
id={`${prefix}-flash`}
className="btn-check"
autoComplete="off"
style={{ width: "160px" }}
checked={setting.flash}
onChange={() => handleChange({ ...setting, flash: !setting.flash })}
/>
<label className="btn btn-outline-primary" htmlFor={`${prefix}-flash`} style={{ minWidth: "96px" }}>
<label className="btn btn-outline-primary" htmlFor={`${prefix}-flash`} style={{ minWidth: "80px" }}>
{t('flash')}
</label>
</ButtonGroup>

<InputGroup className="me-5">
<InputGroup>
<InputGroup.Text>{tt('color')}</InputGroup.Text>
{ColorPicker(t('flash_color'), setting.flashColor, (color) => handleChange({ ...setting, flashColor: color }))}
</InputGroup>
Expand All @@ -65,7 +64,7 @@ export function AnimationSettingButtonGroup(
checked={setting.outline}
onChange={() => handleChange({ ...setting, outline: !setting.outline })}
/>
<label className="btn btn-outline-primary" htmlFor={`${prefix}-outline`} style={{ minWidth: "96px" }}>
<label className="btn btn-outline-primary" htmlFor={`${prefix}-outline`} style={{ minWidth: "80px" }}>
{t('outline')}
</label>
</ButtonGroup>
Expand All @@ -77,10 +76,10 @@ export function AnimationSettingButtonGroup(
);

return (
<div className="d-flex">
{jsxJump}
{jsxFlash}
{showOutline ? jsxOutline : ""}
</div>
<Row>
<Col className="col-5 col-md-5 mb-1 col-lg-3">{jsxJump}</Col>
<Col className={`col-7 col-md-7 ${showOutline ? 'mb-1 ' : ''}col-lg-4 col-xl-4 px-lg-0`}>{jsxFlash}</Col>
<Col className="col-7 col-md-6 col-lg-4 col-lg-4 px-lg-0">{showOutline ? jsxOutline : ""}</Col>
</Row>
);
}
235 changes: 141 additions & 94 deletions src/components/sections/DiscordUsers.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faArrowDown, faArrowUp } from "@fortawesome/free-solid-svg-icons";
import { faArrowDown, faArrowUp, faPen, faPenToSquare, faTractor, faTrash, faXmark } from "@fortawesome/free-solid-svg-icons";
import { Container, Row, Col, InputGroup, Form, Button, Modal } from "react-bootstrap";
import { DiscordUser, ConfContext } from "../../models/Context";
import { useTranslation } from "react-i18next";
Expand Down Expand Up @@ -92,6 +92,128 @@ export function DiscordUsers() {

function DiscordUserRow(user: DiscordUser, index: number) {
const isEditing = discordUserEditing.index < discordUsers.length;
const buttonInterval = 'me-1'

function EditButton() {
return (<Button size="sm" variant="secondary" className={`${buttonInterval} ${isEditing ? "invisible" : "visible"}`}
title={tt('edit')}
onClick={() => startEdit(index)}>
<span className="d-none d-lg-block" style={{ minWidth: '70px' }}>{tt('edit')}</span>
<span className="d-lg-none"><FontAwesomeIcon icon={faPenToSquare} /></span>
</Button>);
}

function RemoveButton() {
return (<Button size="sm" variant="danger" className={`${buttonInterval} ${isEditing ? "invisible" : "visible"}`}
title={tt('remove')}
onClick={
() => {
setModalOpen(true);
setRemoveIndex(index);
}
}>
<span className="d-none d-lg-block" style={{ minWidth: '70px' }}>{tt('remove')}</span>
<span className="d-lg-none"><FontAwesomeIcon icon={faTrash} /></span>
</Button>);
}

function SaveButton(isValid: boolean) {
const title = isEditing ? tt('save') : tt('add');
return (<Button type="submit" size="sm" variant="primary" className={`${buttonInterval}`} disabled={!isValid}
title={title}>

<span className="d-none d-lg-block" style={{ minWidth: '70px' }}>{title}</span>
<span className="d-lg-none"><FontAwesomeIcon icon={faPen} /></span>
</Button>);
}

function CancelButton(isEditing: boolean) {
return (<Button size="sm" variant="secondary" className={`${buttonInterval} ${isEditing ? "visible" : "invisible"}`} onClick={cancelEdit}
title={tt('cancel')}>
<span className="d-none d-lg-block" style={{ minWidth: '70px' }}>{tt('cancel')}</span>
<span className="d-lg-none"><FontAwesomeIcon icon={faXmark} /></span>
</Button>);
}

function MoveDownButton() {
return (<Button
size="sm"
variant="secondary"
className={`${buttonInterval} ${isEditing || index === discordUsers.length - 1 ? "invisible" : "visible"}`}
onClick={() => moveDown(index)}
>
<FontAwesomeIcon icon={faArrowDown} />
</Button>);
}

function MoveUpButton() {
return (<Button
size="sm"
variant="secondary"
className={`${isEditing || index === 0 ? "invisible" : "visible"}`}
onClick={() => moveUp(index)}
>
<FontAwesomeIcon icon={faArrowUp} />
</Button>);
}

function NameInput(disabled: boolean, isNameEmpty: boolean, isNameValid: boolean, feedback: string) {
if (disabled) {
return (<InputGroup size="sm">
<InputGroup.Text id={`discord-user-${index}`}>{tt('name')}</InputGroup.Text>
<Form.Control
area-label={`discord-user-${index}`}
area-aria-describedby={`discord-user-${index}`}
disabled={true}
value={user.name}
/>
</InputGroup>);
} else {
return (<InputGroup size="sm" hasValidation>
<InputGroup.Text id={`discord-user-edit-${index}`}>{tt('name')}</InputGroup.Text>
<Form.Control
area-label={`discord-user-edit-label-${index}`}
area-aria-describedby={`discord-user-edit-${index}`}
required={isEditing}
placeholder={t('name_placeholder')}
value={discordUserEditing.name}
isValid={!isNameEmpty && isNameValid}
isInvalid={!isNameEmpty && !isNameValid}
onChange={(e) => updateDiscordUserEditing(index, e.target.value, discordUserEditing.id)}
/>
<Form.Control.Feedback type="invalid" tooltip={true}>{feedback}</Form.Control.Feedback>
</InputGroup>);
}
}

function IdInput(disabled: boolean, isIdEmpty: boolean, isIdValid: boolean, feedback: string) {
if (disabled) {
return (<InputGroup size="sm">
<InputGroup.Text id={`discord-id-${index}`}>ID</InputGroup.Text>
<Form.Control
area-label={`discord-id-label-${index}`}
area-aria-describedby={`discord-id-${index}`}
disabled={true}
value={user.id}
/>
</InputGroup>);
} else {
return (<InputGroup size="sm" hasValidation>
<InputGroup.Text id={`discord-id-edit-${index}`}>ID</InputGroup.Text>
<Form.Control
area-label={`discord-id-edit-label-${index}`}
area-aria-describedby={`discord-id-edit-${index}`}
required={isEditing}
placeholder={t('id_placeholder')}
value={discordUserEditing.id}
isValid={!isIdEmpty && isIdValid}
isInvalid={!isIdEmpty && !isIdValid}
onChange={(e) => updateDiscordUserEditing(index, discordUserEditing.name, e.target.value)}
/>
<Form.Control.Feedback type="invalid" tooltip={true}>{feedback}</Form.Control.Feedback>
</InputGroup>);
}
}

if (index === discordUserEditing.index) {
const nameTrimmed = discordUserEditing.name.trim();
Expand All @@ -109,110 +231,35 @@ export function DiscordUsers() {
return (
<Form key={`discord-${index}`} onSubmit={handleSubmit}>
<Row className="mb-1">
<Col className="col-md-3">
<InputGroup size="sm" hasValidation>
<InputGroup.Text id={`discord-user-edit-${index}`}>{tt('name')}</InputGroup.Text>
<Form.Control
area-label={`discord-user-edit-label-${index}`}
area-aria-describedby={`discord-user-edit-${index}`}
required={isEditing}
placeholder={t('name_placeholder')}
value={discordUserEditing.name}
isValid={!isNameEmpty && isNameValid}
isInvalid={!isNameEmpty && !isNameValid}
onChange={(e) => updateDiscordUserEditing(index, e.target.value, discordUserEditing.id)}
/>
<Form.Control.Feedback type="invalid" tooltip={true}>{nameFeedback}</Form.Control.Feedback>
</InputGroup>
<Col className="col-4 col-lg-3 pe-0">
{NameInput(false, isNameEmpty, isNameValid, nameFeedback)}
</Col>
<Col className='col-md-3'>
<InputGroup size="sm" hasValidation>
<InputGroup.Text id={`discord-id-edit-${index}`}>ID</InputGroup.Text>
<Form.Control
area-label={`discord-id-edit-label-${index}`}
area-aria-describedby={`discord-id-edit-${index}`}
required={isEditing}
placeholder={t('id_placeholder')}
value={discordUserEditing.id}
isValid={!isIdEmpty && isIdValid}
isInvalid={!isIdEmpty && !isIdValid}
onChange={(e) => updateDiscordUserEditing(index, discordUserEditing.name, e.target.value)}
/>
<Form.Control.Feedback type="invalid" tooltip={true}>{idFeedback}</Form.Control.Feedback>
</InputGroup>
<Col className="col-3 col-sm-4 col-md-5 col-lg-3 pe-0">
{IdInput(false, isIdEmpty, isIdValid, idFeedback)}
</Col>
<Col className="col-md-3">
<Button type="submit" size="sm" variant="primary" className="me-3" disabled={!isNameValid || !isIdValid}
style={{ minWidth: '70px' }}>
{`${isEditing ? tt('save') : tt('add')}`}
</Button>
<Button size="sm" variant="secondary" className={`${isEditing ? "visible" : "invisible"}`} onClick={cancelEdit}
style={{ minWidth: '70px' }}>
{tt('cancel')}
</Button>
<Col className="col-5 col-sm-4 col-md-3 col-lg-5 pe-0">
{SaveButton(isNameValid && isIdValid)}
{CancelButton(isEditing)}
</Col>
</Row>
</Form>
);
} else {
return (
<Row key={`discord-${index}`} className="mb-1">
<Col className="col-md-3">
<InputGroup size="sm">
<InputGroup.Text id={`discord-user-${index}`}>{tt('name')}</InputGroup.Text>
<Form.Control
area-label={`discord-user-${index}`}
area-aria-describedby={`discord-user-${index}`}
disabled={true}
value={user.name}
/>
</InputGroup>
</Col>
<Col className="col-md-3">
<InputGroup size="sm">
<InputGroup.Text id={`discord-id-${index}`}>ID</InputGroup.Text>
<Form.Control
area-label={`discord-id-label-${index}`}
area-aria-describedby={`discord-id-${index}`}
disabled={true}
value={user.id}
/>
</InputGroup>
<Col className="col-4 col-lg-3 pe-0">
{NameInput(true, false, false, '')}
</Col>
<Col className="col-md-3">
<Button size="sm" variant="secondary" className={`me-3 ${isEditing ? "invisible" : "visible"}`}
style={{ minWidth: '70px' }}
onClick={() => startEdit(index)}>
{tt('edit')}
</Button>
<Button size="sm" variant="danger" className={`${isEditing ? "invisible" : "visible"}`}
style={{ minWidth: '70px' }}
onClick={
() => {
setModalOpen(true);
setRemoveIndex(index);
}
}>
{tt('remove')}
</Button>
<Col className="col-3 col-sm-4 col-md-5 col-lg-3 pe-0">
{IdInput(true, false, false, '')}
</Col>
<Col className="col-md-2">
<Button
size="sm"
variant="secondary"
className={`me-3 ${isEditing || index === discordUsers.length - 1 ? "invisible" : "visible"}`}
onClick={() => moveDown(index)}
>
<FontAwesomeIcon icon={faArrowDown} />
</Button>
<Button
size="sm"
variant="secondary"
className={`${isEditing || index === 0 ? "invisible" : "visible"}`}
onClick={() => moveUp(index)}
>
<FontAwesomeIcon icon={faArrowUp} />
</Button>
<Col className="col-5 col-sm-4 col-md-3 col-lg-5 pe-0">
<EditButton />
<span className="d-none d-lg-inline-block me-2" />
<RemoveButton />
<span className="d-none d-lg-inline-block me-4" />
<MoveDownButton />
<MoveUpButton />
</Col>
</Row>
);
Expand Down
Loading

0 comments on commit 0890ac0

Please sign in to comment.