Storybook updates (#15848)

* updates

* updating doc

* Fixed broken documentation in Storybook stories.

* bring back a element

* md --> mdx

* c-* doc update

Co-authored-by: Nick Taylor <nick@dev.to>
This commit is contained in:
ludwiczakpawel 2022-01-14 11:06:23 +01:00 committed by GitHub
parent ea28093bbb
commit 086a53ba93
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
56 changed files with 160 additions and 632 deletions

View file

@ -25,7 +25,7 @@ class FocusedForm extends Component {
export default {
component: SearchForm,
title: 'App Components/Search/Search Form',
title: 'App Components/Search',
};
export const NoSearchTerm = () => <SearchForm {...commonProps} searchTerm="" />;

View file

@ -7,7 +7,7 @@ import {
select,
} from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions';
import notes from './buttons.md';
import notes from './buttons.mdx';
import { Button } from '@crayons';
import '../../storybook-utilities/designSystem.scss';
@ -20,7 +20,7 @@ const commonProps = {
};
export default {
title: 'Components/Buttons',
title: 'Deprecated/Buttons',
decorator: [withKnobs],
parameters: {
notes,

View file

@ -5,7 +5,7 @@ import CogIcon from '@images/cog.svg';
export default {
component: Button,
title: 'BETA/Buttons',
title: 'Components/Buttons',
parameters: {
docs: {
page: ButtonsDoc,

View file

@ -5,7 +5,7 @@ import CogIcon from '@images/cog.svg';
export default {
component: CTA,
title: 'BETA/Navigation/CTAs',
title: 'Components/Navigation/CTAs',
parameters: {
docs: {
page: CTAsDoc,

View file

@ -1,24 +1,29 @@
import { h } from 'preact';
import { withKnobs, text } from '@storybook/addon-knobs';
import './dropdown-css-helper.scss';
import notes from './dropdowns.md';
import { ButtonNew as Button, Dropdown } from '@crayons';
import notes from './dropdowns.mdx';
import { Dropdown, ButtonNew as Button } from '@crayons';
export default {
title: 'Components/Dropdowns',
decorators: [withKnobs],
parameters: { notes },
parameters: {
docs: {
page: notes,
},
},
};
export const Default = () => (
<div className="dropdown-trigger-container">
<Button id="storybook-dropdown-trigger" aria-haspopup="true">
<Button
id="storybook-dropdown-trigger"
className="dropdown-trigger"
aria-haspopup="true"
>
Click to trigger dropdown
</Button>
<Dropdown
triggerButtonId="storybook-dropdown-trigger"
dropdownContentId="storybook-dropdown"
className={text('className', 'mb-2')}
>
<p>
Hey, I&apos;m a dropdown content! Lorem ipsum dolor sit amet,

View file

@ -1,9 +1,13 @@
<mark>Please disregard generated HTML output in one of the tabs in the panel below. This one is a special snowflake for which you should use the below rails helper instead.</mark>
# Icons
This component is supposed to make it easy to add icons to your JSX code.
This component is supposed to make it easy to add icons to the user interface.
## How?
### JSX
You can pass an object as `src` prop:
```
@ -11,20 +15,42 @@ import Twitter from '@images/twitter.svg';
<Icon src={Twitter} />
```
Yes, we have an alias `@images` that should make it easier to access `/app/assets/images` folder.
Yes, we have an alias `@images` that should make it easier to access `/app/assets/images` folder while importing.
### Rails
For Rails world, we have a helper which injects our icons similarly:
```
crayons_icon_tag(file_name, css_class: nil, native: false, **opts)
```
Keep in mind there's no need to provide the folder path - the helper handles that.
#### Parameters:
- **`name`** (String|Symbol) - The icon name from `/app/assets/images` folder. The `.svg` file extensions will be added automatically if missing.
- **`css_class`** (String) - additional CSS classes.
- **`native`** (Boolean) - when set to true, icon will not inherit its parent's color.
- **`opts`** - additional keyword arguments to be passed through to the [`inline_svg_tag` helper](https://github.com/jamesmartin/inline_svg).
## Colors
If asset (SVG file) was exported correctly (see Rules section below) and `<Icon />` component was used correctly,
If asset (SVG file) was exported correctly (see Rules section below) and the component was used correctly,
icon should inherit some Crayons styling that will, for example, automatically apply container's color to the icon itself.
For example, icon will automatically inherit link color whenever it's placed inside a link element.
### Native colors
By adding `native` prop we tell icon to NOT inherit its parent color.
By adding `native` prop/parameter we tell icon to NOT inherit its parent color.
Instead it will keep whatever colors were defined in the SVG code.
This is helpful for branded icons that come with their own specific color (logos like Twitter, Facebook, etc.) or for multicolor icons.
```
JSX: <Icon src={Twitter} native />
Rails: <%= crayons_icon_tag("twitter", native: true) %>
```
## Rules
Most of the icons you would ever need should already be inside `/app/assets/images` folder. If you can't find one, ask your designer.

View file

@ -1,11 +1,11 @@
import { h } from 'preact';
import { Icon } from '..';
import IconsDoc from './Icons.mdx';
import CogIcon from '@images/twitter.svg';
import TwitterIcon from '@images/twitter.svg';
export default {
component: Icon,
title: 'BETA/Icons',
title: 'Components/Icons',
parameters: {
docs: {
page: IconsDoc,
@ -22,12 +22,12 @@ export default {
},
};
export const Default = (args) => <Icon src={CogIcon} {...args} />;
export const Default = (args) => <Icon src={TwitterIcon} {...args} />;
Default.args = {
native: false,
};
export const NativeColors = (args) => <Icon src={CogIcon} {...args} />;
export const NativeColors = (args) => <Icon src={TwitterIcon} {...args} />;
NativeColors.args = {
native: true,
};

View file

@ -1,11 +1,12 @@
import { h } from 'preact';
import '../../storybook-utilities/designSystem.scss';
import notes from './indicators.md';
import notes from './indicators.mdx';
export default {
title: 'Components/Indicators/HTML',
title: 'Components/Indicators',
parameters: {
notes,
docs: {
page: notes,
},
},
};

View file

@ -5,7 +5,7 @@ import CogIcon from '@images/cog.svg';
export default {
component: Link,
title: 'BETA/Navigation/Links',
title: 'Components/Navigation/Links',
parameters: {
docs: {
page: LinksDoc,

View file

@ -2,7 +2,7 @@ import { h } from 'preact';
import { MarkdownToolbar } from '@crayons';
export default {
title: 'App Components/MarkdownToolbar',
title: 'App Components/Markdown Toolbar',
};
export const Default = () => {

View file

@ -1,9 +1,9 @@
import { h, createRef, render } from 'preact';
import { MentionAutocompleteTextArea } from '../MentionAutocompleteTextArea';
import notes from './mention-autocomplete.md';
import notes from './mention-autocomplete.mdx';
export default {
title: 'App Components/MentionAutocompleteTextArea',
title: 'App Components/Mention Autocomplete Textarea',
parameters: { notes },
};

View file

@ -1,11 +1,15 @@
import { h } from 'preact';
import { useState } from 'preact/hooks';
import notes from './drawers.md';
import { MobileDrawer, Button } from '@crayons';
import Notes from './drawers.mdx';
import { MobileDrawer, ButtonNew as Button } from '@crayons';
export default {
title: 'Components/MobileDrawer',
parameters: { notes },
title: 'BETA/MobileDrawer',
parameters: {
docs: {
page: Notes,
},
},
};
export const Default = () => {

View file

@ -1,4 +1,4 @@
## MobileDrawers
# Mobile Drawers
MobileDrawers are intended to be used in small screen sizes only (i.e. for
mobile UI variants), and always appear from the bottom of the viewport. The
@ -7,7 +7,7 @@ button which triggers the MobileDrawer may be located anywhere on the page.
MobileDrawer content should always include at least one interactive item (e.g.
button, link) to make sure focus may be transferred to the new content.
### MobileDrawer accessibility
## MobileDrawer accessibility
The MobileDrawer is essentially a
[modal dialog](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/dialog_role).

View file

@ -1,38 +1,53 @@
import { h } from 'preact';
import { useState } from 'preact/hooks';
import { withKnobs, text, boolean, select } from '@storybook/addon-knobs';
import notes from './modals.md';
import { Modal, Button } from '@crayons';
import '../../storybook-utilities/designSystem.scss';
import notes from './modals.mdx';
import { Modal, ButtonNew as Button } from '@crayons';
export default {
title: 'Components/Modals',
decorator: [withKnobs],
parameters: { notes },
parameters: {
docs: {
page: notes,
},
},
argTypes: {
size: {
control: {
type: 'select',
options: {
default: 'default',
small: 's',
medium: 'm',
},
},
table: {
defaultValue: { summary: 'default' },
},
},
overlay: {
table: {
defaultValue: { summary: true },
},
},
title: {
control: {
type: 'text',
},
table: {
defaultValue: { summary: 'Modal title' },
},
},
},
};
export const Default = () => {
export const Default = (args) => {
const [isModalOpen, setIsModalOpen] = useState(false);
return (
<div>
<Button onClick={() => setIsModalOpen(true)}>Open modal</Button>
{isModalOpen && (
<Modal
onClose={() => setIsModalOpen(false)}
size={select(
'size',
{
Small: 's',
Medium: 'm',
Default: 'default',
},
'default',
)}
className={text('className')}
title={text('title', 'This is my Modal title')}
overlay={boolean('overlay', true)}
>
<Modal onClose={() => setIsModalOpen(false)} {...args}>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse
odio est, ultricies vel euismod ut, fringilla quis tellus. Sed at
@ -44,6 +59,8 @@ export const Default = () => {
);
};
Default.story = {
name: 'Modals',
Default.args = {
size: 'default',
title: 'My modal',
overlay: true,
};

View file

@ -1,10 +1,13 @@
import { h } from 'preact';
import '../../storybook-utilities/designSystem.scss';
import notes from './notices.md';
import notes from './notices.mdx';
export default {
title: 'Components/Notices/HTML',
parameters: { notes },
title: 'Components/Notices',
parameters: {
docs: {
page: notes,
},
},
};
export const Default = () => (

View file

@ -1,11 +1,12 @@
import { h } from 'preact';
import '../../../storybook-utilities/designSystem.scss';
import notes from '../../avatars-and-logos.md';
import notes from '../../avatars-and-logos.mdx';
export default {
title: 'Components/Avatars & Logos/Avatars/HTML',
title: 'Components/Avatars & Logos/Avatars',
parameters: {
notes,
docs: {
page: notes,
},
},
};

View file

@ -1,10 +1,13 @@
import { h } from 'preact';
import '../../../storybook-utilities/designSystem.scss';
import notes from '../../avatars-and-logos.md';
import notes from '../../avatars-and-logos.mdx';
export default {
title: 'Components/Avatars & Logos/Logos/HTML',
parameters: { notes },
title: 'Components/Avatars & Logos/Logos',
parameters: {
docs: {
page: notes,
},
},
};
export const Default = () => (

View file

@ -1,10 +1,10 @@
import { h } from 'preact';
import { Fieldset } from '../../../storybook-utilities/Fieldset';
import '../../../storybook-utilities/designSystem.scss';
import notes from '../../form-elements.md';
import notes from '../../form-elements.mdx';
export default {
title: 'Components/Form Components/Checkbox/HTML',
title: 'Components/Form Elements/Checkbox',
parameters: { notes },
};

View file

@ -1,10 +1,10 @@
import { h } from 'preact';
import { action } from '@storybook/addon-actions';
import notes from '../../form-elements.md';
import notes from '../../form-elements.mdx';
import { FormField, RadioButton } from '@crayons';
export default {
title: 'Components/Form Components/Form Field',
title: 'Components/Form Elements/Form Field',
parameters: { notes },
};

View file

@ -1,11 +1,11 @@
import { h } from 'preact';
import { withKnobs, text, boolean } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions';
import notes from '../../form-elements.md';
import notes from '../../form-elements.mdx';
import { RadioButton } from '@crayons';
export default {
title: 'Components/Form Components/Radio Button',
title: 'Components/Form Elements/Radio Button',
decorators: [withKnobs],
parameters: { notes },
};

View file

@ -2,7 +2,7 @@ import { h } from 'preact';
import { Fieldset } from '../../../storybook-utilities/Fieldset';
import '../../../storybook-utilities/designSystem.scss';
export default { title: 'Components/Form Components/Radio Button/HTML' };
export default { title: 'Components/Form Elements/Radio Button/HTML' };
export const Default = () => (
<input type="radio" name="n1" className="crayons-radio" />

View file

@ -12,7 +12,7 @@ export const Select = () => (
export default {
component: Select,
title: 'Components/Select',
title: 'Components/Form Elements/Select',
};
export const Default = () => {

View file

@ -3,7 +3,7 @@ import { h } from 'preact';
import '../../../storybook-utilities/designSystem.scss';
export default {
title: 'Components/Form Components/Multiline Text Field/HTML',
title: 'Components/Form Elements/Multiline Text Field',
};
export const Default = () => (

View file

@ -2,7 +2,7 @@ import { h } from 'preact';
import '../../../storybook-utilities/designSystem.scss';
export default { title: 'Components/Form Components/Text Field/HTML' };
export default { title: 'Components/Form Elements/Text Field' };
export const Default = () => (
<input

View file

@ -19,40 +19,44 @@ Preact.
The entire design system uses the [BEM](http://getbem.com/naming) methodology
for naming CSS classes. Even Preact components under the hood use it.
### `crayons-*`
### `crayons-*` or `c-*`
Crayons is the name of our design system. All Crayons components use the
`crayons-` prefix. It's useful because we can easily identify what **IS** and
`crayons-` or `c-` prefix. It's useful because we can easily identify what **IS** and
what **IS NOT** a Crayons component. It's also practical because Crayons was
implemented when we already had tons of other frontend classes in the codebase.
It prevents overwriting styles by other CSS and it's very unlikely someone has
ever created a `.crayons-btn` style BUT it's very likely someone has created
ever created a `.c-btn` style BUT it's very likely someone has created
`.btn` style...
`crayons-*` prefix will eventually be superseded by the `c-*` prefix. The `c-` prefix
is just shorter, faster to type and it keep the markup a tiny bit cleaner. Plus we save some bytes :).
## HTML & CSS Components
You'll need to copy piece of html code responsible for rendering a component and
that's it. Imagine a simple button component. The code below will render a
**primary button** with specific styling:
`<button class="crayons-btn">Hello</button>`
`<button class="c-btn c-btn--primary">Hello</button>`
Crayons offers different variants for a button. A button can be one of the
following variants: primary, secondary, outlined, danger, ghost, with icon, and
following variants: default, primary, secondary, with icon, and
so on. All of the components and its variations are described in the Components
section.
section in the Storybook.
Imagine you need a small (size **s** ), **secondary** type. In this case you
will need to apply specific modifier class for that:
`<button class="crayons-btn crayons-btn--secondary crayons-btn--s">Hello</button>`
`<button class="c-btn c-btn--primary c-btn--destructive">Hello</button>`
## Preact Components
The same button above that was created with pure HTML using modifying classes is
also a Preact component.
`import { Button } from '@crayons'; //... <Button size="s" variant="secondary">Hello<Button>`
```
import { Button } from '@crayons';
...
<Button variant="primary" destructive>Hello<Button>
```
To import a design system component, e.g. `<Button />`, import it from
`@crayons`. Instead of modifying CSS classes, modify props, e.g.

View file

@ -31,8 +31,7 @@ when we use SCSS variables. It's just easier.
### Themes
Forem support multiple themes so you should always test your work against all
themes. We have a file with all color variables and each theme has its own too.
Forem support two themes so you should always test your work against both.
- Default theme: `app/assets/stylesheets/config/_colors.scss`
@ -58,8 +57,6 @@ You can access all of the SCSS files in `app/assets/stylesheets` folder.
|`/config/_generator.scss`| Contains SCSS mixins generating *all* of our utility classes.
|`/config/_import.scss`| Contains helpers for SCSS as well as media breakpoints variables.
|`/config/_variables.scss`| Contains all CSS native variables.
|—|—|
|`/themes`| Contains color declarations for other themes.
There are other folders and top level files that we use, but they might be deprecated in the future. They are:

View file

@ -9,5 +9,4 @@ export * from '@crayons/Icons';
export * from '@crayons/Modal';
export * from '@crayons/Spinner';
export * from '@crayons/MobileDrawer';
export * from '@crayons/navigation';
export * from '@crayons/MarkdownToolbar';

View file

@ -1,115 +0,0 @@
import { h, Fragment } from 'preact';
import { useState } from 'preact/hooks';
import PropTypes from 'prop-types';
import { MobileDrawer } from '@crayons/MobileDrawer';
import { Button } from '@crayons/Button';
const OverflowIcon = () => (
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M7 12a2 2 0 11-4 0 2 2 0 014 0zm7 0a2 2 0 11-4 0 2 2 0 014 0zm5 2a2 2 0 100-4 2 2 0 000 4z"
/>
</svg>
);
const CheckIcon = () => (
<svg
aria-hidden="true"
className="check-icon"
fill="currentColor"
width="24"
height="24"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M10 15.172l9.192-9.193 1.415 1.414L10 18l-6.364-6.364 1.414-1.414 4.95 4.95z" />
</svg>
);
/**
* Renders a page heading with a button which activates a <MobileDrawer /> with a list of the given navigation links.
*
* @param {object} props
* @param {number} headingLevel The level of heading to render as the page title (e.g. 1-6)
* @param {string} navigationTitle The title to be used for the navigation element (e.g. 'Feed timeframes')
* @param {Array} navigationLinks An array of navigationLink objects to display
*
* @example
* <MobileDrawerNavigation
* headingLevel={2}
* navigationTitle="Feed options"
* navigationLinks={links} />
*/
export const MobileDrawerNavigation = ({
headingLevel,
navigationTitle,
navigationLinks,
}) => {
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
const currentPage = navigationLinks.find((item) => item.isCurrentPage);
const Heading = `h${headingLevel}`;
return (
<Fragment>
<div className="flex justify-between">
<Heading>{currentPage.displayName}</Heading>
<Button
aria-label={navigationTitle}
icon={OverflowIcon}
size="s"
contentType="icon"
variant="ghost"
onClick={() => setIsDrawerOpen(true)}
/>
</div>
{isDrawerOpen && (
<MobileDrawer
title={navigationTitle}
onClose={() => setIsDrawerOpen(false)}
>
<nav aria-label={navigationTitle} className="drawer-navigation">
<ul className="list-none">
{navigationLinks.map((linkDetails) => {
const { url, isCurrentPage, displayName } = linkDetails;
return (
<li
key={`link-${url}`}
className="drawer-navigation__item py-2"
>
<a href={url} aria-current={isCurrentPage ? 'page' : null}>
{displayName}
</a>
<CheckIcon />
</li>
);
})}
</ul>
</nav>
<Button
variant="secondary"
className="w-100 mt-4"
onClick={() => setIsDrawerOpen(false)}
>
Cancel
</Button>
</MobileDrawer>
)}
</Fragment>
);
};
MobileDrawerNavigation.propTypes = {
headingLevel: PropTypes.oneOf([1, 2, 3, 4, 5, 6]).isRequired,
navigationTitle: PropTypes.string.isRequired,
navigationLinks: PropTypes.arrayOf(
PropTypes.shape({
url: PropTypes.string,
isCurrentPage: PropTypes.bool,
displayName: PropTypes.string,
}),
).isRequired,
};

View file

@ -1,54 +0,0 @@
import { h, Fragment } from 'preact';
import notes from './mobileDrawerNavigation.md';
import { MobileDrawerNavigation } from '@crayons';
export default {
title: 'App Components/MobileDrawerNavigation',
parameters: { notes },
};
export const Default = () => {
const { href, hash } = window.location;
const indexOfHash = href.indexOf(hash) || href.length;
const baseStoryUrl = href.substr(0, indexOfHash);
const links = [
{
url: baseStoryUrl,
displayName: 'Drawer Navigation',
isCurrentPage: href === baseStoryUrl,
},
{
url: `${baseStoryUrl}/#2`,
displayName: 'Example link 2',
isCurrentPage: `#2` === hash,
},
{
url: `${baseStoryUrl}/#3`,
displayName: 'Example link 3',
isCurrentPage: `#3` === hash,
},
{
url: `${baseStoryUrl}/#4`,
displayName: 'Example link 4',
isCurrentPage: `#4` === hash,
},
];
return (
<Fragment>
<MobileDrawerNavigation
headingLevel={2}
navigationTitle="Example MobileDrawerNavigation"
navigationLinks={links}
/>
<p className="my-4">
Click on the button to view and select navigation links.
</p>
</Fragment>
);
};
Default.story = {
name: 'MobileDrawerNavigation',
};

View file

@ -1,139 +0,0 @@
/* eslint-disable jsx-a11y/no-static-element-interactions */
/* eslint-disable jsx-a11y/click-events-have-key-events */
// Disabled for the file due to issues disabling for individual JSX lines.
// These are disabled to allow the "click outside to close" functionality
import { h } from 'preact';
import { useState, useEffect } from 'preact/hooks';
import notes from './mobileDrawerNavigation.md';
export default {
title: 'App Components/MobileDrawerNavigation/HTML',
parameters: { notes },
};
export const Default = () => {
const [isNavOpen, setIsNavOpen] = useState(false);
const { href, hash } = window.location;
const indexOfHash = href.indexOf(hash) || href.length;
const baseStoryUrl = href.substr(0, indexOfHash);
useEffect(() => {
const keyupListener = (e) => {
if (e.key === 'Escape') {
setIsNavOpen(false);
}
};
document.addEventListener('keyup', keyupListener);
return () => document.removeEventListener('keyup', keyupListener);
}, []);
return (
<div>
<div class="flex justify-between">
<h1>Link 1</h1>
<button
onClick={() => setIsNavOpen(true)}
aria-label="Test navigation"
class="crayons-btn crayons-btn--ghost crayons-btn--s crayons-btn--icon"
type="button"
>
<svg height="24" width="24" xmlns="http://www.w3.org/2000/svg">
<path
clip-rule="evenodd"
d="M7 12a2 2 0 11-4 0 2 2 0 014 0zm7 0a2 2 0 11-4 0 2 2 0 014 0zm5 2a2 2 0 100-4 2 2 0 000 4z"
fill-rule="evenodd"
/>
</svg>
</button>
</div>
{isNavOpen && (
<div class="crayons-mobile-drawer">
<div
class="crayons-mobile-drawer__overlay"
onClick={() => setIsNavOpen(false)}
/>
<div
aria-label="Test navigation"
aria-modal="true"
class="crayons-mobile-drawer__content"
role="dialog"
>
<nav aria-label="Test navigation" class="drawer-navigation">
<ul class="list-none">
<li class="drawer-navigation__item py-2">
<a
aria-current={href === baseStoryUrl ? 'page' : null}
href={baseStoryUrl}
>
Link 1
</a>
<svg
aria-hidden="true"
class="check-icon"
fill="currentColor"
height="24"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M10 15.172l9.192-9.193 1.415 1.414L10 18l-6.364-6.364 1.414-1.414 4.95 4.95z" />
</svg>
</li>
<li class="drawer-navigation__item py-2">
<a
href={`${baseStoryUrl}/#2`}
aria-current={`#2` === hash ? 'page' : null}
>
Link 2
</a>
<svg
aria-hidden="true"
class="check-icon"
fill="currentColor"
height="24"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M10 15.172l9.192-9.193 1.415 1.414L10 18l-6.364-6.364 1.414-1.414 4.95 4.95z" />
</svg>
</li>
<li class="drawer-navigation__item py-2">
<a
href={`${baseStoryUrl}/#3`}
aria-current={`#3` === hash ? 'page' : null}
>
Link 3
</a>
<svg
aria-hidden="true"
class="check-icon"
fill="currentColor"
height="24"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M10 15.172l9.192-9.193 1.415 1.414L10 18l-6.364-6.364 1.414-1.414 4.95 4.95z" />
</svg>
</li>
</ul>
</nav>
<button
class="crayons-btn crayons-btn--secondary w-100 mt-4"
type="button"
onClick={() => setIsNavOpen(false)}
>
Cancel
</button>
</div>
</div>
)}
</div>
);
};
Default.story = {
name: 'MobileDrawerNavigation',
};

View file

@ -1,29 +0,0 @@
## MobileDrawerNavigation
The MobileDrawerNavigation component is intended to be used on small
(mobile-sized) screens only. It can be used as an alternative to the larger
navigation tab component.
The component is responsible for showing:
- The heading of the currently selected page
- A navigation dialog with the given links
This component is best placed at the top of a page. The dialog utilizes
`<MobileDrawer />`, and will appear from the bottom of the screen.
### MobileDrawerNavigation Accessibility
The MobileDrawerNavigation component requires a `navigationTitle` prop which
will be used for:
- The activating button for the navigation dialog
- The label of the navigation dialog
- The label of the navigation element containing the links
This helps ensure accessible element names are surfaced to all users.
The component also requires a `headingLevel` prop which is used to determine the
HTML element used for the displayed current page title (e.g. `1` will render an
`h1`). Appropriate consideration should be given to which heading level is
semantically correct for the location the component is rendered.

View file

@ -1,85 +0,0 @@
import { h } from 'preact';
import { axe } from 'jest-axe';
import '@testing-library/jest-dom';
import { render, waitFor } from '@testing-library/preact';
import { MobileDrawerNavigation } from '../MobileDrawerNavigation';
describe('<MobileDrawerNavigation />', () => {
const testLinks = [
{ url: '/#1', displayName: 'Link 1', isCurrentPage: true },
{ url: '/#2', displayName: 'Link 2', isCurrentPage: false },
{ url: '/#3', displayName: 'Link 3', isCurrentPage: false },
];
it('should have no a11y violations when closed', async () => {
const { container } = render(
<MobileDrawerNavigation
navigationTitle="Test navigation"
headingLevel={1}
navigationLinks={testLinks}
/>,
);
const results = await axe(container);
expect(results).toHaveNoViolations();
});
it('should have no a11y violations when open', async () => {
const { container, getByRole } = render(
<MobileDrawerNavigation
navigationTitle="Test navigation"
headingLevel={1}
navigationLinks={testLinks}
/>,
);
getByRole('button', { name: 'Test navigation' }).click();
await waitFor(() => getByRole('navigation', { name: 'Test navigation' }));
const results = await axe(container);
expect(results).toHaveNoViolations();
});
it('should render a heading with a button when closed', () => {
const { container } = render(
<MobileDrawerNavigation
navigationTitle="Test navigation"
headingLevel={1}
navigationLinks={testLinks}
/>,
);
expect(container.innerHTML).toMatchSnapshot();
});
it('should render a navigation with a checkmark for current page when open', async () => {
const { container, getByRole } = render(
<MobileDrawerNavigation
navigationTitle="Test navigation"
headingLevel={1}
navigationLinks={testLinks}
/>,
);
getByRole('button', { name: 'Test navigation' }).click();
await waitFor(() => getByRole('navigation', { name: 'Test navigation' }));
expect(container.innerHTML).toMatchSnapshot();
});
it('should render all links', async () => {
const { getByRole } = render(
<MobileDrawerNavigation
navigationTitle="Test navigation"
headingLevel={1}
navigationLinks={testLinks}
/>,
);
getByRole('button', { name: 'Test navigation' }).click();
await waitFor(() => getByRole('navigation', { name: 'Test navigation' }));
expect(getByRole('link', { name: 'Link 1' })).toBeInTheDocument();
expect(getByRole('link', { name: 'Link 2' })).toBeInTheDocument();
expect(getByRole('link', { name: 'Link 3' })).toBeInTheDocument();
});
});

View file

@ -1,5 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<MobileDrawerNavigation /> should render a heading with a button when closed 1`] = `"<div class=\\"flex justify-between\\"><h1>Link 1</h1><button class=\\"crayons-btn crayons-btn--ghost crayons-btn--s crayons-btn--icon\\" type=\\"button\\" aria-label=\\"Test navigation\\"><svg width=\\"24\\" height=\\"24\\" xmlns=\\"http://www.w3.org/2000/svg\\"><path fill-rule=\\"evenodd\\" clip-rule=\\"evenodd\\" d=\\"M7 12a2 2 0 11-4 0 2 2 0 014 0zm7 0a2 2 0 11-4 0 2 2 0 014 0zm5 2a2 2 0 100-4 2 2 0 000 4z\\"></path></svg></button></div>"`;
exports[`<MobileDrawerNavigation /> should render a navigation with a checkmark for current page when open 1`] = `"<div class=\\"flex justify-between\\"><h1>Link 1</h1><button class=\\"crayons-btn crayons-btn--ghost crayons-btn--s crayons-btn--icon\\" type=\\"button\\" aria-label=\\"Test navigation\\"><svg width=\\"24\\" height=\\"24\\" xmlns=\\"http://www.w3.org/2000/svg\\"><path fill-rule=\\"evenodd\\" clip-rule=\\"evenodd\\" d=\\"M7 12a2 2 0 11-4 0 2 2 0 014 0zm7 0a2 2 0 11-4 0 2 2 0 014 0zm5 2a2 2 0 100-4 2 2 0 000 4z\\"></path></svg></button></div><div class=\\"crayons-mobile-drawer\\"><div class=\\"crayons-mobile-drawer__overlay\\"></div><div class=\\"crayons-mobile-drawer__content\\" role=\\"dialog\\" aria-modal=\\"true\\" aria-label=\\"Test navigation\\"><nav aria-label=\\"Test navigation\\" class=\\"drawer-navigation\\"><ul class=\\"list-none\\"><li class=\\"drawer-navigation__item py-2\\"><a href=\\"/#1\\" aria-current=\\"page\\">Link 1</a><svg aria-hidden=\\"true\\" class=\\"check-icon\\" fill=\\"currentColor\\" width=\\"24\\" height=\\"24\\" viewBox=\\"0 0 24 24\\" xmlns=\\"http://www.w3.org/2000/svg\\"><path d=\\"M10 15.172l9.192-9.193 1.415 1.414L10 18l-6.364-6.364 1.414-1.414 4.95 4.95z\\"></path></svg></li><li class=\\"drawer-navigation__item py-2\\"><a href=\\"/#2\\">Link 2</a><svg aria-hidden=\\"true\\" class=\\"check-icon\\" fill=\\"currentColor\\" width=\\"24\\" height=\\"24\\" viewBox=\\"0 0 24 24\\" xmlns=\\"http://www.w3.org/2000/svg\\"><path d=\\"M10 15.172l9.192-9.193 1.415 1.414L10 18l-6.364-6.364 1.414-1.414 4.95 4.95z\\"></path></svg></li><li class=\\"drawer-navigation__item py-2\\"><a href=\\"/#3\\">Link 3</a><svg aria-hidden=\\"true\\" class=\\"check-icon\\" fill=\\"currentColor\\" width=\\"24\\" height=\\"24\\" viewBox=\\"0 0 24 24\\" xmlns=\\"http://www.w3.org/2000/svg\\"><path d=\\"M10 15.172l9.192-9.193 1.415 1.414L10 18l-6.364-6.364 1.414-1.414 4.95 4.95z\\"></path></svg></li></ul></nav><button class=\\"crayons-btn crayons-btn--secondary w-100 mt-4\\" type=\\"button\\">Cancel</button></div></div>"`;

View file

@ -1,7 +1,7 @@
import { h } from 'preact';
import '../../../storybook-utilities/designSystem.scss';
import { useState } from 'preact/hooks';
import notes from './navigation-tab.md';
import notes from './navigation-tab.mdx';
export default {
title: 'Components/Navigation/Tabs/HTML',

View file

@ -1 +0,0 @@
export * from './MobileDrawerNavigation/MobileDrawerNavigation';

View file

@ -1,4 +0,0 @@
## Navigation: Main nav
Used as main nav in left sidebar or dropdowns...
Can contain icons.

View file

@ -1,51 +0,0 @@
import { h } from 'preact';
import '../../../storybook-utilities/designSystem.scss';
import notes from './main-navigation.md';
export default {
title: 'Components/Navigation/Main Navigation/HTML',
parameters: { notes },
};
export const Default = () => (
<div className="p-6 bg-smoke-10">
<a href="/" className="crayons-nav-block crayons-nav-block--current">
<span className="crayons-icon" role="img" aria-label="home">
🏡
</span>
Home
</a>
<a href="/" className="crayons-nav-block">
<span className="crayons-icon" role="img" aria-label="Podcasts">
📻
</span>
Podcasts
</a>
<a href="/" className="crayons-nav-block">
<span className="crayons-icon" role="img" aria-label="Tags">
🏷
</span>
Tags
</a>
<a href="/" className="crayons-nav-block">
<span className="crayons-icon" role="img" aria-label="Listings">
📑
</span>
Listings
<span className="crayons-indicator">3</span>
</a>
<a href="/" className="crayons-nav-block">
<span className="crayons-icon" role="img" aria-label="Code of Conduct">
👍
</span>
Code of Conduct
</a>
<a href="/" className="crayons-nav-block crayons-nav-block--indented">
More...
</a>
</div>
);
Default.story = {
name: 'default',
};

View file

@ -3,7 +3,7 @@ import { h } from 'preact';
import '../../storybook-utilities/designSystem.scss';
import './typography.scss';
import notes from './typography.md';
import notes from './typography.mdx';
export default {
title: 'Fundamentals/Typography/1_Main',

View file

@ -3,7 +3,7 @@ import { h } from 'preact';
import '../../storybook-utilities/designSystem.scss';
import './typography.scss';
import notes from './accented-typography.md';
import notes from './accented-typography.mdx';
export default {
title: 'Fundamentals/Typography/2_Accent',

View file

@ -1,15 +0,0 @@
import { h } from 'preact';
export const CogIcon = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
role="img"
aria-labelledby="ai2ols8ka2ohfp0z568lj68ic2du21s"
className="crayons-icon"
>
<title id="ai2ols8ka2ohfp0z568lj68ic2du21s">Preferences</title>
<path d="M12 1l9.5 5.5v11L12 23l-9.5-5.5v-11L12 1zm0 2.311L4.5 7.653v8.694l7.5 4.342 7.5-4.342V7.653L12 3.311zM12 16a4 4 0 110-8 4 4 0 010 8zm0-2a2 2 0 100-4 2 2 0 000 4z" />
</svg>
);

View file

@ -1,12 +0,0 @@
import { h } from 'preact';
import { CogIcon } from '../CogIcon';
export default {
title: 'Components/Icons',
};
export const Default = () => <CogIcon />;
Default.story = {
name: 'cog icon',
};

View file

@ -1,18 +0,0 @@
import { h } from 'preact';
import { render } from '@testing-library/preact';
import { axe } from 'jest-axe';
import { CogIcon } from '../CogIcon';
describe('<CommentSubscription />', () => {
it('should have no a11y violations', async () => {
const { container } = render(<CogIcon />);
const results = await axe(container);
expect(results).toHaveNoViolations();
});
it('should render', () => {
const { container } = render(<CogIcon />);
expect(container.innerHTML).toMatchSnapshot();
});
});

View file

@ -1,3 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<CommentSubscription /> should render 1`] = `"<svg xmlns=\\"http://www.w3.org/2000/svg\\" width=\\"24\\" height=\\"24\\" role=\\"img\\" aria-labelledby=\\"ai2ols8ka2ohfp0z568lj68ic2du21s\\" class=\\"crayons-icon\\"><title id=\\"ai2ols8ka2ohfp0z568lj68ic2du21s\\">Preferences</title><path d=\\"M12 1l9.5 5.5v11L12 23l-9.5-5.5v-11L12 1zm0 2.311L4.5 7.653v8.694l7.5 4.342 7.5-4.342V7.653L12 3.311zM12 16a4 4 0 110-8 4 4 0 010 8zm0-2a2 2 0 100-4 2 2 0 000 4z\\"></path></svg>"`;

View file

@ -1 +0,0 @@
export * from './CogIcon';

View file

@ -2,7 +2,7 @@ import { h } from 'preact';
import { Meta } from '@storybook/addon-docs/blocks';
<Meta title="Components/Media Queries" />
<Meta title="Fundamentals/Media Queries" />
# Media Queries