summaryrefslogtreecommitdiffstats
path: root/src/components/organisms
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/organisms')
-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
11 files changed, 177 insertions, 385 deletions
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);
}
}
}