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 42 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
5 changes: 5 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,10 @@ 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. We have removed them 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. Going forward addon creators and Storybook maintainers should use the new `Button` component. `IconButton` is still available for use, but we might remove it in the future as this is just a wrapper around the `Button` component. `Form.Button` is depreciated and will be removed in the future.
Copy link
Contributor

Choose a reason for hiding this comment

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

We need to:

  1. be specific about which exact components have been deprecated (currently it just says "a lot of different buttons")
  2. which exact props have been deprecated
  3. which new props replace which old props
  4. give an example of migrating from the old props to the new props

We don't need to specify stuff that we "might remove" in the future, it doesn't help the user and just creates uncertainty.

In reality this is mostly an accessible version of what's written in the source code and the types, but we can't expect users to read those at all. Consider that users will see the warning in the console with a link to this section, they'll need a way forward here to resolve the warning.

Here's a proposal:

The X component from @storybook/components have been deprecated.
The following props to the Button component have been deprecated:

  • X use Y instead
  • X use Y instead
  • ...
    (same for IconButton if it has any deprecations)
    Here's an example of migrating from the old props to the new props:
// deprecated usage
<Button ... />

// new usage
<Button ... />

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I just pushed an update with some new notes and clear descriptions of what props are deprecated and what is the alternative.


## 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