Skip to content

Commit

Permalink
Storybook/Button documentation (#19298)
Browse files Browse the repository at this point in the history
* Button docs

* Change files

* use @fluentui/react-icons

* styling of stories

* use variables for repeated styles

* Update packages/react-button/.storybook/preview.js

Co-authored-by: Martin Hochel <[email protected]>

* Update preview.js

* Update preview.js

* Update preview.js

* fix object spread

* remove unused tmp-icons

* move description to a separate file

* code style

* add Markdown typing for typescript

* add displayName to satisfy a lint rule

Co-authored-by: Martin Hochel <[email protected]>
  • Loading branch information
PeterDraex and Hotell authored Aug 23, 2021
1 parent d5d6048 commit 0352049
Show file tree
Hide file tree
Showing 9 changed files with 234 additions and 121 deletions.
5 changes: 5 additions & 0 deletions .storybook/preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,9 @@ export const parameters = {
disable: true,
expanded: true,
},
docs: {
source: {
excludeDecorators: true,
},
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "none",
"comment": "Button docs",
"packageName": "@fluentui/react-button",
"email": "[email protected]",
"dependentChangeType": "none"
}
1 change: 1 addition & 0 deletions packages/react-button/.storybook/preview.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as rootPreview from '../../../.storybook/preview';

export const decorators = [...rootPreview.decorators];
export const parameters = { ...rootPreview.parameters };
118 changes: 0 additions & 118 deletions packages/react-button/src/Button.stories.tsx

This file was deleted.

184 changes: 184 additions & 0 deletions packages/react-button/src/components/Button/Button.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
import * as React from 'react';
import { Button, ButtonProps } from '../../Button';
import { Meta } from '@storybook/react';
import { CalendarMonth24Regular } from '@fluentui/react-icons';
import descriptionMd from './ButtonDescription.md';
import bestPracticesMd from './ButtonBestPractices.md';

export const Default = (props: ButtonProps) => <Button {...props}>Button</Button>;

export const Emphasis = () => (
<>
<Button primary>Primary button</Button>
<Button>Default button</Button>
<Button outline>Outline button</Button>
<Button subtle>Subtle button</Button>
<Button transparent>Transparent button</Button>
</>
);
Emphasis.parameters = {
docs: {
description: {
story:
'- `primary` button is used for the most important action on the page or in a view\n' +
'- `default` button is used for subordinate actions\n' +
'- `outline` has no background styling and is emphasized through the styling of its content and borders\n' +
'- `transparent` has no background or border styling and is just emphasized through its content styling\n' +
'- `subtle` button blends into its background and becomes less emphasized\n',
},
},
};

export const ButtonWithIcon = () => (
<>
<Button icon={<CalendarMonth24Regular />}>Text</Button>
<Button icon={<CalendarMonth24Regular />} iconPosition="after">
Text
</Button>
<Button icon={<CalendarMonth24Regular />} />
</>
);
ButtonWithIcon.parameters = {
docs: {
description: {
story:
'Button has an `icon` slot that, if specified, renders an icon either `before` or `after` the children, ' +
'as specified by the `iconPosition` prop.',
},
},
};

export const CircularButton = () => (
<>
<Button circular>Button</Button>
<Button circular outline icon={<CalendarMonth24Regular />} />
<Button circular subtle icon={<CalendarMonth24Regular />} />
<Button circular transparent icon={<CalendarMonth24Regular />} />
</>
);
CircularButton.parameters = {
docs: {
description: {
story: 'A button can have completely rounded corners.',
},
},
};

export const ButtonSize = () => {
const groupStyles: React.CSSProperties = { display: 'flex', flexWrap: 'wrap', gap: '0.5em' };
const headerStyles: React.CSSProperties = { width: '100%', margin: 0 };
return (
<>
<div style={groupStyles}>
<h4 style={headerStyles}>small</h4>
<Button size="small">Text</Button>
<Button size="small" icon={<CalendarMonth24Regular />}>
Text
</Button>
<Button size="small" icon={<CalendarMonth24Regular />} />
</div>
<div style={groupStyles}>
<h4 style={headerStyles}>medium</h4>
<Button>Text</Button>
<Button icon={<CalendarMonth24Regular />}>Text</Button>
<Button icon={<CalendarMonth24Regular />} />
</div>
<div style={groupStyles}>
<h4 style={headerStyles}>large</h4>
<Button size="large">Text</Button>
<Button size="large" icon={<CalendarMonth24Regular />}>
Text
</Button>
<Button size="large" icon={<CalendarMonth24Regular />} />
</div>
</>
);
};
ButtonSize.parameters = {
docs: {
description: {
story: 'A button supports `small`, `medium` and `large` size. Default size is `medium`.',
},
},
};

export const BlockButton = () => (
<>
<Button block>Block button</Button>
</>
);
BlockButton.parameters = {
docs: {
description: {
story: 'A button can fill the width of its container.',
},
},
};

export const DisabledButton = () => {
const groupStyles: React.CSSProperties = { display: 'flex', flexWrap: 'wrap', gap: '0.5em' };

return (
<>
<div style={groupStyles}>
<Button>Default</Button>
<Button disabled>Disabled</Button>
<Button disabledFocusable>Disabled focusable</Button>
</div>
<div style={groupStyles}>
<Button primary icon={<CalendarMonth24Regular />}>
Primary
</Button>
<Button primary disabled icon={<CalendarMonth24Regular />}>
Primary disabled
</Button>
<Button primary disabledFocusable>
Primary disabled focusable
</Button>
</div>
</>
);
};
DisabledButton.parameters = {
docs: {
description: {
story: `A button can be \`disabled\` or \`disabledFocusable\`.
\`disabledFocusable\` is used in scenarios where it is important to keep a consistent tab order
for screen reader and keyboard users. The primary example of this pattern is when
the disabled button is in a menu or a commandbar and is seldom used for standalone buttons.`,
},
},
};

export const ButtonWithLongText = () => (
<>
<Button>Text</Button>
<Button>Text truncates after it hits the max width token value</Button>
</>
);
ButtonWithLongText.parameters = {
docs: {
description: {
story: 'Text truncates after it hits the max width theme token value.',
},
},
};

export default {
title: 'Components/Button',
component: Button,
parameters: {
docs: {
description: {
component: [descriptionMd, bestPracticesMd].join('\n'),
},
},
},
decorators: [
Story => (
<div style={{ display: 'flex', justifyContent: 'space-evenly' }}>
<Story />
</div>
),
],
} as Meta;
4 changes: 1 addition & 3 deletions packages/react-button/src/components/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import { renderButton } from './renderButton';
import { useButtonStyles } from './useButtonStyles';

/**
* Define a styled Button, using the `useButton` hook.
* {@docCategory Button}
* Buttons give people a way to trigger an action.
*/
export const Button: React.FunctionComponent<ButtonProps & React.RefAttributes<HTMLElement>> = React.forwardRef<
HTMLElement,
Expand All @@ -18,5 +17,4 @@ export const Button: React.FunctionComponent<ButtonProps & React.RefAttributes<H

return renderButton(state);
});

Button.displayName = 'Button';
22 changes: 22 additions & 0 deletions packages/react-button/src/components/Button/ButtonBestPractices.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
## Best practices

### Layout

- For dialog boxes and panels, where people are moving through a sequence of screens, right-align buttons with the
container.
- For single-page forms and focused tasks, left-align buttons with the container.
- Always place the primary button on the left, the secondary button just to the right of it.
- Show only one primary button that inherits theme color at rest state. If there are more than two buttons with
equal priority, all buttons should have neutral backgrounds.
- Don't use a button to navigate to another place; use a link instead. The exception is in a wizard where "Back" and
"Next" buttons may be used.
- Don't place the default focus on a button that destroys data. Instead, place the default focus on the button that
performs the "safe act" and retains the content (such as "Save") or cancels the action (such as "Cancel").

### Content

- Use sentence-style capitalization—only capitalize the first word. For more info, see
[Capitalization](https://docs.microsoft.com/en-us/style-guide/capitalization) in the Microsoft Writing Style Guide.
- Make sure it's clear what will happen when people interact with the button. Be concise; usually a single verb
is best. Include a noun if there is any room for interpretation about what the verb means.
For example, "Delete folder" or "Create account".
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Buttons give people a way to trigger an action.

They’re typically found in forms, dialog panels, and dialogs. Some buttons are specialized for particular tasks,
such as navigation, repeated actions, or presenting menus.

See also:
[MenuButton](/?path=/docs/components-menubutton--menu-button-playground),
[ToggleButton](/?path=/docs/components-togglebutton--toggle-button-playground),
[CompoundButton](/?path=/docs/components-compoundbutton--compound-button-playground)
5 changes: 5 additions & 0 deletions typings/custom-global/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ declare module '*.svg' {
export default svgPath;
}

/**
* Generic typings for Markdown files.
*/
declare module '*.md';

// These declarations are meant to represent the parts of Map/WeakMap/Set that exist in IE 11.
// Therefore, some functionality (such as constructor parameters) is intentionally missing.

Expand Down

0 comments on commit 0352049

Please sign in to comment.