Skip to content

Commit

Permalink
Merge pull request #24266 from storybookjs/icon-button
Browse files Browse the repository at this point in the history
UI: Improved Button and IconButton
  • Loading branch information
cdedreuille authored Oct 6, 2023
2 parents b8f97f0 + b30db0e commit b444604
Show file tree
Hide file tree
Showing 22 changed files with 784 additions and 1,145 deletions.
19 changes: 19 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
- [From version 7.x to 8.0.0](#from-version-7x-to-800)
- [Core changes](#core-changes)
- [UI layout state has changed shape](#ui-layout-state-has-changed-shape)
- [New UI and props for Button and IconButton components](#new-ui-and-props-for-button-and-iconbutton-components)
- [From version 7.4.0 to 7.5.0](#from-version-740-to-750)
- [`storyStoreV6` and `storiesOf` is deprecated](#storystorev6-and-storiesof-is-deprecated)
- [`storyIndexers` is replaced with `experimental_indexers`](#storyindexers-is-replaced-with-experimental_indexers)
Expand Down Expand Up @@ -320,6 +321,24 @@ In Storybook 7 it was possible to use `addons.setConfig({...});` to configure St
- `showPanel: boolean` is now split into `bottomPanelHeight: number` and `rightPanelWidth: number`, where the numbers represents the size of the panel in pixels.
- `isFullscreen: boolean` is no longer supported, but can be achieved by setting a combination of the above.

#### New UI and props for Button and IconButton components

We used to have a lot of different buttons in `@storybook/components` that were not used anywhere. In Storybook 8.0 we are deprecating `Form.Button` and added a new `Button` component that can be used in all places. The `IconButton` component has also been updated to use the new `Button` component under the hood. Going forward addon creators and Storybook maintainers should use the new `Button` component instead of `Form.Button`.

For the `Button` component, the following props are now deprecated:

- `isLink` - Please use the `asChild` prop instead like this: `<Button asChild><a href="">Link</a></Button>`
- `primary` - Please use the `variant` prop instead.
- `secondary` - Please use the `variant` prop instead.
- `tertiary` - Please use the `variant` prop instead.
- `gray` - Please use the `variant` prop instead.
- `inForm` - Please use the `variant` prop instead.
- `small` - Please use the `size` prop instead.
- `outline` - Please use the `variant` prop instead.
- `containsIcon`. Please add your icon as a child directly. No need for this prop anymore.

The `IconButton` doesn't have any deprecated props but it now uses the new `Button` component under the hood so all props for `IconButton` will be the same as `Button`.

## From version 7.4.0 to 7.5.0

#### `storyStoreV6` and `storiesOf` is deprecated
Expand Down
1 change: 0 additions & 1 deletion code/ui/blocks/src/controls/Object.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,6 @@ export const ObjectControl: FC<ObjectProps> = ({ name, value, onChange }) => {
<Wrapper>
{['Object', 'Array'].includes(getObjectType(data)) && (
<RawButton
href="#"
onClick={(e: SyntheticEvent) => {
e.preventDefault();
setShowRaw((v) => !v);
Expand Down
3 changes: 1 addition & 2 deletions code/ui/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,7 @@
"prep": "../../../scripts/prepare/bundle.ts"
},
"dependencies": {
"@radix-ui/react-select": "^1.2.2",
"@radix-ui/react-toolbar": "^1.0.4",
"@radix-ui/react-slot": "^1.0.2",
"@storybook/client-logger": "workspace:*",
"@storybook/csf": "^0.1.0",
"@storybook/global": "^5.0.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import type { Meta, StoryObj } from '@storybook/react';
import React from 'react';
import { Button } from './Button';
import { Icons } from '../icon/icon';
import { Form } from '../form';

const meta: Meta<typeof Button> = {
title: 'Button/Deprecated',
component: Button,
tags: ['autodocs'],
};

export default meta;
type Story = StoryObj<typeof Button>;

export const Default = { args: { children: 'Default' } };

export const FormButton: Story = {
render: (args) => <Form.Button {...args} />,
args: { children: 'Form.Button' },
};

export const Primary: Story = { args: { primary: true, children: 'Primary' } };
export const Secondary: Story = { args: { secondary: true, children: 'Secondary' } };
export const Tertiary: Story = { args: { tertiary: true, children: 'Tertiary' } };
export const Gray: Story = { args: { gray: true, children: 'Gray' } };

export const Outline: Story = { args: { outline: true, children: 'Outline' } };
export const OutlinePrimary: Story = {
args: { outline: true, primary: true, children: 'Outline Primary' },
};
export const OutlineSecondary: Story = {
args: { outline: true, secondary: true, children: 'Outline Secondary' },
};
export const OutlineTertiary: Story = {
args: { outline: true, tertiary: true, children: 'Outline Tertiary' },
};

export const Disabled: Story = { args: { disabled: true, children: 'Disabled' } };
export const DisabledPrimary: Story = {
args: { disabled: true, primary: true, children: 'Disabled Priary' },
};
export const DisabledSecondary: Story = {
args: { disabled: true, secondary: true, children: 'Disabled Secondary' },
};
export const DisabledTertiary: Story = {
args: { disabled: true, tertiary: true, children: 'Disabled Tertiary' },
};
export const DisabledGray: Story = {
args: { disabled: true, gray: true, children: 'Disabled Gray' },
};

export const Small: Story = { args: { small: true, children: 'Small' } };
export const SmallPrimary: Story = {
args: { small: true, primary: true, children: 'Small Priary' },
};
export const SmallSecondary: Story = {
args: { small: true, secondary: true, children: 'Small Secondary' },
};
export const SmallTertiary: Story = {
args: { small: true, tertiary: true, children: 'Small Tertiary' },
};
export const SmallGray: Story = {
args: { small: true, gray: true, children: 'Small Gray' },
};

export const IsLink: Story = {
args: { isLink: true, children: 'Button as a link' },
};

export const IconPrimary: Story = {
args: {
primary: true,
containsIcon: true,
title: 'link',
children: <Icons icon="link" />,
},
};
export const IconOutline: Story = {
args: { outline: true, containsIcon: true, title: 'link', children: <Icons icon="link" /> },
};
export const IconOutlineSmall: Story = {
args: {
outline: true,
containsIcon: true,
small: true,
title: 'link',
children: <Icons icon="link" />,
},
};
219 changes: 161 additions & 58 deletions code/ui/components/src/components/Button/Button.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,82 +1,185 @@
import type { Meta, StoryObj } from '@storybook/react';
import type { ReactNode } from 'react';
import React from 'react';
import type { Args } from '@storybook/types';

import { Button } from './Button';
import { Icons } from '../icon/icon';
import { Form } from '../form/index';

export default {
const meta = {
title: 'Button',
component: Button,
};
args: { children: 'Button' },
} satisfies Meta<typeof Button>;

export const Default = { args: { children: 'Default' } };
export default meta;
type Story = StoryObj<typeof meta>;

export const FormButton = {
render: (args: Args) => <Form.Button {...args} />,
args: { children: 'Form.Button' },
};
const Stack = ({ children }: { children: ReactNode }) => (
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>{children}</div>
);

export const Primary = { args: { primary: true, children: 'Primary' } };
export const Secondary = { args: { secondary: true, children: 'Secondary' } };
export const Tertiary = { args: { tertiary: true, children: 'Tertiary' } };
export const Gray = { args: { gray: true, children: 'Gray' } };
const Row = ({ children }: { children: ReactNode }) => (
<div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>{children}</div>
);

export const Outline = { args: { outline: true, children: 'Outline' } };
export const OutlinePrimary = {
args: { outline: true, primary: true, children: 'Outline Primary' },
};
export const OutlineSecondary = {
args: { outline: true, secondary: true, children: 'Outline Secondary' },
};
export const OutlineTertiary = {
args: { outline: true, tertiary: true, children: 'Outline Tertiary' },
};
export const Base: Story = {};

export const Disabled = { args: { disabled: true, children: 'Disabled' } };
export const DisabledPrimary = {
args: { disabled: true, primary: true, children: 'Disabled Priary' },
};
export const DisabledSecondary = {
args: { disabled: true, secondary: true, children: 'Disabled Secondary' },
};
export const DisabledTertiary = {
args: { disabled: true, tertiary: true, children: 'Disabled Tertiary' },
};
export const DisabledGray = {
args: { disabled: true, gray: true, children: 'Disabled Gray' },
export const Variants: Story = {
render: (args) => (
<Stack>
<Row>
<Button variant="solid" {...args}>
Solid
</Button>
<Button variant="outline" {...args}>
Outline
</Button>
<Button variant="ghost" {...args}>
Ghost
</Button>
</Row>
<Row>
<Button variant="solid" {...args}>
<Icons icon="facehappy" /> Solid
</Button>
<Button variant="outline" {...args}>
<Icons icon="facehappy" /> Outline
</Button>
<Button variant="ghost" {...args}>
<Icons icon="facehappy" /> Ghost
</Button>
</Row>
<Row>
<Button variant="solid" padding="small" {...args}>
<Icons icon="facehappy" />
</Button>
<Button variant="outline" padding="small" {...args}>
<Icons icon="facehappy" />
</Button>
<Button variant="ghost" padding="small" {...args}>
<Icons icon="facehappy" />
</Button>
</Row>
</Stack>
),
};

export const Small = { args: { small: true, children: 'Small' } };
export const SmallPrimary = {
args: { small: true, primary: true, children: 'Small Priary' },
export const Active: Story = {
args: {
active: true,
children: (
<>
<Icons icon="facehappy" />
Button
</>
),
},
render: (args) => (
<Row>
<Button variant="solid" {...args} />
<Button variant="outline" {...args} />
<Button variant="ghost" {...args} />
</Row>
),
};
export const SmallSecondary = {
args: { small: true, secondary: true, children: 'Small Secondary' },

export const WithIcon: Story = {
args: {
children: (
<>
<Icons icon="facehappy" />
Button
</>
),
},
render: (args) => (
<Row>
<Button variant="solid" {...args} />
<Button variant="outline" {...args} />
<Button variant="ghost" {...args} />
</Row>
),
};
export const SmallTertiary = {
args: { small: true, tertiary: true, children: 'Small Tertiary' },

export const IconOnly: Story = {
args: {
children: <Icons icon="facehappy" />,
padding: 'small',
},
render: (args) => (
<Row>
<Button variant="solid" {...args} />
<Button variant="outline" {...args} />
<Button variant="ghost" {...args} />
</Row>
),
};
export const SmallGray = {
args: { small: true, gray: true, children: 'Small Gray' },

export const Sizes: Story = {
render: () => (
<Row>
<Button size="small">Small Button</Button>
<Button size="medium">Medium Button</Button>
</Row>
),
};

export const IconPrimary = {
export const Disabled: Story = {
args: {
primary: true,
containsIcon: true,
title: 'link',
children: <Icons icon="link" />,
disabled: true,
children: 'Disabled Button',
},
};
export const IconOutline = {
args: { outline: true, containsIcon: true, title: 'link', children: <Icons icon="link" /> },

export const WithHref: Story = {
render: () => (
<Row>
<Button onClick={() => console.log('Hello')}>I am a button using onClick</Button>
<Button asChild>
<a href="https://storybook.js.org/">I am an anchor using Href</a>
</Button>
</Row>
),
};
export const IconOutlineSmall = {

export const Animated: Story = {
args: {
outline: true,
containsIcon: true,
small: true,
title: 'link',
children: <Icons icon="link" />,
variant: 'outline',
},
render: (args) => (
<Stack>
<Row>
<Button animation="glow" {...args}>
Button
</Button>
<Button animation="jiggle" {...args}>
Button
</Button>
<Button animation="rotate360" {...args}>
Button
</Button>
</Row>
<Row>
<Button animation="glow" {...args}>
<Icons icon="facehappy" /> Button
</Button>
<Button animation="jiggle" {...args}>
<Icons icon="facehappy" /> Button
</Button>
<Button animation="rotate360" {...args}>
<Icons icon="facehappy" /> Button
</Button>
</Row>
<Row>
<Button animation="glow" padding="small" {...args}>
<Icons icon="facehappy" />
</Button>
<Button animation="jiggle" padding="small" {...args}>
<Icons icon="facehappy" />
</Button>
<Button animation="rotate360" padding="small" {...args}>
<Icons icon="facehappy" />
</Button>
</Row>
</Stack>
),
};
Loading

0 comments on commit b444604

Please sign in to comment.