aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/organisms/modals
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2022-04-08 22:36:24 +0200
committerArmand Philippot <git@armandphilippot.com>2022-04-08 23:31:58 +0200
commit0b3146f7278929c4d1b33dd8f94f34e351e5e5a9 (patch)
tree6a784b197a283a7da07c2e1df80a29fee8b3790a /src/components/organisms/modals
parent61278678ea8a8febee0574cd0f6006492d7b15cb (diff)
chore: add a Settings modal component
Diffstat (limited to 'src/components/organisms/modals')
-rw-r--r--src/components/organisms/modals/settings-modal.module.scss14
-rw-r--r--src/components/organisms/modals/settings-modal.stories.tsx31
-rw-r--r--src/components/organisms/modals/settings-modal.test.tsx34
-rw-r--r--src/components/organisms/modals/settings-modal.tsx51
4 files changed, 130 insertions, 0 deletions
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..f17c9b3
--- /dev/null
+++ b/src/components/organisms/modals/settings-modal.module.scss
@@ -0,0 +1,14 @@
+.wrapper {
+ max-width: 30ch;
+
+ .label {
+ margin-right: auto;
+ }
+}
+
+.tooltip {
+ width: 120%;
+ top: calc(100% + var(--spacing-sm));
+ right: -10%;
+ transform-origin: top right;
+}
diff --git a/src/components/organisms/modals/settings-modal.stories.tsx b/src/components/organisms/modals/settings-modal.stories.tsx
new file mode 100644
index 0000000..c19a6d7
--- /dev/null
+++ b/src/components/organisms/modals/settings-modal.stories.tsx
@@ -0,0 +1,31 @@
+import { ComponentMeta, ComponentStory } from '@storybook/react';
+import { IntlProvider } from 'react-intl';
+import SettingsModal from './settings-modal';
+
+export default {
+ title: 'Organisms/Modals',
+ component: SettingsModal,
+ argTypes: {
+ className: {
+ control: {
+ type: 'text',
+ },
+ description: 'Set additional classnames to the modal wrapper.',
+ table: {
+ category: 'Styles',
+ },
+ type: {
+ name: 'string',
+ required: false,
+ },
+ },
+ },
+} as ComponentMeta<typeof SettingsModal>;
+
+const Template: ComponentStory<typeof SettingsModal> = (args) => (
+ <IntlProvider locale="en">
+ <SettingsModal {...args} />
+ </IntlProvider>
+);
+
+export const Settings = Template.bind({});
diff --git a/src/components/organisms/modals/settings-modal.test.tsx b/src/components/organisms/modals/settings-modal.test.tsx
new file mode 100644
index 0000000..44695d7
--- /dev/null
+++ b/src/components/organisms/modals/settings-modal.test.tsx
@@ -0,0 +1,34 @@
+import { render, screen } from '@test-utils';
+import SettingsModal from './settings-modal';
+
+jest.mock('next/dynamic', () => () => 'dynamic-import');
+
+describe('SettingsModal', () => {
+ it('renders a theme toggle setting', () => {
+ render(<SettingsModal />);
+ expect(
+ screen.getByRole('checkbox', { name: /^Theme:/i })
+ ).toBeInTheDocument();
+ });
+
+ it('renders a code blocks toggle setting', () => {
+ render(<SettingsModal />);
+ expect(
+ screen.getByRole('checkbox', { name: /^Code blocks:/i })
+ ).toBeInTheDocument();
+ });
+
+ it('renders a motion setting', () => {
+ render(<SettingsModal />);
+ expect(
+ screen.getByRole('checkbox', { name: /^Animations:/i })
+ ).toBeInTheDocument();
+ });
+
+ it('renders a Ackee setting', () => {
+ render(<SettingsModal />);
+ expect(
+ screen.getByRole('combobox', { name: /^Tracking:/i })
+ ).toBeInTheDocument();
+ });
+});
diff --git a/src/components/organisms/modals/settings-modal.tsx b/src/components/organisms/modals/settings-modal.tsx
new file mode 100644
index 0000000..0fac332
--- /dev/null
+++ b/src/components/organisms/modals/settings-modal.tsx
@@ -0,0 +1,51 @@
+import Form from '@components/atoms/forms/form';
+import AckeeSelect from '@components/molecules/forms/ackee-select';
+import MotionToggle 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 from '@components/molecules/modals/modal';
+import { VFC } from 'react';
+import { useIntl } from 'react-intl';
+import styles from './settings-modal.module.scss';
+
+export type SettingsModalProps = {
+ /**
+ * Set additional classnames to modal wrapper.
+ */
+ className?: string;
+};
+
+/**
+ * SettingsModal component
+ *
+ * Render a modal with settings options.
+ */
+const SettingsModal: VFC<SettingsModalProps> = ({ className }) => {
+ const intl = useIntl();
+ const title = intl.formatMessage({
+ defaultMessage: 'Settings',
+ description: 'SettingsModal: title',
+ id: 'gPfT/K',
+ });
+
+ return (
+ <Modal
+ title={title}
+ icon="cogs"
+ className={`${styles.wrapper} ${className}`}
+ >
+ <Form onSubmit={() => null}>
+ <ThemeToggle labelClassName={styles.label} value={false} />
+ <PrismThemeToggle labelClassName={styles.label} value={false} />
+ <MotionToggle labelClassName={styles.label} value={false} />
+ <AckeeSelect
+ initialValue="full"
+ labelClassName={styles.label}
+ tooltipClassName={styles.tooltip}
+ />
+ </Form>
+ </Modal>
+ );
+};
+
+export default SettingsModal;