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

UI: Improved Button and IconButton #24266

Merged
merged 48 commits into from
Oct 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
e760142
Add the new IconButton
cdedreuille Sep 22, 2023
1f2fe6b
Replace IconButton
cdedreuille Sep 22, 2023
e3c3e59
Merge branch 'v8' into icon-button
cdedreuille Sep 22, 2023
8b6b89b
Merge branch 'v8' into icon-button
cdedreuille Sep 22, 2023
9e5ee81
Make IconButton works with text for backward compatibility
cdedreuille Sep 22, 2023
f6f7e26
Remove the old IconButton
cdedreuille Sep 22, 2023
930d1e2
Update separator
cdedreuille Sep 22, 2023
9b12740
Merge branch 'release-8-0' into icon-button
cdedreuille Sep 22, 2023
926da91
Fix icons in panel not showing correctly
cdedreuille Sep 22, 2023
c207df0
Merge branch 'release-8-0' into icon-button
cdedreuille Sep 22, 2023
4cd425c
Update all props on IconButton
cdedreuille Oct 2, 2023
2c49acc
Merge branch 'release-8-0' into icon-button
cdedreuille Oct 2, 2023
c9a9f06
Fix missing IconButton
cdedreuille Oct 2, 2023
4b1e76e
Make icon prop optional
cdedreuille Oct 2, 2023
ae268a5
Update IconButton.tsx
cdedreuille Oct 2, 2023
4ac1af7
Revert "Fix missing IconButton"
cdedreuille Oct 2, 2023
26383b5
Revert
cdedreuille Oct 2, 2023
893d7e7
Fix some issues
cdedreuille Oct 2, 2023
84480a3
Update IconButton.stories.tsx
cdedreuille Oct 2, 2023
e7a67d1
Improved structure
cdedreuille Oct 3, 2023
8ca9be8
Merge branch 'release-8-0' into icon-button
cdedreuille Oct 3, 2023
493cb3e
Improve Button
cdedreuille Oct 3, 2023
c67cfd4
Replace IconButton with new Button component
cdedreuille Oct 3, 2023
21796c2
Update eject.tsx
cdedreuille Oct 3, 2023
698727a
Cleanup
cdedreuille Oct 3, 2023
95808a3
Update Button.tsx
cdedreuille Oct 3, 2023
e8b7934
Fix issues
cdedreuille Oct 3, 2023
fd77578
Fix animation on svg
cdedreuille Oct 3, 2023
2c820ac
Fix name
cdedreuille Oct 3, 2023
cf89b4f
Fixed. I used Stack and Row
cdedreuille Oct 3, 2023
3f8ec42
Removed string
cdedreuille Oct 3, 2023
1dd8cc2
Update Button.tsx
cdedreuille Oct 3, 2023
b24e5c4
Update Button.tsx
cdedreuille Oct 3, 2023
213faad
use 'a' if we are using isLink
cdedreuille Oct 3, 2023
dd8d9e2
Fixes
cdedreuille Oct 3, 2023
1da9c7c
Merge branch 'release-8-0' into icon-button
cdedreuille Oct 3, 2023
76c5601
Add migration + deprecated warnings
cdedreuille Oct 4, 2023
83147eb
Add isLink story
cdedreuille Oct 4, 2023
18e6465
Improve deprecated warning
cdedreuille Oct 4, 2023
2003a4b
Improve Button docs
cdedreuille Oct 4, 2023
602ecd7
Improve docs
cdedreuille Oct 4, 2023
fe09c25
Merge branch 'release-8-0' into icon-button
cdedreuille Oct 5, 2023
3de2756
Improved migration notes
cdedreuille Oct 6, 2023
acbbd3b
Fixed spelling mistake
cdedreuille Oct 6, 2023
64ba705
Update Button.tsx
cdedreuille Oct 6, 2023
aecc130
Cleaning
cdedreuille Oct 6, 2023
0d56d6e
Merge branch 'release-8-0' into icon-button
cdedreuille Oct 6, 2023
b30db0e
Fix button shrinking
cdedreuille Oct 6, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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