Skip to content

Commit 6551167

Browse files
committed
feat(react-formio): add button molecule
1 parent 00bc3fd commit 6551167

File tree

2 files changed

+160
-0
lines changed

2 files changed

+160
-0
lines changed
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import { Meta, StoryObj } from "@storybook/react";
2+
3+
import { Icon } from "../../atoms/icon/Icon";
4+
import { Button, BUTTON_VARIANTS } from "./Button";
5+
6+
/**
7+
* Button component with a label and an onClick handler.
8+
*
9+
* ```ts
10+
* import {Button} from "@tsed/react-formio/molecules/button/Button";
11+
* ```
12+
*
13+
* ## Override Button
14+
*
15+
* This component is registered with the name `Button` and can be overridden with the following code:
16+
*
17+
* ```ts
18+
* registerComponent("Button", MyCustomButtonComponent);
19+
* ```
20+
*/
21+
export default {
22+
title: "Button",
23+
component: Button,
24+
argTypes: {
25+
onClick: { action: "clicked" },
26+
variant: {
27+
control: "select",
28+
options: BUTTON_VARIANTS
29+
},
30+
disabled: {
31+
control: "boolean"
32+
}
33+
},
34+
parameters: {
35+
children: "Text",
36+
variant: "primary"
37+
}
38+
} satisfies Meta<typeof Button>;
39+
40+
type Story = StoryObj<typeof Button>;
41+
42+
export const Usage: Story = {
43+
args: {
44+
children: "Text",
45+
variant: "primary"
46+
}
47+
};
48+
49+
export const Variant: Story = {
50+
args: {
51+
children: "Text"
52+
},
53+
render(args) {
54+
return (
55+
<div className='flex flex-wrap gap-3'>
56+
{BUTTON_VARIANTS.map((variant) => (
57+
<div key={variant}>
58+
<Button {...args} variant={variant as any}>
59+
{variant}
60+
</Button>
61+
</div>
62+
))}
63+
</div>
64+
);
65+
}
66+
};
67+
68+
export const Disabled: Story = {
69+
args: {
70+
children: "Text",
71+
disabled: true
72+
},
73+
render(args) {
74+
return (
75+
<div className='flex flex-wrap gap-3'>
76+
{BUTTON_VARIANTS.map((variant) => (
77+
<div key={variant}>
78+
<Button {...args} variant={variant as any}>
79+
{variant}
80+
</Button>
81+
</div>
82+
))}
83+
</div>
84+
);
85+
}
86+
};
87+
88+
export const WithIcon: Story = {
89+
args: {
90+
children: "Text"
91+
},
92+
render(args) {
93+
return (
94+
<div className='flex flex-wrap gap-3'>
95+
{BUTTON_VARIANTS.map((variant) => (
96+
<div key={variant}>
97+
<Button {...args} variant={variant as any}>
98+
<Icon name='save' />
99+
{variant}
100+
</Button>
101+
</div>
102+
))}
103+
</div>
104+
);
105+
}
106+
};
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import cx from "classnames";
2+
import { type ButtonHTMLAttributes, forwardRef, type LegacyRef, type PropsWithChildren } from "react";
3+
4+
import { registerComponent } from "../../registries/components";
5+
6+
export const BUTTON_VARIANTS = [
7+
"primary",
8+
"secondary",
9+
"success",
10+
"danger",
11+
"warning",
12+
"info",
13+
"light",
14+
"dark",
15+
"link",
16+
"outline-primary",
17+
"outline-secondary",
18+
"outline-success",
19+
"outline-danger",
20+
"outline-warning",
21+
"outline-info",
22+
"outline-light",
23+
"outline-dark",
24+
"outline-link"
25+
];
26+
27+
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
28+
variant?: (typeof BUTTON_VARIANTS)[keyof typeof BUTTON_VARIANTS] | string;
29+
}
30+
31+
export const Button = forwardRef(
32+
({ variant, className, children, ...props }: PropsWithChildren<ButtonProps>, ref: LegacyRef<HTMLButtonElement>) => {
33+
return (
34+
<button
35+
{...props}
36+
ref={ref}
37+
className={cx(
38+
"btn flex gap-1",
39+
{
40+
disabled: props.disabled
41+
},
42+
`btn-${variant}`,
43+
className
44+
)}
45+
disabled={props.disabled}
46+
onClick={(evt) => !props.disabled && props.onClick?.(evt)}
47+
>
48+
{children}
49+
</button>
50+
);
51+
}
52+
);
53+
54+
registerComponent("Button", Button);

0 commit comments

Comments
 (0)