summaryrefslogtreecommitdiffstats
path: root/src/components
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2022-06-08 19:06:27 +0200
committerArmand Philippot <git@armandphilippot.com>2022-06-09 12:34:03 +0200
commitcfdddac43f10d06a8b0e9bcf69dc0ce77ce16649 (patch)
treee3fe4d20291ddbfb0a0a2a17b5cb66107ed735e1 /src/components
parent58cb40f031f395ca9efccff674ba0f2dae723f50 (diff)
fix(settings): avoid cropped tooltip on small devices
I changed the settings disposition to make tooltip positioning easier. Jest complains about ref passed but everything seems to work as expected so I'm not sure it is relevant. Maybe a bug with cloneElement.
Diffstat (limited to 'src/components')
-rw-r--r--src/components/molecules/forms/ackee-toggle.stories.tsx13
-rw-r--r--src/components/molecules/forms/ackee-toggle.tsx6
-rw-r--r--src/components/molecules/forms/fieldset.module.scss4
-rw-r--r--src/components/molecules/forms/fieldset.stories.tsx17
-rw-r--r--src/components/molecules/forms/fieldset.tsx7
-rw-r--r--src/components/molecules/forms/motion-toggle.tsx5
-rw-r--r--src/components/molecules/forms/prism-theme-toggle.tsx2
-rw-r--r--src/components/molecules/forms/radio-group.module.scss6
-rw-r--r--src/components/molecules/forms/radio-group.stories.tsx13
-rw-r--r--src/components/molecules/forms/radio-group.tsx9
-rw-r--r--src/components/molecules/forms/theme-toggle.tsx2
-rw-r--r--src/components/molecules/modals/modal.module.scss4
-rw-r--r--src/components/organisms/forms/settings-form.module.scss81
-rw-r--r--src/components/organisms/forms/settings-form.stories.tsx73
-rw-r--r--src/components/organisms/forms/settings-form.test.tsx66
-rw-r--r--src/components/organisms/forms/settings-form.tsx73
-rw-r--r--src/components/organisms/modals/settings-modal.module.scss46
-rw-r--r--src/components/organisms/modals/settings-modal.stories.tsx9
-rw-r--r--src/components/organisms/modals/settings-modal.test.tsx32
-rw-r--r--src/components/organisms/modals/settings-modal.tsx84
-rw-r--r--src/components/organisms/toolbar/settings.module.scss10
-rw-r--r--src/components/organisms/toolbar/settings.tsx6
-rw-r--r--src/components/organisms/toolbar/toolbar.module.scss82
23 files changed, 246 insertions, 404 deletions
diff --git a/src/components/molecules/forms/ackee-toggle.stories.tsx b/src/components/molecules/forms/ackee-toggle.stories.tsx
index bbc6fb4..3f3f11e 100644
--- a/src/components/molecules/forms/ackee-toggle.stories.tsx
+++ b/src/components/molecules/forms/ackee-toggle.stories.tsx
@@ -22,6 +22,19 @@ export default {
required: false,
},
},
+ buttonClassName: {
+ control: {
+ type: 'text',
+ },
+ description: 'Set additional classnames to the help button.',
+ table: {
+ category: 'Styles',
+ },
+ type: {
+ name: 'string',
+ required: false,
+ },
+ },
className: {
control: {
type: 'text',
diff --git a/src/components/molecules/forms/ackee-toggle.tsx b/src/components/molecules/forms/ackee-toggle.tsx
index a666731..67a3644 100644
--- a/src/components/molecules/forms/ackee-toggle.tsx
+++ b/src/components/molecules/forms/ackee-toggle.tsx
@@ -14,7 +14,11 @@ import Tooltip, { type TooltipProps } from '../modals/tooltip';
export type AckeeToggleProps = Pick<
RadioGroupProps,
- 'bodyClassName' | 'groupClassName' | 'legendClassName'
+ | 'bodyClassName'
+ | 'buttonClassName'
+ | 'groupClassName'
+ | 'legendClassName'
+ | 'legendPosition'
> & {
/**
* Set additional classnames to the toggle wrapper.
diff --git a/src/components/molecules/forms/fieldset.module.scss b/src/components/molecules/forms/fieldset.module.scss
index 3102bf7..38327b4 100644
--- a/src/components/molecules/forms/fieldset.module.scss
+++ b/src/components/molecules/forms/fieldset.module.scss
@@ -5,12 +5,12 @@
font-weight: 600;
&#{&}--has-tooltip {
- padding: 0 var(--spacing-xs) 0 0;
+ margin: 0 var(--spacing-2xs) 0 0;
}
}
.btn {
- margin: 0 var(--spacing-2xs) var(--spacing-2xs) 0;
+ margin: 0 var(--spacing-xs) var(--spacing-2xs) 0;
&--activated {
background: var(--color-primary);
diff --git a/src/components/molecules/forms/fieldset.stories.tsx b/src/components/molecules/forms/fieldset.stories.tsx
index 0778094..85aeb7f 100644
--- a/src/components/molecules/forms/fieldset.stories.tsx
+++ b/src/components/molecules/forms/fieldset.stories.tsx
@@ -1,6 +1,4 @@
import { ComponentMeta, ComponentStory } from '@storybook/react';
-import { TooltipProps } from '../modals/tooltip';
-import { Help } from '../modals/tooltip.stories';
import FieldsetComponent from './fieldset';
import { body, legend, Tooltip } from './fieldset.fixture';
@@ -8,7 +6,7 @@ import { body, legend, Tooltip } from './fieldset.fixture';
* Fieldset - Storybook Meta
*/
export default {
- title: 'Atoms/Forms/Fieldset',
+ title: 'Molecules/Forms/Fieldset',
component: FieldsetComponent,
args: {
legendPosition: 'stacked',
@@ -28,6 +26,19 @@ export default {
required: false,
},
},
+ buttonClassName: {
+ control: {
+ type: 'text',
+ },
+ description: 'Set additional classnames to the help button.',
+ table: {
+ category: 'Styles',
+ },
+ type: {
+ name: 'string',
+ required: false,
+ },
+ },
children: {
control: {
type: null,
diff --git a/src/components/molecules/forms/fieldset.tsx b/src/components/molecules/forms/fieldset.tsx
index dae3ead..961ec6d 100644
--- a/src/components/molecules/forms/fieldset.tsx
+++ b/src/components/molecules/forms/fieldset.tsx
@@ -17,6 +17,10 @@ export type FieldsetProps = {
*/
bodyClassName?: string;
/**
+ * Set additional classnames to the help button.
+ */
+ buttonClassName?: string;
+ /**
* The fieldset body.
*/
children: ReactNode | ReactNode[];
@@ -57,6 +61,7 @@ export type FieldsetProps = {
*/
const Fieldset: FC<FieldsetProps> = ({
bodyClassName = '',
+ buttonClassName = '',
children,
className = '',
legend,
@@ -102,7 +107,7 @@ const Fieldset: FC<FieldsetProps> = ({
<>
<HelpButton
aria-pressed={isTooltipOpened}
- className={`${styles.btn} ${buttonModifier}`}
+ className={`${styles.btn} ${buttonModifier} ${buttonClassName}`}
onClick={() => setIsTooltipOpened(!isTooltipOpened)}
ref={buttonRef}
/>
diff --git a/src/components/molecules/forms/motion-toggle.tsx b/src/components/molecules/forms/motion-toggle.tsx
index ec2d950..ad47b33 100644
--- a/src/components/molecules/forms/motion-toggle.tsx
+++ b/src/components/molecules/forms/motion-toggle.tsx
@@ -13,7 +13,7 @@ export type MotionToggleValue = 'on' | 'off';
export type MotionToggleProps = Pick<
RadioGroupProps,
- 'bodyClassName' | 'groupClassName' | 'legendClassName'
+ 'bodyClassName' | 'groupClassName' | 'legendClassName' | 'legendPosition'
> & {
/**
* True if motion should be reduced by default.
@@ -41,7 +41,8 @@ const MotionToggle: FC<MotionToggleProps> = ({
defaultValue === 'on' ? false : true
);
useAttributes({
- element: document.documentElement || undefined,
+ element:
+ typeof window !== 'undefined' ? document.documentElement : undefined,
attribute: 'reduced-motion',
value: `${isReduced}`,
});
diff --git a/src/components/molecules/forms/prism-theme-toggle.tsx b/src/components/molecules/forms/prism-theme-toggle.tsx
index 0fd9f54..5a4d8a9 100644
--- a/src/components/molecules/forms/prism-theme-toggle.tsx
+++ b/src/components/molecules/forms/prism-theme-toggle.tsx
@@ -12,7 +12,7 @@ import RadioGroup, {
export type PrismThemeToggleProps = Pick<
RadioGroupProps,
- 'bodyClassName' | 'groupClassName' | 'legendClassName'
+ 'bodyClassName' | 'groupClassName' | 'legendClassName' | 'legendPosition'
>;
/**
diff --git a/src/components/molecules/forms/radio-group.module.scss b/src/components/molecules/forms/radio-group.module.scss
index 0bd34b9..f363d1b 100644
--- a/src/components/molecules/forms/radio-group.module.scss
+++ b/src/components/molecules/forms/radio-group.module.scss
@@ -2,9 +2,9 @@
@use "@styles/abstracts/mixins" as mix;
.wrapper {
- &--inline#{&}--regular {
- .option:first-of-type {
- margin-left: var(--spacing-2xs);
+ &--inline {
+ .legend {
+ margin-right: var(--spacing-2xs);
}
}
diff --git a/src/components/molecules/forms/radio-group.stories.tsx b/src/components/molecules/forms/radio-group.stories.tsx
index ad1bd6d..de5da7c 100644
--- a/src/components/molecules/forms/radio-group.stories.tsx
+++ b/src/components/molecules/forms/radio-group.stories.tsx
@@ -26,6 +26,19 @@ export default {
required: false,
},
},
+ buttonClassName: {
+ control: {
+ type: 'text',
+ },
+ description: 'Set additional classnames to the help button.',
+ table: {
+ category: 'Styles',
+ },
+ type: {
+ name: 'string',
+ required: false,
+ },
+ },
className: {
control: {
type: 'text',
diff --git a/src/components/molecules/forms/radio-group.tsx b/src/components/molecules/forms/radio-group.tsx
index 134829f..3930908 100644
--- a/src/components/molecules/forms/radio-group.tsx
+++ b/src/components/molecules/forms/radio-group.tsx
@@ -25,7 +25,12 @@ export type RadioGroupOption = Pick<
export type RadioGroupProps = Pick<
FieldsetProps,
- 'bodyClassName' | 'className' | 'legend' | 'legendClassName' | 'Tooltip'
+ | 'bodyClassName'
+ | 'buttonClassName'
+ | 'className'
+ | 'legend'
+ | 'legendClassName'
+ | 'Tooltip'
> &
Pick<LabelledBooleanFieldProps, 'labelPosition' | 'labelSize'> & {
/**
@@ -78,6 +83,7 @@ const RadioGroup: FC<RadioGroupProps> = ({
kind = 'regular',
labelPosition,
labelSize,
+ legendClassName,
legendPosition = 'inline',
onChange,
optionClassName = '',
@@ -134,6 +140,7 @@ const RadioGroup: FC<RadioGroupProps> = ({
return (
<Fieldset
className={`${styles.wrapper} ${styles[alignmentModifier]} ${styles[toggleModifier]} ${className}`}
+ legendClassName={`${styles.legend} ${legendClassName}`}
legendPosition={legendPosition}
role="radiogroup"
{...props}
diff --git a/src/components/molecules/forms/theme-toggle.tsx b/src/components/molecules/forms/theme-toggle.tsx
index 1c6481a..6a676a9 100644
--- a/src/components/molecules/forms/theme-toggle.tsx
+++ b/src/components/molecules/forms/theme-toggle.tsx
@@ -12,7 +12,7 @@ import RadioGroup, {
export type ThemeToggleProps = Pick<
RadioGroupProps,
- 'bodyClassName' | 'groupClassName' | 'legendClassName'
+ 'bodyClassName' | 'groupClassName' | 'legendClassName' | 'legendPosition'
>;
/**
diff --git a/src/components/molecules/modals/modal.module.scss b/src/components/molecules/modals/modal.module.scss
index 8866834..f57d33c 100644
--- a/src/components/molecules/modals/modal.module.scss
+++ b/src/components/molecules/modals/modal.module.scss
@@ -24,10 +24,6 @@
margin-bottom: var(--spacing-2xs);
}
}
-
- @include mix.dimensions("sm") {
- max-width: 35ch;
- }
}
}
diff --git a/src/components/organisms/forms/settings-form.module.scss b/src/components/organisms/forms/settings-form.module.scss
deleted file mode 100644
index 647f1b5..0000000
--- a/src/components/organisms/forms/settings-form.module.scss
+++ /dev/null
@@ -1,81 +0,0 @@
-@use "@styles/abstracts/mixins" as mix;
-
-.wrapper {
- display: flex;
- flex-flow: row wrap;
- align-items: flex-start;
- align-content: flex-start;
-
- @include mix.media("screen") {
- @include mix.dimensions(null, "2xs", "height") {
- column-gap: var(--spacing-lg);
- row-gap: var(--spacing-xs);
- font-size: var(--font-size-sm);
- }
- }
-
- .label {
- @include mix.media("screen") {
- @include mix.dimensions(null, "2xs", "height") {
- margin: 0 auto;
- float: none;
- font-size: var(--font-size-sm);
- }
-
- @include mix.dimensions(null, "2xs") {
- //font-size: var(--font-size-sm);
- }
- }
- }
-
- .tooltip {
- top: unset;
- bottom: calc(100% + var(--spacing-2xs));
- font-size: var(--font-size-sm);
- transform-origin: bottom center;
-
- @include mix.media("screen") {
- @include mix.dimensions(null, "2xs", "height") {
- width: 250%;
- transform-origin: bottom left;
- }
-
- @include mix.dimensions("sm") {
- font-size: var(--font-size-md);
- }
- }
- }
-}
-
-.items {
- margin: var(--spacing-2xs) 0;
-
- @include mix.media("screen") {
- @include mix.dimensions(null, "2xs", "height") {
- display: flex;
- flex-flow: column wrap;
- max-width: fit-content;
- margin: 0;
- }
- }
-}
-
-.group {
- margin-left: auto;
-
- @include mix.media("screen") {
- @include mix.dimensions(null, "2xs", "height") {
- margin: auto;
- }
- }
-}
-
-.fieldset__body {
- margin-left: auto;
-
- @include mix.media("screen") {
- @include mix.dimensions(null, "2xs", "height") {
- margin: 0 auto;
- }
- }
-}
diff --git a/src/components/organisms/forms/settings-form.stories.tsx b/src/components/organisms/forms/settings-form.stories.tsx
deleted file mode 100644
index de9f769..0000000
--- a/src/components/organisms/forms/settings-form.stories.tsx
+++ /dev/null
@@ -1,73 +0,0 @@
-import { storageKey as ackeeStorageKey } from '@components/molecules/forms/ackee-toggle.fixture';
-import { storageKey as motionStorageKey } from '@components/molecules/forms/motion-toggle.fixture';
-import { ComponentMeta, ComponentStory } from '@storybook/react';
-import SettingsForm from './settings-form';
-
-/**
- * SettingsModal - Storybook Meta
- */
-export default {
- title: 'Organisms/Forms',
- component: SettingsForm,
- argTypes: {
- ackeeStorageKey: {
- control: {
- type: 'text',
- },
- description: 'The local storage key for Ackee setting.',
- type: {
- name: 'string',
- required: true,
- },
- },
- className: {
- control: {
- type: 'text',
- },
- description: 'Set additional classnames to the modal wrapper.',
- table: {
- category: 'Styles',
- },
- type: {
- name: 'string',
- required: false,
- },
- },
- motionStorageKey: {
- control: {
- type: 'text',
- },
- description: 'The local storage key for reduced motion setting.',
- type: {
- name: 'string',
- required: true,
- },
- },
- tooltipClassName: {
- control: {
- type: 'text',
- },
- description: 'Set additional classnames to the tooltip wrapper.',
- table: {
- category: 'Styles',
- },
- type: {
- name: 'string',
- required: false,
- },
- },
- },
-} as ComponentMeta<typeof SettingsForm>;
-
-const Template: ComponentStory<typeof SettingsForm> = (args) => (
- <SettingsForm {...args} />
-);
-
-/**
- * Form Stories - Settings
- */
-export const Settings = Template.bind({});
-Settings.args = {
- ackeeStorageKey,
- motionStorageKey,
-};
diff --git a/src/components/organisms/forms/settings-form.test.tsx b/src/components/organisms/forms/settings-form.test.tsx
deleted file mode 100644
index de2d4c9..0000000
--- a/src/components/organisms/forms/settings-form.test.tsx
+++ /dev/null
@@ -1,66 +0,0 @@
-import { storageKey as ackeeStorageKey } from '@components/molecules/forms/ackee-toggle.fixture';
-import { storageKey as motionStorageKey } from '@components/molecules/forms/motion-toggle.fixture';
-import { render, screen } from '@tests/utils';
-import SettingsForm from './settings-form';
-
-describe('SettingsForm', () => {
- it('renders a form', () => {
- render(
- <SettingsForm
- ackeeStorageKey={ackeeStorageKey}
- motionStorageKey={motionStorageKey}
- />
- );
- expect(
- screen.getByRole('form', { name: /^Settings form/i })
- ).toBeInTheDocument();
- });
-
- it('renders a theme setting', () => {
- render(
- <SettingsForm
- ackeeStorageKey={ackeeStorageKey}
- motionStorageKey={motionStorageKey}
- />
- );
- expect(
- screen.getByRole('radiogroup', { name: /^Theme:/i })
- ).toBeInTheDocument();
- });
-
- it('renders a code blocks setting', () => {
- render(
- <SettingsForm
- ackeeStorageKey={ackeeStorageKey}
- motionStorageKey={motionStorageKey}
- />
- );
- expect(
- screen.getByRole('radiogroup', { name: /^Code blocks:/i })
- ).toBeInTheDocument();
- });
-
- it('renders a motion setting', () => {
- render(
- <SettingsForm
- ackeeStorageKey={ackeeStorageKey}
- motionStorageKey={motionStorageKey}
- />
- );
- expect(
- screen.getByRole('radiogroup', { name: /^Animations:/i })
- ).toBeInTheDocument();
- });
-
- it('renders a Ackee setting', () => {
- render(
- <SettingsForm
- ackeeStorageKey={ackeeStorageKey}
- motionStorageKey={motionStorageKey}
- />
- );
- expect(
- screen.getByRole('radiogroup', { name: /^Tracking:/i })
- ).toBeInTheDocument();
- });
-});
diff --git a/src/components/organisms/forms/settings-form.tsx b/src/components/organisms/forms/settings-form.tsx
deleted file mode 100644
index 5d915a8..0000000
--- a/src/components/organisms/forms/settings-form.tsx
+++ /dev/null
@@ -1,73 +0,0 @@
-import Form from '@components/atoms/forms/form';
-import AckeeToggle, {
- type AckeeToggleProps,
-} from '@components/molecules/forms/ackee-toggle';
-import MotionToggle, {
- type MotionToggleProps,
-} from '@components/molecules/forms/motion-toggle';
-import PrismThemeToggle from '@components/molecules/forms/prism-theme-toggle';
-import ThemeToggle from '@components/molecules/forms/theme-toggle';
-import { FC } from 'react';
-import { useIntl } from 'react-intl';
-import styles from './settings-form.module.scss';
-
-export type SettingsFormProps = Pick<AckeeToggleProps, 'tooltipClassName'> & {
- /**
- * The local storage key for Ackee settings.
- */
- ackeeStorageKey: AckeeToggleProps['storageKey'];
- /**
- * The local storage key for Reduce motion settings.
- */
- motionStorageKey: MotionToggleProps['storageKey'];
-};
-
-const SettingsForm: FC<SettingsFormProps> = ({
- ackeeStorageKey,
- motionStorageKey,
- tooltipClassName,
-}) => {
- const intl = useIntl();
- const ariaLabel = intl.formatMessage({
- defaultMessage: 'Settings form',
- id: 'gX+YVy',
- description: 'SettingsForm: an accessible form name',
- });
-
- return (
- <Form
- aria-label={ariaLabel}
- className={styles.wrapper}
- itemsClassName={styles.items}
- onSubmit={() => null}
- >
- <ThemeToggle
- bodyClassName={styles.fieldset__body}
- groupClassName={styles.group}
- legendClassName={styles.label}
- />
- <PrismThemeToggle
- bodyClassName={styles.fieldset__body}
- groupClassName={styles.group}
- legendClassName={styles.label}
- />
- <MotionToggle
- defaultValue="on"
- bodyClassName={styles.fieldset__body}
- groupClassName={styles.group}
- legendClassName={styles.label}
- storageKey={motionStorageKey}
- />
- <AckeeToggle
- defaultValue="full"
- bodyClassName={styles.fieldset__body}
- groupClassName={`${styles.group} ${styles['group--ackee']}`}
- legendClassName={`${styles.label} ${styles['label--ackee']}`}
- storageKey={ackeeStorageKey}
- tooltipClassName={`${styles.tooltip} ${tooltipClassName}`}
- />
- </Form>
- );
-};
-
-export default SettingsForm;
diff --git a/src/components/organisms/modals/settings-modal.module.scss b/src/components/organisms/modals/settings-modal.module.scss
new file mode 100644
index 0000000..fef3492
--- /dev/null
+++ b/src/components/organisms/modals/settings-modal.module.scss
@@ -0,0 +1,46 @@
+@use "@styles/abstracts/functions" as fun;
+@use "@styles/abstracts/variables" as var;
+
+.wrapper {
+ width: 100%;
+
+ @media screen and (max-height: #{var.get-breakpoint("2xs")}) and (max-width: #{var.get-breakpoint("sm")}) {
+ --first-col-width: #{fun.convert-px(160)};
+ --col-gap: var(--spacing-xl);
+
+ display: grid;
+ grid-template-columns: var(--first-col-width) 1fr;
+ gap: var(--spacing-xl);
+ }
+}
+
+.form {
+ display: flex;
+ flex-flow: row wrap;
+ column-gap: var(--spacing-lg);
+}
+
+.items {
+ margin: 0 0 var(--spacing-2xs);
+ max-width: unset;
+}
+
+.fieldset__body {
+ margin-left: auto;
+}
+
+.tooltip {
+ font-size: var(--font-size-sm);
+ z-index: 2;
+
+ @media screen and (max-height: #{var.get-breakpoint("2xs")}) {
+ width: calc(100vw - var(--spacing-md));
+ padding: var(--spacing-md) var(--spacing-2xs) var(--spacing-2xs)
+ var(--spacing-2xs);
+ right: 0;
+ }
+
+ @media screen and (min-width: #{var.get-breakpoint("sm")}) {
+ width: 100%;
+ }
+}
diff --git a/src/components/organisms/modals/settings-modal.stories.tsx b/src/components/organisms/modals/settings-modal.stories.tsx
index d263e2b..649d68b 100644
--- a/src/components/organisms/modals/settings-modal.stories.tsx
+++ b/src/components/organisms/modals/settings-modal.stories.tsx
@@ -1,3 +1,5 @@
+import { storageKey as ackeeStorageKey } from '@components/molecules/forms/ackee-toggle.fixture';
+import { storageKey as motionStorageKey } from '@components/molecules/forms/motion-toggle.fixture';
import { ComponentMeta, ComponentStory } from '@storybook/react';
import SettingsModal from './settings-modal';
@@ -55,6 +57,9 @@ export default {
},
},
},
+ parameters: {
+ layout: 'fullscreen',
+ },
} as ComponentMeta<typeof SettingsModal>;
const Template: ComponentStory<typeof SettingsModal> = (args) => (
@@ -65,3 +70,7 @@ const Template: ComponentStory<typeof SettingsModal> = (args) => (
* Modals Stories - Settings
*/
export const Settings = Template.bind({});
+Settings.args = {
+ ackeeStorageKey,
+ motionStorageKey,
+};
diff --git a/src/components/organisms/modals/settings-modal.test.tsx b/src/components/organisms/modals/settings-modal.test.tsx
index 91f77de..9277067 100644
--- a/src/components/organisms/modals/settings-modal.test.tsx
+++ b/src/components/organisms/modals/settings-modal.test.tsx
@@ -1,14 +1,40 @@
+import { storageKey as ackeeStorageKey } from '@components/molecules/forms/ackee-toggle.fixture';
+import { storageKey as motionStorageKey } from '@components/molecules/forms/motion-toggle.fixture';
import { render, screen } from '@tests/utils';
import SettingsModal from './settings-modal';
describe('SettingsModal', () => {
- it('renders a fake heading', () => {
+ it('renders the modal heading', () => {
render(
<SettingsModal
- ackeeStorageKey="ackee-tracking"
- motionStorageKey="reduce-motion"
+ ackeeStorageKey={ackeeStorageKey}
+ motionStorageKey={motionStorageKey}
/>
);
expect(screen.getByText(/Settings/i)).toBeInTheDocument();
});
+
+ it('renders a settings form', () => {
+ render(
+ <SettingsModal
+ ackeeStorageKey={ackeeStorageKey}
+ motionStorageKey={motionStorageKey}
+ />
+ );
+ expect(
+ screen.getByRole('form', { name: /^Settings form/i })
+ ).toBeInTheDocument();
+ expect(
+ screen.getByRole('radiogroup', { name: /^Theme:/i })
+ ).toBeInTheDocument();
+ expect(
+ screen.getByRole('radiogroup', { name: /^Code blocks:/i })
+ ).toBeInTheDocument();
+ expect(
+ screen.getByRole('radiogroup', { name: /^Animations:/i })
+ ).toBeInTheDocument();
+ expect(
+ screen.getByRole('radiogroup', { name: /^Tracking:/i })
+ ).toBeInTheDocument();
+ });
});
diff --git a/src/components/organisms/modals/settings-modal.tsx b/src/components/organisms/modals/settings-modal.tsx
index 0ab6b7a..d11dfe7 100644
--- a/src/components/organisms/modals/settings-modal.tsx
+++ b/src/components/organisms/modals/settings-modal.tsx
@@ -1,23 +1,28 @@
-import Spinner from '@components/atoms/loaders/spinner';
+import Form from '@components/atoms/forms/form';
+import AckeeToggle, {
+ AckeeToggleProps,
+} from '@components/molecules/forms/ackee-toggle';
+import MotionToggle, {
+ MotionToggleProps,
+} from '@components/molecules/forms/motion-toggle';
+import PrismThemeToggle from '@components/molecules/forms/prism-theme-toggle';
+import ThemeToggle from '@components/molecules/forms/theme-toggle';
import Modal, { type ModalProps } from '@components/molecules/modals/modal';
-import dynamic from 'next/dynamic';
import { FC } from 'react';
import { useIntl } from 'react-intl';
-import { type SettingsFormProps } from '../forms/settings-form';
-
-const DynamicSettingsForm = dynamic(
- () => import('@components/organisms/forms/settings-form'),
- {
- loading: () => <Spinner />,
- ssr: false,
- }
-);
+import styles from './settings-modal.module.scss';
export type SettingsModalProps = Pick<ModalProps, 'className'> &
- Pick<
- SettingsFormProps,
- 'ackeeStorageKey' | 'motionStorageKey' | 'tooltipClassName'
- >;
+ Pick<AckeeToggleProps, 'tooltipClassName'> & {
+ /**
+ * The local storage key for Ackee settings.
+ */
+ ackeeStorageKey: AckeeToggleProps['storageKey'];
+ /**
+ * The local storage key for Reduce motion settings.
+ */
+ motionStorageKey: MotionToggleProps['storageKey'];
+ };
/**
* SettingsModal component
@@ -26,7 +31,9 @@ export type SettingsModalProps = Pick<ModalProps, 'className'> &
*/
const SettingsModal: FC<SettingsModalProps> = ({
className = '',
- ...props
+ ackeeStorageKey,
+ motionStorageKey,
+ tooltipClassName,
}) => {
const intl = useIntl();
const title = intl.formatMessage({
@@ -34,10 +41,51 @@ const SettingsModal: FC<SettingsModalProps> = ({
description: 'SettingsModal: title',
id: 'gPfT/K',
});
+ const ariaLabel = intl.formatMessage({
+ defaultMessage: 'Settings form',
+ id: 'xYNeKX',
+ description: 'SettingsModal: an accessible form name',
+ });
return (
- <Modal title={title} icon="cogs" className={className}>
- <DynamicSettingsForm {...props} />
+ <Modal
+ title={title}
+ icon="cogs"
+ className={`${styles.wrapper} ${className}`}
+ >
+ <Form
+ aria-label={ariaLabel}
+ className={styles.form}
+ itemsClassName={styles.items}
+ onSubmit={() => null}
+ >
+ <ThemeToggle
+ bodyClassName={styles.fieldset__body}
+ groupClassName={styles.group}
+ legendClassName={styles.label}
+ />
+ <PrismThemeToggle
+ bodyClassName={styles.fieldset__body}
+ groupClassName={styles.group}
+ legendClassName={styles.label}
+ />
+ <MotionToggle
+ defaultValue="on"
+ bodyClassName={styles.fieldset__body}
+ groupClassName={styles.group}
+ legendClassName={styles.label}
+ storageKey={motionStorageKey}
+ />
+ <AckeeToggle
+ defaultValue="full"
+ bodyClassName={styles.fieldset__body}
+ buttonClassName={styles.btn}
+ groupClassName={`${styles.group} ${styles['group--ackee']}`}
+ legendClassName={`${styles.label} ${styles['label--ackee']}`}
+ storageKey={ackeeStorageKey}
+ tooltipClassName={`${styles.tooltip} ${tooltipClassName}`}
+ />
+ </Form>
</Modal>
);
};
diff --git a/src/components/organisms/toolbar/settings.module.scss b/src/components/organisms/toolbar/settings.module.scss
index 08c8cd4..a46f28c 100644
--- a/src/components/organisms/toolbar/settings.module.scss
+++ b/src/components/organisms/toolbar/settings.module.scss
@@ -1,10 +1,8 @@
@use "@styles/abstracts/functions" as fun;
@use "@styles/abstracts/mixins" as mix;
-.modal {
- @include mix.media("screen") {
- @include mix.dimensions("sm") {
- width: 120%;
- }
- }
+.item .tooltip {
+ top: unset;
+ bottom: calc(100% + var(--spacing-2xs));
+ transform-origin: bottom center;
}
diff --git a/src/components/organisms/toolbar/settings.tsx b/src/components/organisms/toolbar/settings.tsx
index ee59e26..774de64 100644
--- a/src/components/organisms/toolbar/settings.tsx
+++ b/src/components/organisms/toolbar/settings.tsx
@@ -50,7 +50,7 @@ const Settings: ForwardRefRenderFunction<HTMLDivElement, SettingsProps> = (
<div className={`${sharedStyles.item} ${settingsStyles.item}`} ref={ref}>
<BooleanField
checked={isActive}
- className={`${sharedStyles.checkbox} ${settingsStyles.checkbox}`}
+ className={sharedStyles.checkbox}
id="settings-button"
name="settings-button"
onChange={setIsActive}
@@ -67,9 +67,9 @@ const Settings: ForwardRefRenderFunction<HTMLDivElement, SettingsProps> = (
</FlippingLabel>
<SettingsModal
ackeeStorageKey={ackeeStorageKey}
- className={`${sharedStyles.modal} ${settingsStyles.modal} ${className}`}
+ className={`${sharedStyles.modal} ${className}`}
motionStorageKey={motionStorageKey}
- tooltipClassName={tooltipClassName}
+ tooltipClassName={`${settingsStyles.tooltip} ${tooltipClassName}`}
/>
</div>
);
diff --git a/src/components/organisms/toolbar/toolbar.module.scss b/src/components/organisms/toolbar/toolbar.module.scss
index ca9cd33..85eeee5 100644
--- a/src/components/organisms/toolbar/toolbar.module.scss
+++ b/src/components/organisms/toolbar/toolbar.module.scss
@@ -1,5 +1,5 @@
@use "@styles/abstracts/functions" as fun;
-@use "@styles/abstracts/mixins" as mix;
+@use "@styles/abstracts/variables" as var;
@use "@styles/abstracts/placeholders";
.wrapper {
@@ -8,7 +8,7 @@
display: flex;
flex-flow: row wrap;
align-items: center;
- justify-content: space-around;
+ gap: var(--spacing-sm);
width: 100%;
height: var(--toolbar-size);
position: relative;
@@ -27,72 +27,30 @@
animation: slide-in-from-bottom 0.8s ease-in-out 0s 1;
}
- @include mix.media("screen") {
- @include mix.dimensions("sm") {
- :global {
- animation: slide-in-from-top 1s ease-in-out 0s 1;
- }
- }
- }
-
- .modal {
- &--search,
- &--settings {
- @include mix.media("screen") {
- @include mix.dimensions("sm") {
- min-width: 32ch;
- }
- }
- }
- }
-
- @include mix.media("screen") {
- @include mix.dimensions(null, "2xs", "height") {
- --toolbar-size: #{fun.convert-px(70)};
- }
+ @media screen and (max-width: #{var.get-breakpoint("sm")}) {
+ justify-content: space-around;
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ z-index: 5;
- @include mix.dimensions(null, "sm") {
+ .modal {
+ width: 100%;
position: fixed;
- bottom: 0;
+ top: unset;
left: 0;
- z-index: 5;
-
- .modal {
- top: unset;
- bottom: calc(var(--toolbar-size) - #{fun.convert-px(4)});
- max-height: calc(100vh - var(--toolbar-size));
- }
-
- .tooltip {
- padding: calc(var(--title-height) / 2 + var(--spacing-2xs))
- var(--spacing-2xs) var(--spacing-2xs);
- top: unset;
- bottom: calc(100% + var(--spacing-2xs));
- transform-origin: bottom right;
- }
- }
-
- @include mix.dimensions("sm", "md") {
- .modal {
- top: calc(var(--toolbar-size) + var(--spacing-2xs));
- bottom: unset;
- }
+ bottom: calc(var(--toolbar-size) - #{fun.convert-px(4)});
+ max-height: calc(100vh - var(--toolbar-size));
}
+ }
- @include mix.dimensions("sm") {
- justify-content: flex-end;
- gap: var(--spacing-sm);
-
- .tooltip {
- transform-origin: top right;
- }
- }
+ @media screen and (max-height: #{var.get-breakpoint("2xs")}) {
+ --toolbar-size: #{fun.convert-px(70)};
+ }
- @include mix.dimensions("md") {
- .tooltip {
- width: 120%;
- right: -10%;
- }
+ @media screen and (min-width: #{var.get-breakpoint("sm")}) {
+ .modal {
+ min-width: fun.convert-px(380);
}
}
}