summaryrefslogtreecommitdiffstats
path: root/src/components/organisms
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2022-04-14 19:25:46 +0200
committerArmand Philippot <git@armandphilippot.com>2022-04-14 19:25:46 +0200
commit1d162d7aafb3cfe2c3351b5fd891bbf6d476e9b2 (patch)
treec263967fcb9f0fdaa2f665b0471091dfcc62b34e /src/components/organisms
parent15fd9f4a6ecf947c7648c6b7865b97c40124fde1 (diff)
chore: add a Settings component
Diffstat (limited to 'src/components/organisms')
-rw-r--r--src/components/organisms/modals/settings-modal.module.scss23
-rw-r--r--src/components/organisms/modals/settings-modal.test.tsx2
-rw-r--r--src/components/organisms/modals/settings-modal.tsx14
-rw-r--r--src/components/organisms/toolbar/settings.module.scss10
-rw-r--r--src/components/organisms/toolbar/settings.stories.tsx76
-rw-r--r--src/components/organisms/toolbar/settings.test.tsx18
-rw-r--r--src/components/organisms/toolbar/settings.tsx72
7 files changed, 202 insertions, 13 deletions
diff --git a/src/components/organisms/modals/settings-modal.module.scss b/src/components/organisms/modals/settings-modal.module.scss
index f17c9b3..ebae3da 100644
--- a/src/components/organisms/modals/settings-modal.module.scss
+++ b/src/components/organisms/modals/settings-modal.module.scss
@@ -1,14 +1,21 @@
-.wrapper {
- max-width: 30ch;
+@use "@styles/abstracts/mixins" as mix;
+.wrapper {
.label {
margin-right: auto;
}
-}
-.tooltip {
- width: 120%;
- top: calc(100% + var(--spacing-sm));
- right: -10%;
- transform-origin: top right;
+ @include mix.media("screen") {
+ @include mix.dimensions(null, "2xs", "height") {
+ font-size: var(--font-size-sm);
+
+ .heading {
+ font-size: var(--font-size-lg);
+ }
+
+ .label {
+ font-size: var(--font-size-sm);
+ }
+ }
+ }
}
diff --git a/src/components/organisms/modals/settings-modal.test.tsx b/src/components/organisms/modals/settings-modal.test.tsx
index 44695d7..6291e54 100644
--- a/src/components/organisms/modals/settings-modal.test.tsx
+++ b/src/components/organisms/modals/settings-modal.test.tsx
@@ -1,8 +1,6 @@
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 />);
diff --git a/src/components/organisms/modals/settings-modal.tsx b/src/components/organisms/modals/settings-modal.tsx
index 0fac332..25d6f6f 100644
--- a/src/components/organisms/modals/settings-modal.tsx
+++ b/src/components/organisms/modals/settings-modal.tsx
@@ -10,9 +10,13 @@ import styles from './settings-modal.module.scss';
export type SettingsModalProps = {
/**
- * Set additional classnames to modal wrapper.
+ * Set additional classnames to the modal wrapper.
*/
className?: string;
+ /**
+ * Set additional classnames to the tooltip wrapper.
+ */
+ tooltipClassName?: string;
};
/**
@@ -20,7 +24,10 @@ export type SettingsModalProps = {
*
* Render a modal with settings options.
*/
-const SettingsModal: VFC<SettingsModalProps> = ({ className }) => {
+const SettingsModal: VFC<SettingsModalProps> = ({
+ className = '',
+ tooltipClassName = '',
+}) => {
const intl = useIntl();
const title = intl.formatMessage({
defaultMessage: 'Settings',
@@ -33,6 +40,7 @@ const SettingsModal: VFC<SettingsModalProps> = ({ className }) => {
title={title}
icon="cogs"
className={`${styles.wrapper} ${className}`}
+ headingClassName={styles.heading}
>
<Form onSubmit={() => null}>
<ThemeToggle labelClassName={styles.label} value={false} />
@@ -41,7 +49,7 @@ const SettingsModal: VFC<SettingsModalProps> = ({ className }) => {
<AckeeSelect
initialValue="full"
labelClassName={styles.label}
- tooltipClassName={styles.tooltip}
+ tooltipClassName={tooltipClassName}
/>
</Form>
</Modal>
diff --git a/src/components/organisms/toolbar/settings.module.scss b/src/components/organisms/toolbar/settings.module.scss
new file mode 100644
index 0000000..08c8cd4
--- /dev/null
+++ b/src/components/organisms/toolbar/settings.module.scss
@@ -0,0 +1,10 @@
+@use "@styles/abstracts/functions" as fun;
+@use "@styles/abstracts/mixins" as mix;
+
+.modal {
+ @include mix.media("screen") {
+ @include mix.dimensions("sm") {
+ width: 120%;
+ }
+ }
+}
diff --git a/src/components/organisms/toolbar/settings.stories.tsx b/src/components/organisms/toolbar/settings.stories.tsx
new file mode 100644
index 0000000..f01e772
--- /dev/null
+++ b/src/components/organisms/toolbar/settings.stories.tsx
@@ -0,0 +1,76 @@
+import { ComponentMeta, ComponentStory } from '@storybook/react';
+import { useState } from 'react';
+import { IntlProvider } from 'react-intl';
+import SettingsComponent from './settings';
+
+export default {
+ title: 'Organisms/Toolbar',
+ component: SettingsComponent,
+ argTypes: {
+ className: {
+ control: {
+ type: 'text',
+ },
+ description: 'Set additional classnames to the modal wrapper.',
+ table: {
+ category: 'Styles',
+ },
+ type: {
+ name: 'string',
+ required: false,
+ },
+ },
+ isActive: {
+ control: {
+ type: null,
+ },
+ description: 'Define the modal state: either opened or closed.',
+ type: {
+ name: 'boolean',
+ required: true,
+ },
+ },
+ setIsActive: {
+ control: {
+ type: null,
+ },
+ description: 'A callback function to update modal state.',
+ type: {
+ name: 'function',
+ 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 SettingsComponent>;
+
+const Template: ComponentStory<typeof SettingsComponent> = ({
+ isActive,
+ setIsActive: _setIsActive,
+ ...args
+}) => {
+ const [isOpen, setIsOpen] = useState<boolean>(isActive);
+
+ return (
+ <IntlProvider locale="en">
+ <SettingsComponent isActive={isOpen} setIsActive={setIsOpen} {...args} />
+ </IntlProvider>
+ );
+};
+
+export const Settings = Template.bind({});
+Settings.args = {
+ isActive: false,
+};
diff --git a/src/components/organisms/toolbar/settings.test.tsx b/src/components/organisms/toolbar/settings.test.tsx
new file mode 100644
index 0000000..96a32c9
--- /dev/null
+++ b/src/components/organisms/toolbar/settings.test.tsx
@@ -0,0 +1,18 @@
+import { render, screen } from '@test-utils';
+import Settings from './settings';
+
+describe('Settings', () => {
+ it('renders a button to open settings modal', () => {
+ render(<Settings isActive={false} setIsActive={() => null} />);
+ expect(
+ screen.getByRole('checkbox', { name: 'Open settings' })
+ ).toBeInTheDocument();
+ });
+
+ it('renders a button to close settings modal', () => {
+ render(<Settings isActive={true} setIsActive={() => null} />);
+ expect(
+ screen.getByRole('checkbox', { name: 'Close settings' })
+ ).toBeInTheDocument();
+ });
+});
diff --git a/src/components/organisms/toolbar/settings.tsx b/src/components/organisms/toolbar/settings.tsx
new file mode 100644
index 0000000..88539fb
--- /dev/null
+++ b/src/components/organisms/toolbar/settings.tsx
@@ -0,0 +1,72 @@
+import Checkbox, { CheckboxProps } from '@components/atoms/forms/checkbox';
+import Label from '@components/atoms/forms/label';
+import Cog from '@components/atoms/icons/cog';
+import { VFC } from 'react';
+import { useIntl } from 'react-intl';
+import SettingsModal from '../modals/settings-modal';
+import sharedStyles from './toolbar-items.module.scss';
+import settingsStyles from './settings.module.scss';
+
+export type SettingsProps = {
+ /**
+ * Set additional classnames to the modal wrapper.
+ */
+ className?: string;
+ /**
+ * The button state.
+ */
+ isActive: CheckboxProps['value'];
+ /**
+ * A callback function to handle button state.
+ */
+ setIsActive: CheckboxProps['setValue'];
+ /**
+ * Set additional classnames to the tooltip wrapper.
+ */
+ tooltipClassName?: string;
+};
+
+const Settings: VFC<SettingsProps> = ({
+ className = '',
+ isActive,
+ setIsActive,
+ tooltipClassName = '',
+}) => {
+ const intl = useIntl();
+ const label = isActive
+ ? intl.formatMessage({
+ defaultMessage: 'Close settings',
+ id: '+viX9b',
+ description: 'Settings: Close label',
+ })
+ : intl.formatMessage({
+ defaultMessage: 'Open settings',
+ id: 'QCW3cy',
+ description: 'Settings: Open label',
+ });
+
+ return (
+ <div className={`${sharedStyles.item} ${settingsStyles.item}`}>
+ <Checkbox
+ id="settings-button"
+ name="settings-button"
+ value={isActive}
+ setValue={setIsActive}
+ className={`${sharedStyles.checkbox} ${settingsStyles.checkbox}`}
+ />
+ <Label
+ htmlFor="settings-button"
+ aria-label={label}
+ className={`${sharedStyles.label} ${settingsStyles.label}`}
+ >
+ <Cog />
+ </Label>
+ <SettingsModal
+ className={`${sharedStyles.modal} ${settingsStyles.modal} ${className}`}
+ tooltipClassName={tooltipClassName}
+ />
+ </div>
+ );
+};
+
+export default Settings;