mirror of
https://github.com/penpot/penpot.git
synced 2026-08-07 13:29:07 +00:00
Merge pull request #4919 from penpot/ladybenko-7869-ds-buttons
Implement design system buttons
This commit is contained in:
commit
e48aa909da
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
(ns app.main.ui.ds
|
(ns app.main.ui.ds
|
||||||
(:require
|
(:require
|
||||||
|
[app.main.ui.ds.buttons.button :refer [button*]]
|
||||||
|
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
||||||
[app.main.ui.ds.foundations.assets.icon :refer [icon* icon-list]]
|
[app.main.ui.ds.foundations.assets.icon :refer [icon* icon-list]]
|
||||||
[app.main.ui.ds.foundations.assets.raw-svg :refer [raw-svg* raw-svg-list]]
|
[app.main.ui.ds.foundations.assets.raw-svg :refer [raw-svg* raw-svg-list]]
|
||||||
[app.main.ui.ds.foundations.typography :refer [typography-list]]
|
[app.main.ui.ds.foundations.typography :refer [typography-list]]
|
||||||
@ -16,8 +18,10 @@
|
|||||||
|
|
||||||
(def default
|
(def default
|
||||||
"A export used for storybook"
|
"A export used for storybook"
|
||||||
#js {:Heading heading*
|
#js {:Button button*
|
||||||
|
:Heading heading*
|
||||||
:Icon icon*
|
:Icon icon*
|
||||||
|
:IconButton icon-button*
|
||||||
:Loader loader*
|
:Loader loader*
|
||||||
:RawSvg raw-svg*
|
:RawSvg raw-svg*
|
||||||
:Text text*
|
:Text text*
|
||||||
|
|||||||
10
frontend/src/app/main/ui/ds/_borders.scss
Normal file
10
frontend/src/app/main/ui/ds/_borders.scss
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
//
|
||||||
|
// Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
@use "./utils.scss" as *;
|
||||||
|
|
||||||
|
// TODO: create actual tokens once we have them from design
|
||||||
|
$br-8: px2rem(8);
|
||||||
10
frontend/src/app/main/ui/ds/_sizes.scss
Normal file
10
frontend/src/app/main/ui/ds/_sizes.scss
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
//
|
||||||
|
// Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
@use "./utils.scss" as *;
|
||||||
|
|
||||||
|
// TODO: create actual tokens once we have them from design
|
||||||
|
$sz-32: px2rem(32);
|
||||||
132
frontend/src/app/main/ui/ds/buttons/_buttons.scss
Normal file
132
frontend/src/app/main/ui/ds/buttons/_buttons.scss
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
//
|
||||||
|
// Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
@use "../_borders.scss" as *;
|
||||||
|
@use "../_sizes.scss" as *;
|
||||||
|
@use "../utils.scss" as *;
|
||||||
|
|
||||||
|
%base-button {
|
||||||
|
--button-bg-color: initial;
|
||||||
|
--button-fg-color: initial;
|
||||||
|
--button-hover-bg-color: initial;
|
||||||
|
--button-hover-fg-color: initial;
|
||||||
|
--button-active-bg-color: initial;
|
||||||
|
--button-disabled-bg-color: initial;
|
||||||
|
--button-disabled-fg-color: initial;
|
||||||
|
--button-border-color: var(--button-bg-color);
|
||||||
|
--button-focus-inner-ring-color: initial;
|
||||||
|
--button-focus-outer-ring-color: initial;
|
||||||
|
|
||||||
|
appearance: none;
|
||||||
|
height: $sz-32;
|
||||||
|
border: none;
|
||||||
|
border-radius: $br-8;
|
||||||
|
|
||||||
|
background: var(--button-bg-color);
|
||||||
|
color: var(--button-fg-color);
|
||||||
|
border: 1px solid var(--button-border-color);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
--button-bg-color: var(--button-hover-bg-color);
|
||||||
|
--button-fg-color: var(--button-hover-fg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
--button-bg-color: var(--button-active-bg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible {
|
||||||
|
outline: var(--button-focus-inner-ring-color) solid #{px2rem(2)};
|
||||||
|
outline-offset: -#{px2rem(3)};
|
||||||
|
--button-border-color: var(--button-focus-outer-ring-color);
|
||||||
|
--button-fg-color: var(--button-focus-fg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
--button-bg-color: var(--button-disabled-bg-color);
|
||||||
|
--button-fg-color: var(--button-disabled-fg-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
%base-button-primary {
|
||||||
|
--button-bg-color: var(--color-accent-primary);
|
||||||
|
--button-fg-color: var(--color-background-secondary);
|
||||||
|
|
||||||
|
--button-hover-bg-color: var(--color-accent-tertiary);
|
||||||
|
--button-hover-fg-color: var(--color-background-secondary);
|
||||||
|
|
||||||
|
--button-active-bg-color: var(--color-accent-tertiary);
|
||||||
|
|
||||||
|
--button-disabled-bg-color: var(--color-accent-primary-muted);
|
||||||
|
--button-disabled-fg-color: var(--color-background-secondary);
|
||||||
|
|
||||||
|
--button-focus-bg-color: var(--color-accent-primary);
|
||||||
|
--button-focus-fg-color: var(--color-background-secondary);
|
||||||
|
--button-focus-inner-ring-color: var(--color-background-secondary);
|
||||||
|
--button-focus-outer-ring-color: var(--color-accent-primary);
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
box-shadow: inset 0 0 #{px2rem(10)} #{px2rem(2)} rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
%base-button-secondary {
|
||||||
|
--button-bg-color: var(--color-background-tertiary);
|
||||||
|
--button-fg-color: var(--color-foreground-secondary);
|
||||||
|
|
||||||
|
--button-hover-bg-color: var(--color-background-tertiary);
|
||||||
|
--button-hover-fg-color: var(--color-accent-primary);
|
||||||
|
|
||||||
|
--button-active-bg-color: var(--color-background-quaternary);
|
||||||
|
|
||||||
|
--button-disabled-bg-color: transparent;
|
||||||
|
--button-disabled-fg-color: var(--color-foreground-secondary);
|
||||||
|
|
||||||
|
--button-focus-bg-color: var(--color-background-tertiary);
|
||||||
|
--button-focus-fg-color: var(--color-foreground-primary);
|
||||||
|
--button-focus-inner-ring-color: var(--color-background-secondary);
|
||||||
|
--button-focus-outer-ring-color: var(--color-accent-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
%base-button-ghost {
|
||||||
|
--button-bg-color: transparent;
|
||||||
|
--button-fg-color: var(--color-foreground-secondary);
|
||||||
|
|
||||||
|
--button-hover-bg-color: var(--color-background-tertiary);
|
||||||
|
--button-hover-fg-color: var(--color-accent-primary);
|
||||||
|
|
||||||
|
--button-active-bg-color: var(--color-background-quaternary);
|
||||||
|
|
||||||
|
--button-disabled-bg-color: transparent;
|
||||||
|
--button-disabled-fg-color: var(--color-accent-primary-muted);
|
||||||
|
|
||||||
|
--button-focus-bg-color: transparent;
|
||||||
|
--button-focus-fg-color: var(--color-foreground-secondary);
|
||||||
|
--button-focus-inner-ring-color: transparent;
|
||||||
|
--button-focus-outer-ring-color: var(--color-accent-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
%base-button-destructive {
|
||||||
|
--button-bg-color: var(--color-accent-error);
|
||||||
|
--button-fg-color: var(--color-foreground-primary);
|
||||||
|
|
||||||
|
--button-hover-bg-color: var(--color-background-error);
|
||||||
|
--button-hover-fg-color: var(--color-foreground-primary);
|
||||||
|
|
||||||
|
--button-active-bg-color: var(--color-accent-error);
|
||||||
|
|
||||||
|
--button-disabled-bg-color: var(--color-background-error);
|
||||||
|
--button-disabled-fg-color: var(--color-accent-error);
|
||||||
|
|
||||||
|
--button-focus-bg-color: var(--color-accent-error);
|
||||||
|
--button-focus-fg-color: var(--color-foreground-primary);
|
||||||
|
--button-focus-inner-ring-color: var(--color-background-primary);
|
||||||
|
--button-focus-outer-ring-color: var(--color-accent-primary);
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
box-shadow: inset 0 0 #{px2rem(10)} #{px2rem(2)} rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
30
frontend/src/app/main/ui/ds/buttons/button.cljs
Normal file
30
frontend/src/app/main/ui/ds/buttons/button.cljs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
;;
|
||||||
|
;; Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
(ns app.main.ui.ds.buttons.button
|
||||||
|
(:require-macros
|
||||||
|
[app.common.data.macros :as dm]
|
||||||
|
[app.main.style :as stl])
|
||||||
|
(:require
|
||||||
|
[app.main.ui.ds.foundations.assets.icon :refer [icon*]]
|
||||||
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
|
(def button-variants (set '("primary" "secondary" "ghost" "destructive")))
|
||||||
|
|
||||||
|
(mf/defc button*
|
||||||
|
{::mf/props :obj}
|
||||||
|
[{:keys [variant icon children class] :rest props}]
|
||||||
|
(assert (or (nil? variant) (contains? button-variants variant) "expected valid variant"))
|
||||||
|
(let [variant (or variant "primary")
|
||||||
|
class (dm/str class " " (stl/css-case :button true
|
||||||
|
:button-primary (= variant "primary")
|
||||||
|
:button-secondary (= variant "secondary")
|
||||||
|
:button-ghost (= variant "ghost")
|
||||||
|
:button-destructive (= variant "destructive")))
|
||||||
|
props (mf/spread-props props {:class class})]
|
||||||
|
[:> "button" props
|
||||||
|
(when icon [:> icon* {:id icon :size "m"}])
|
||||||
|
[:span {:class (stl/css :label-wrapper)} children]]))
|
||||||
35
frontend/src/app/main/ui/ds/buttons/button.scss
Normal file
35
frontend/src/app/main/ui/ds/buttons/button.scss
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
//
|
||||||
|
// Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
@use "../typography.scss" as *;
|
||||||
|
@use "./buttons" as *;
|
||||||
|
|
||||||
|
.button {
|
||||||
|
@extend %base-button;
|
||||||
|
|
||||||
|
@include use-typography("headline-small");
|
||||||
|
padding: 0 var(--sp-m);
|
||||||
|
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
column-gap: var(--sp-xs);
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-primary {
|
||||||
|
@extend %base-button-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-secondary {
|
||||||
|
@extend %base-button-secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-ghost {
|
||||||
|
@extend %base-button-ghost;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-destructive {
|
||||||
|
@extend %base-button-destructive;
|
||||||
|
}
|
||||||
74
frontend/src/app/main/ui/ds/buttons/button.stories.jsx
Normal file
74
frontend/src/app/main/ui/ds/buttons/button.stories.jsx
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
//
|
||||||
|
// Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
import * as React from "react";
|
||||||
|
import Components from "@target/components";
|
||||||
|
|
||||||
|
const { Button } = Components;
|
||||||
|
const { icons } = Components.meta;
|
||||||
|
|
||||||
|
const iconList = [
|
||||||
|
...Object.entries(icons)
|
||||||
|
.map(([_, value]) => value)
|
||||||
|
.sort(),
|
||||||
|
];
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: "Buttons/Button",
|
||||||
|
component: Components.Button,
|
||||||
|
argTypes: {
|
||||||
|
icon: {
|
||||||
|
options: iconList,
|
||||||
|
control: { type: "select" },
|
||||||
|
},
|
||||||
|
disabled: { control: "boolean" },
|
||||||
|
variant: {
|
||||||
|
options: ["primary", "secondary", "ghost", "destructive"],
|
||||||
|
control: { type: "select" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
args: {
|
||||||
|
children: "Lorem ipsum",
|
||||||
|
disabled: false,
|
||||||
|
variant: undefined,
|
||||||
|
},
|
||||||
|
parameters: {
|
||||||
|
controls: { exclude: ["children"] },
|
||||||
|
},
|
||||||
|
render: ({ ...args }) => <Button {...args} />,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Default = {};
|
||||||
|
|
||||||
|
export const WithIcon = {
|
||||||
|
args: {
|
||||||
|
icon: "effects",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Primary = {
|
||||||
|
args: {
|
||||||
|
variant: "primary",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Secondary = {
|
||||||
|
args: {
|
||||||
|
variant: "secondary",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Ghost = {
|
||||||
|
args: {
|
||||||
|
variant: "ghost",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Destructive = {
|
||||||
|
args: {
|
||||||
|
variant: "destructive",
|
||||||
|
},
|
||||||
|
};
|
||||||
69
frontend/src/app/main/ui/ds/buttons/buttons.mdx
Normal file
69
frontend/src/app/main/ui/ds/buttons/buttons.mdx
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import { Canvas, Meta } from '@storybook/blocks';
|
||||||
|
import * as ButtonStories from "./button.stories";
|
||||||
|
import * as IconButtonStories from "./icon_button.stories";
|
||||||
|
|
||||||
|
<Meta title="Buttons/Buttons" />
|
||||||
|
|
||||||
|
# Buttons
|
||||||
|
|
||||||
|
Buttons trigger an action such as submitting a form or showing/hiding an interface component.
|
||||||
|
|
||||||
|
## Variants
|
||||||
|
|
||||||
|
**Primary** (`"primary"`), used to initiate the main / primary action of a view or flow. Avoid to have more than one primary buttons in the same view or flow.
|
||||||
|
|
||||||
|
<Canvas of={ButtonStories.Primary} />
|
||||||
|
|
||||||
|
**Secondary** (`"secondary"`), the default and most common buttons in the interface. Use them for non primary actions.
|
||||||
|
|
||||||
|
<Canvas of={ButtonStories.Secondary} />
|
||||||
|
|
||||||
|
**Ghosts** (`"ghost"`), used for less prominent, and sometimes independent, actions (examples: add pages, add properties, etc.)
|
||||||
|
|
||||||
|
<Canvas of={ButtonStories.Ghost} />
|
||||||
|
|
||||||
|
**Destructive** (`"destructive"`), used for any action that destroys any object or data. Don't use them for actions like dettach, unlink, etc.
|
||||||
|
|
||||||
|
<Canvas of={ButtonStories.Destructive} />
|
||||||
|
|
||||||
|
## Technical notes
|
||||||
|
|
||||||
|
### Icons
|
||||||
|
|
||||||
|
Both `button*` and `icon-button*` accept an `icon` prop, which must contain an [icon ID](../foundations/assets/icon.mdx).
|
||||||
|
These are available in the `app.main.ds.foundations.assets.icon` namespace.
|
||||||
|
|
||||||
|
```clj
|
||||||
|
(ns app.main.ui.foo
|
||||||
|
(:require
|
||||||
|
[app.main.ui.ds.foundations.assets.icon :as i]))
|
||||||
|
```
|
||||||
|
|
||||||
|
```clj
|
||||||
|
[:> button* {:icon i/effects} "Lorem ipsum"]
|
||||||
|
```
|
||||||
|
|
||||||
|
<Canvas of={ButtonStories.WithIcon} />
|
||||||
|
|
||||||
|
### Accessibility
|
||||||
|
|
||||||
|
Icon buttons require an `aria-label`. This is also shown in a tooltip on hovering the button.
|
||||||
|
|
||||||
|
```clj
|
||||||
|
[:> icon-button* {:icon i/effects :aria-label "Lorem ipsum"}]
|
||||||
|
```
|
||||||
|
|
||||||
|
<Canvas of={IconButtonStories.Default} />
|
||||||
|
|
||||||
|
## Usage guidelines (design)
|
||||||
|
|
||||||
|
### Where to use
|
||||||
|
|
||||||
|
Penpot app has a high-density interface, so use buttons thoughtfully to establish
|
||||||
|
a clear and logical visual hierarchy, and avoid overwhelming the user.
|
||||||
|
|
||||||
|
### When to use
|
||||||
|
|
||||||
|
Buttons can be used in forms, navigation links or anywhere that needs simple,
|
||||||
|
standard button functionality. Used also to grab users' attention (i.e. navigate
|
||||||
|
to main user flows like register, etc.)
|
||||||
30
frontend/src/app/main/ui/ds/buttons/icon_button.cljs
Normal file
30
frontend/src/app/main/ui/ds/buttons/icon_button.cljs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
;;
|
||||||
|
;; Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
(ns app.main.ui.ds.buttons.icon-button
|
||||||
|
(:require-macros
|
||||||
|
[app.common.data.macros :as dm]
|
||||||
|
[app.main.style :as stl])
|
||||||
|
(:require
|
||||||
|
[app.main.ui.ds.foundations.assets.icon :refer [icon*]]
|
||||||
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
|
(def button-variants (set '("primary" "secondary" "ghost" "destructive")))
|
||||||
|
|
||||||
|
(mf/defc icon-button*
|
||||||
|
{::mf/props :obj}
|
||||||
|
[{:keys [class icon variant aria-label] :rest props}]
|
||||||
|
(assert (or (not variant) (contains? button-variants variant)) "invalid variant")
|
||||||
|
(assert (some? aria-label) "aria-label must be provided")
|
||||||
|
(assert (some? icon) "an icon id must be provided")
|
||||||
|
(let [variant (or variant "primary")
|
||||||
|
class (dm/str class " " (stl/css-case :icon-button true
|
||||||
|
:icon-button-primary (= variant "primary")
|
||||||
|
:icon-button-secondary (= variant "secondary")
|
||||||
|
:icon-button-ghost (= variant "ghost")
|
||||||
|
:icon-button-destructive (= variant "destructive")))
|
||||||
|
props (mf/spread-props props {:class class :title aria-label})]
|
||||||
|
[:> "button" props [:> icon* {:id icon :aria-label aria-label}]]))
|
||||||
33
frontend/src/app/main/ui/ds/buttons/icon_button.scss
Normal file
33
frontend/src/app/main/ui/ds/buttons/icon_button.scss
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
//
|
||||||
|
// Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
@use "../typography.scss" as *;
|
||||||
|
@use "../_sizes.scss" as *;
|
||||||
|
@use "./buttons" as *;
|
||||||
|
|
||||||
|
.icon-button {
|
||||||
|
@extend %base-button;
|
||||||
|
width: #{$sz-32};
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-button-primary {
|
||||||
|
@extend %base-button-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-button-secondary {
|
||||||
|
@extend %base-button-secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-button-ghost {
|
||||||
|
@extend %base-button-ghost;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-button-destructive {
|
||||||
|
@extend %base-button-destructive;
|
||||||
|
}
|
||||||
66
frontend/src/app/main/ui/ds/buttons/icon_button.stories.jsx
Normal file
66
frontend/src/app/main/ui/ds/buttons/icon_button.stories.jsx
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
//
|
||||||
|
// Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
import * as React from "react";
|
||||||
|
import Components from "@target/components";
|
||||||
|
|
||||||
|
const { IconButton } = Components;
|
||||||
|
const { icons } = Components.meta;
|
||||||
|
|
||||||
|
const iconList = [
|
||||||
|
...Object.entries(icons)
|
||||||
|
.map(([_, value]) => value)
|
||||||
|
.sort(),
|
||||||
|
];
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: "Buttons/IconButton",
|
||||||
|
component: Components.IconButton,
|
||||||
|
argTypes: {
|
||||||
|
icon: {
|
||||||
|
options: iconList,
|
||||||
|
control: { type: "select" },
|
||||||
|
},
|
||||||
|
disabled: { control: "boolean" },
|
||||||
|
variant: {
|
||||||
|
options: ["primary", "secondary", "ghost", "destructive"],
|
||||||
|
control: { type: "select" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
args: {
|
||||||
|
disabled: false,
|
||||||
|
variant: undefined,
|
||||||
|
"aria-label": "Lorem ipsum",
|
||||||
|
icon: "effects",
|
||||||
|
},
|
||||||
|
render: ({ ...args }) => <IconButton {...args} />,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Default = {};
|
||||||
|
|
||||||
|
export const Primary = {
|
||||||
|
args: {
|
||||||
|
variant: "primary",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Secondary = {
|
||||||
|
args: {
|
||||||
|
variant: "secondary",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Ghost = {
|
||||||
|
args: {
|
||||||
|
variant: "ghost",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Destructive = {
|
||||||
|
args: {
|
||||||
|
variant: "destructive",
|
||||||
|
},
|
||||||
|
};
|
||||||
Loading…
x
Reference in New Issue
Block a user