Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Storybook/Button documentation #19298

Merged
merged 16 commits into from
Aug 23, 2021
Merged
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,
PeterDraex marked this conversation as resolved.
Show resolved Hide resolved
expanded: true,
},
docs: {
source: {
excludeDecorators: true,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is this config for ? I'm unable to find any related docs - can you provide those pls?

Copy link
Contributor Author

@PeterDraex PeterDraex Aug 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without this config, the source code for the main story wasn’t being shown properly - only the decorator was visible and not the story code itself. This config option isn’t present in the docs, I found it in this comment: storybookjs/storybook#12596 (comment)

},
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "none",
"comment": "Button docs",
"packageName": "@fluentui/react-button",
"email": "peter@draxler.ml",
"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>;
PeterDraex marked this conversation as resolved.
Show resolved Hide resolved

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' +
PeterDraex marked this conversation as resolved.
Show resolved Hide resolved
'- `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.
PeterDraex marked this conversation as resolved.
Show resolved Hide resolved
*/
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';
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 @@ -6,6 +6,11 @@ declare module '*.scss' {
export default styles;
}

/**
* 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