@grantbii/design-system 3.0.3 → 3.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/molecules/ToggleButton.d.ts +21 -0
- package/core/molecules/ToggleButton.js +161 -0
- package/core/molecules/ToggleButton.js.map +1 -0
- package/core/molecules/index.d.ts +1 -0
- package/core/molecules/index.js +1 -0
- package/core/molecules/index.js.map +1 -1
- package/package.json +1 -1
- package/stories/molecules/ToggleButton.stories.d.ts +11 -0
- package/stories/molecules/ToggleButton.stories.js +79 -0
- package/stories/molecules/ToggleButton.stories.js.map +1 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type ButtonHTMLAttributes, type HTMLAttributes } from "react";
|
|
2
|
+
export type ToggleButtonSize = "small" | "medium" | "large";
|
|
3
|
+
export type ToggleButtonProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, "onChange"> & {
|
|
4
|
+
pressed?: boolean;
|
|
5
|
+
onPressedChange?: (isPressed: boolean) => void;
|
|
6
|
+
size?: ToggleButtonSize;
|
|
7
|
+
};
|
|
8
|
+
declare const ToggleButton: ({ pressed, onPressedChange, onClick, size, type, ...props }: ToggleButtonProps) => import("react").JSX.Element;
|
|
9
|
+
export default ToggleButton;
|
|
10
|
+
export type ToggleButtonGroupProps = Omit<HTMLAttributes<HTMLDivElement>, "defaultValue" | "onChange"> & {
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
size?: ToggleButtonSize;
|
|
13
|
+
value?: string;
|
|
14
|
+
defaultValue?: string;
|
|
15
|
+
onValueChange?: (value: string) => void;
|
|
16
|
+
};
|
|
17
|
+
export declare const ToggleButtonGroup: ({ children, value, defaultValue, onValueChange, disabled, size, ...props }: ToggleButtonGroupProps) => import("react").JSX.Element;
|
|
18
|
+
export type ToggleButtonGroupItemProps = Omit<ToggleButtonProps, "onPressedChange" | "pressed" | "size"> & {
|
|
19
|
+
value: string;
|
|
20
|
+
};
|
|
21
|
+
export declare const ToggleButtonGroupItem: ({ value, disabled, ...props }: ToggleButtonGroupItemProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { createContext, useContext, useMemo, useState, } from "react";
|
|
4
|
+
import styled from "styled-components";
|
|
5
|
+
import { Color, Typography } from "../atoms";
|
|
6
|
+
import { applyTypography } from "../integrations";
|
|
7
|
+
const toggleButtonSizeStyles = {
|
|
8
|
+
small: {
|
|
9
|
+
iconButtonSize: "26px",
|
|
10
|
+
textButtonHeight: "26px",
|
|
11
|
+
iconSize: "14px",
|
|
12
|
+
padding: "6px",
|
|
13
|
+
},
|
|
14
|
+
medium: {
|
|
15
|
+
iconButtonSize: "46px",
|
|
16
|
+
textButtonHeight: "48px",
|
|
17
|
+
iconSize: "20px",
|
|
18
|
+
padding: "13px",
|
|
19
|
+
},
|
|
20
|
+
large: {
|
|
21
|
+
iconButtonSize: "52px",
|
|
22
|
+
textButtonHeight: "56px",
|
|
23
|
+
iconSize: "20px",
|
|
24
|
+
padding: "16px",
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
const toggleButtonTypography = {
|
|
28
|
+
small: {
|
|
29
|
+
...Typography.captionMedium,
|
|
30
|
+
fontSize: { small: "10px", large: "10px" },
|
|
31
|
+
},
|
|
32
|
+
medium: Typography.bodyPrimaryMedium,
|
|
33
|
+
large: Typography.subheading2Medium,
|
|
34
|
+
};
|
|
35
|
+
const ToggleButton = ({ pressed, onPressedChange, onClick, size = "medium", type = "button", ...props }) => {
|
|
36
|
+
const [isUncontrolledPressed, setIsUncontrolledPressed] = useState(false);
|
|
37
|
+
const isPressed = pressed ?? isUncontrolledPressed;
|
|
38
|
+
return (_jsx(ToggleButtonContainer, { ...props, type: type, "data-state": isPressed ? "on" : "off", "$size": size, onClick: (event) => {
|
|
39
|
+
onClick?.(event);
|
|
40
|
+
if (event.defaultPrevented)
|
|
41
|
+
return;
|
|
42
|
+
const shouldPress = !isPressed;
|
|
43
|
+
if (pressed === undefined)
|
|
44
|
+
setIsUncontrolledPressed(shouldPress);
|
|
45
|
+
onPressedChange?.(shouldPress);
|
|
46
|
+
} }));
|
|
47
|
+
};
|
|
48
|
+
export default ToggleButton;
|
|
49
|
+
const ToggleButtonGroupContext = createContext(null);
|
|
50
|
+
export const ToggleButtonGroup = ({ children, value, defaultValue, onValueChange, disabled = false, size = "medium", ...props }) => {
|
|
51
|
+
const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue ?? "");
|
|
52
|
+
const selectedValue = value ?? uncontrolledValue;
|
|
53
|
+
const contextValue = useMemo(() => ({
|
|
54
|
+
isGroupDisabled: disabled,
|
|
55
|
+
selectedValue,
|
|
56
|
+
groupSize: size,
|
|
57
|
+
toggleItem: (itemValue) => {
|
|
58
|
+
const nextSelectedValue = selectedValue === itemValue ? "" : itemValue;
|
|
59
|
+
if (value === undefined)
|
|
60
|
+
setUncontrolledValue(nextSelectedValue);
|
|
61
|
+
onValueChange?.(nextSelectedValue);
|
|
62
|
+
},
|
|
63
|
+
}), [disabled, onValueChange, selectedValue, size, value]);
|
|
64
|
+
return (_jsx(ToggleButtonGroupContext.Provider, { value: contextValue, children: _jsx(ToggleButtonGroupContainer, { ...props, role: "group", children: children }) }));
|
|
65
|
+
};
|
|
66
|
+
export const ToggleButtonGroupItem = ({ value, disabled, ...props }) => {
|
|
67
|
+
const groupContext = useContext(ToggleButtonGroupContext);
|
|
68
|
+
if (!groupContext)
|
|
69
|
+
throw new Error("ToggleButtonGroupItem must be used within ToggleButtonGroup");
|
|
70
|
+
return (_jsx(ToggleButton, { ...props, pressed: groupContext.selectedValue === value, disabled: groupContext.isGroupDisabled || disabled, size: groupContext.groupSize, onPressedChange: () => groupContext.toggleItem(value) }));
|
|
71
|
+
};
|
|
72
|
+
const ToggleButtonContainer = styled.button `
|
|
73
|
+
display: inline-flex;
|
|
74
|
+
align-items: center;
|
|
75
|
+
justify-content: center;
|
|
76
|
+
box-sizing: border-box;
|
|
77
|
+
min-width: ${({ $size }) => toggleButtonSizeStyles[$size].iconButtonSize};
|
|
78
|
+
height: ${({ $size }) => toggleButtonSizeStyles[$size].iconButtonSize};
|
|
79
|
+
padding: ${({ $size }) => toggleButtonSizeStyles[$size].padding};
|
|
80
|
+
|
|
81
|
+
${({ $size }) => applyTypography(toggleButtonTypography[$size])}
|
|
82
|
+
white-space: nowrap;
|
|
83
|
+
|
|
84
|
+
color: ${Color.typography.blackHigh};
|
|
85
|
+
background: ${Color.neutral.white};
|
|
86
|
+
border: 1px solid ${Color.neutral.grey2};
|
|
87
|
+
border-radius: 6px;
|
|
88
|
+
|
|
89
|
+
cursor: pointer;
|
|
90
|
+
|
|
91
|
+
&:hover:not(:disabled):not([data-state="on"]) {
|
|
92
|
+
background: ${Color.accent.blue3};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
&[data-state="on"] {
|
|
96
|
+
position: relative;
|
|
97
|
+
z-index: 1;
|
|
98
|
+
|
|
99
|
+
color: ${Color.typography.whiteHigh};
|
|
100
|
+
background: ${Color.brand.grantbiiBlue};
|
|
101
|
+
border-color: ${Color.brand.grantbiiBlue};
|
|
102
|
+
|
|
103
|
+
&:hover:not(:disabled) {
|
|
104
|
+
background: ${Color.accent.blue2};
|
|
105
|
+
border-color: ${Color.accent.blue2};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
&:focus-visible {
|
|
110
|
+
position: relative;
|
|
111
|
+
z-index: 2;
|
|
112
|
+
outline: 2px solid ${Color.accent.blue2};
|
|
113
|
+
outline-offset: 2px;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
&:disabled {
|
|
117
|
+
color: ${Color.typography.blackMedium};
|
|
118
|
+
background: ${Color.neutral.grey2};
|
|
119
|
+
cursor: not-allowed;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
svg {
|
|
123
|
+
flex: none;
|
|
124
|
+
width: ${({ $size }) => toggleButtonSizeStyles[$size].iconSize};
|
|
125
|
+
height: ${({ $size }) => toggleButtonSizeStyles[$size].iconSize};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
&:not(:has(svg)) {
|
|
129
|
+
height: ${({ $size }) => toggleButtonSizeStyles[$size].textButtonHeight};
|
|
130
|
+
}
|
|
131
|
+
`;
|
|
132
|
+
const ToggleButtonGroupContainer = styled.div `
|
|
133
|
+
display: inline-flex;
|
|
134
|
+
box-sizing: border-box;
|
|
135
|
+
|
|
136
|
+
border-radius: 6px;
|
|
137
|
+
outline: 1px solid ${Color.neutral.grey2};
|
|
138
|
+
outline-offset: -1px;
|
|
139
|
+
|
|
140
|
+
> button {
|
|
141
|
+
border: 0;
|
|
142
|
+
border-radius: 0;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
> button:not(:last-child) {
|
|
146
|
+
border-right: 1px solid ${Color.neutral.grey2};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
> button:first-child {
|
|
150
|
+
border-radius: 6px 0 0 6px;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
> button:last-child {
|
|
154
|
+
border-radius: 0 6px 6px 0;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
> button:only-child {
|
|
158
|
+
border-radius: 6px;
|
|
159
|
+
}
|
|
160
|
+
`;
|
|
161
|
+
//# sourceMappingURL=ToggleButton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToggleButton.js","sourceRoot":"","sources":["../../../core/molecules/ToggleButton.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\nimport {\n createContext,\n useContext,\n useMemo,\n useState,\n type ButtonHTMLAttributes,\n type HTMLAttributes,\n} from \"react\";\nimport styled from \"styled-components\";\nimport { Color, Typography } from \"../atoms\";\nimport { applyTypography } from \"../integrations\";\n\nexport type ToggleButtonSize = \"small\" | \"medium\" | \"large\";\n\nconst toggleButtonSizeStyles: Record<\n ToggleButtonSize,\n {\n iconButtonSize: string;\n textButtonHeight: string;\n iconSize: string;\n padding: string;\n }\n> = {\n small: {\n iconButtonSize: \"26px\",\n textButtonHeight: \"26px\",\n iconSize: \"14px\",\n padding: \"6px\",\n },\n medium: {\n iconButtonSize: \"46px\",\n textButtonHeight: \"48px\",\n iconSize: \"20px\",\n padding: \"13px\",\n },\n large: {\n iconButtonSize: \"52px\",\n textButtonHeight: \"56px\",\n iconSize: \"20px\",\n padding: \"16px\",\n },\n};\n\nconst toggleButtonTypography: Record<ToggleButtonSize, Typography.TextStyle> = {\n small: {\n ...Typography.captionMedium,\n fontSize: { small: \"10px\", large: \"10px\" },\n },\n medium: Typography.bodyPrimaryMedium,\n large: Typography.subheading2Medium,\n};\n\nexport type ToggleButtonProps = Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n \"onChange\"\n> & {\n pressed?: boolean;\n onPressedChange?: (isPressed: boolean) => void;\n size?: ToggleButtonSize;\n};\n\nconst ToggleButton = ({\n pressed,\n onPressedChange,\n onClick,\n size = \"medium\",\n type = \"button\",\n ...props\n}: ToggleButtonProps) => {\n const [isUncontrolledPressed, setIsUncontrolledPressed] = useState(false);\n const isPressed = pressed ?? isUncontrolledPressed;\n\n return (\n <ToggleButtonContainer\n {...props}\n type={type}\n data-state={isPressed ? \"on\" : \"off\"}\n $size={size}\n onClick={(event) => {\n onClick?.(event);\n if (event.defaultPrevented) return;\n\n const shouldPress = !isPressed;\n if (pressed === undefined) setIsUncontrolledPressed(shouldPress);\n onPressedChange?.(shouldPress);\n }}\n />\n );\n};\n\nexport default ToggleButton;\n\nexport type ToggleButtonGroupProps = Omit<\n HTMLAttributes<HTMLDivElement>,\n \"defaultValue\" | \"onChange\"\n> & {\n disabled?: boolean;\n size?: ToggleButtonSize;\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n};\n\ntype ToggleButtonGroupContextValue = {\n isGroupDisabled: boolean;\n selectedValue: string;\n groupSize: ToggleButtonSize;\n toggleItem: (itemValue: string) => void;\n};\n\nconst ToggleButtonGroupContext =\n createContext<ToggleButtonGroupContextValue | null>(null);\n\nexport const ToggleButtonGroup = ({\n children,\n value,\n defaultValue,\n onValueChange,\n disabled = false,\n size = \"medium\",\n ...props\n}: ToggleButtonGroupProps) => {\n const [uncontrolledValue, setUncontrolledValue] = useState(\n defaultValue ?? \"\",\n );\n const selectedValue = value ?? uncontrolledValue;\n const contextValue = useMemo<ToggleButtonGroupContextValue>(\n () => ({\n isGroupDisabled: disabled,\n selectedValue,\n groupSize: size,\n toggleItem: (itemValue) => {\n const nextSelectedValue = selectedValue === itemValue ? \"\" : itemValue;\n if (value === undefined) setUncontrolledValue(nextSelectedValue);\n onValueChange?.(nextSelectedValue);\n },\n }),\n [disabled, onValueChange, selectedValue, size, value],\n );\n\n return (\n <ToggleButtonGroupContext.Provider value={contextValue}>\n <ToggleButtonGroupContainer {...props} role=\"group\">\n {children}\n </ToggleButtonGroupContainer>\n </ToggleButtonGroupContext.Provider>\n );\n};\n\nexport type ToggleButtonGroupItemProps = Omit<\n ToggleButtonProps,\n \"onPressedChange\" | \"pressed\" | \"size\"\n> & {\n value: string;\n};\n\nexport const ToggleButtonGroupItem = ({\n value,\n disabled,\n ...props\n}: ToggleButtonGroupItemProps) => {\n const groupContext = useContext(ToggleButtonGroupContext);\n if (!groupContext)\n throw new Error(\n \"ToggleButtonGroupItem must be used within ToggleButtonGroup\",\n );\n\n return (\n <ToggleButton\n {...props}\n pressed={groupContext.selectedValue === value}\n disabled={groupContext.isGroupDisabled || disabled}\n size={groupContext.groupSize}\n onPressedChange={() => groupContext.toggleItem(value)}\n />\n );\n};\n\nconst ToggleButtonContainer = styled.button<{ $size: ToggleButtonSize }>`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n min-width: ${({ $size }) => toggleButtonSizeStyles[$size].iconButtonSize};\n height: ${({ $size }) => toggleButtonSizeStyles[$size].iconButtonSize};\n padding: ${({ $size }) => toggleButtonSizeStyles[$size].padding};\n\n ${({ $size }) => applyTypography(toggleButtonTypography[$size])}\n white-space: nowrap;\n\n color: ${Color.typography.blackHigh};\n background: ${Color.neutral.white};\n border: 1px solid ${Color.neutral.grey2};\n border-radius: 6px;\n\n cursor: pointer;\n\n &:hover:not(:disabled):not([data-state=\"on\"]) {\n background: ${Color.accent.blue3};\n }\n\n &[data-state=\"on\"] {\n position: relative;\n z-index: 1;\n\n color: ${Color.typography.whiteHigh};\n background: ${Color.brand.grantbiiBlue};\n border-color: ${Color.brand.grantbiiBlue};\n\n &:hover:not(:disabled) {\n background: ${Color.accent.blue2};\n border-color: ${Color.accent.blue2};\n }\n }\n\n &:focus-visible {\n position: relative;\n z-index: 2;\n outline: 2px solid ${Color.accent.blue2};\n outline-offset: 2px;\n }\n\n &:disabled {\n color: ${Color.typography.blackMedium};\n background: ${Color.neutral.grey2};\n cursor: not-allowed;\n }\n\n svg {\n flex: none;\n width: ${({ $size }) => toggleButtonSizeStyles[$size].iconSize};\n height: ${({ $size }) => toggleButtonSizeStyles[$size].iconSize};\n }\n\n &:not(:has(svg)) {\n height: ${({ $size }) => toggleButtonSizeStyles[$size].textButtonHeight};\n }\n`;\n\nconst ToggleButtonGroupContainer = styled.div`\n display: inline-flex;\n box-sizing: border-box;\n\n border-radius: 6px;\n outline: 1px solid ${Color.neutral.grey2};\n outline-offset: -1px;\n\n > button {\n border: 0;\n border-radius: 0;\n }\n\n > button:not(:last-child) {\n border-right: 1px solid ${Color.neutral.grey2};\n }\n\n > button:first-child {\n border-radius: 6px 0 0 6px;\n }\n\n > button:last-child {\n border-radius: 0 6px 6px 0;\n }\n\n > button:only-child {\n border-radius: 6px;\n }\n`;\n"]}
|
|
@@ -7,4 +7,5 @@ export { default as PageLoader } from "./PageLoader";
|
|
|
7
7
|
export { default as RadioButton } from "./RadioButton";
|
|
8
8
|
export { default as Textarea } from "./Textarea";
|
|
9
9
|
export { default as Tooltip, TooltipContent, TooltipTrigger, type TooltipContentProps, type TooltipProps, type TooltipSide, type TooltipTriggerProps, } from "./Tooltip";
|
|
10
|
+
export { default as ToggleButton, ToggleButtonGroup, ToggleButtonGroupItem, type ToggleButtonGroupItemProps, type ToggleButtonGroupProps, type ToggleButtonProps, type ToggleButtonSize, } from "./ToggleButton";
|
|
10
11
|
export { default as Toast, ToastProvider, useToast, type ToastOptions, type ToastProps, type ToastVariant, } from "./Toast";
|
package/core/molecules/index.js
CHANGED
|
@@ -7,5 +7,6 @@ export { default as PageLoader } from "./PageLoader";
|
|
|
7
7
|
export { default as RadioButton } from "./RadioButton";
|
|
8
8
|
export { default as Textarea } from "./Textarea";
|
|
9
9
|
export { default as Tooltip, TooltipContent, TooltipTrigger, } from "./Tooltip";
|
|
10
|
+
export { default as ToggleButton, ToggleButtonGroup, ToggleButtonGroupItem, } from "./ToggleButton";
|
|
10
11
|
export { default as Toast, ToastProvider, useToast, } from "./Toast";
|
|
11
12
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../core/molecules/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EACL,OAAO,IAAI,MAAM,EACjB,SAAS,GAGV,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EACL,OAAO,IAAI,OAAO,EAClB,cAAc,EACd,cAAc,GAKf,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,OAAO,IAAI,KAAK,EAChB,aAAa,EACb,QAAQ,GAIT,MAAM,SAAS,CAAC","sourcesContent":["export { default as Badge, RawBadge } from \"./Badge\";\nexport {\n default as Button,\n RawButton,\n type ButtonSize,\n type ButtonVariant,\n} from \"./Button\";\nexport { default as Checkbox } from \"./Checkbox\";\nexport { default as Input } from \"./Input\";\nexport { default as Overlay } from \"./Overlay\";\nexport { default as PageLoader } from \"./PageLoader\";\nexport { default as RadioButton } from \"./RadioButton\";\nexport { default as Textarea } from \"./Textarea\";\nexport {\n default as Tooltip,\n TooltipContent,\n TooltipTrigger,\n type TooltipContentProps,\n type TooltipProps,\n type TooltipSide,\n type TooltipTriggerProps,\n} from \"./Tooltip\";\nexport {\n default as Toast,\n ToastProvider,\n useToast,\n type ToastOptions,\n type ToastProps,\n type ToastVariant,\n} from \"./Toast\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../core/molecules/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EACL,OAAO,IAAI,MAAM,EACjB,SAAS,GAGV,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EACL,OAAO,IAAI,OAAO,EAClB,cAAc,EACd,cAAc,GAKf,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,OAAO,IAAI,YAAY,EACvB,iBAAiB,EACjB,qBAAqB,GAKtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,OAAO,IAAI,KAAK,EAChB,aAAa,EACb,QAAQ,GAIT,MAAM,SAAS,CAAC","sourcesContent":["export { default as Badge, RawBadge } from \"./Badge\";\nexport {\n default as Button,\n RawButton,\n type ButtonSize,\n type ButtonVariant,\n} from \"./Button\";\nexport { default as Checkbox } from \"./Checkbox\";\nexport { default as Input } from \"./Input\";\nexport { default as Overlay } from \"./Overlay\";\nexport { default as PageLoader } from \"./PageLoader\";\nexport { default as RadioButton } from \"./RadioButton\";\nexport { default as Textarea } from \"./Textarea\";\nexport {\n default as Tooltip,\n TooltipContent,\n TooltipTrigger,\n type TooltipContentProps,\n type TooltipProps,\n type TooltipSide,\n type TooltipTriggerProps,\n} from \"./Tooltip\";\nexport {\n default as ToggleButton,\n ToggleButtonGroup,\n ToggleButtonGroupItem,\n type ToggleButtonGroupItemProps,\n type ToggleButtonGroupProps,\n type ToggleButtonProps,\n type ToggleButtonSize,\n} from \"./ToggleButton\";\nexport {\n default as Toast,\n ToastProvider,\n useToast,\n type ToastOptions,\n type ToastProps,\n type ToastVariant,\n} from \"./Toast\";\n"]}
|
package/package.json
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ToggleButton } from "@/.";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/nextjs-vite";
|
|
3
|
+
declare const meta: Meta<typeof ToggleButton>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof meta>;
|
|
6
|
+
export declare const Icon: Story;
|
|
7
|
+
export declare const WithTooltip: Story;
|
|
8
|
+
export declare const Text: Story;
|
|
9
|
+
export declare const IconGroup: Story;
|
|
10
|
+
export declare const TextGroup: Story;
|
|
11
|
+
export declare const Disabled: Story;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { SystemIcon, ToggleButton, ToggleButtonGroup, ToggleButtonGroupItem, Tooltip, TooltipContent, TooltipTrigger, } from "@/.";
|
|
3
|
+
import { expect, userEvent, within } from "storybook/test";
|
|
4
|
+
const meta = {
|
|
5
|
+
title: "Molecules/Toggle Button",
|
|
6
|
+
component: ToggleButton,
|
|
7
|
+
tags: ["autodocs"],
|
|
8
|
+
args: {
|
|
9
|
+
disabled: false,
|
|
10
|
+
size: "medium",
|
|
11
|
+
},
|
|
12
|
+
argTypes: {
|
|
13
|
+
children: {
|
|
14
|
+
description: "Icon or text displayed inside the toggle button.",
|
|
15
|
+
control: false,
|
|
16
|
+
},
|
|
17
|
+
pressed: {
|
|
18
|
+
description: "Pressed state when the toggle is controlled.",
|
|
19
|
+
control: "boolean",
|
|
20
|
+
},
|
|
21
|
+
onPressedChange: {
|
|
22
|
+
description: "Called when the pressed state changes.",
|
|
23
|
+
control: false,
|
|
24
|
+
},
|
|
25
|
+
size: {
|
|
26
|
+
description: "Size of the toggle button.",
|
|
27
|
+
table: { defaultValue: { summary: '"medium"' } },
|
|
28
|
+
control: "radio",
|
|
29
|
+
options: ["small", "medium", "large"],
|
|
30
|
+
},
|
|
31
|
+
disabled: {
|
|
32
|
+
description: "Prevents the toggle button from being pressed.",
|
|
33
|
+
table: { defaultValue: { summary: "false" } },
|
|
34
|
+
control: "boolean",
|
|
35
|
+
},
|
|
36
|
+
title: {
|
|
37
|
+
description: "Native browser tooltip text for the button.",
|
|
38
|
+
control: "text",
|
|
39
|
+
},
|
|
40
|
+
type: {
|
|
41
|
+
description: "Native button behavior when used inside a form.",
|
|
42
|
+
table: { defaultValue: { summary: '"button"' } },
|
|
43
|
+
control: "radio",
|
|
44
|
+
options: ["button", "submit", "reset"],
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
export default meta;
|
|
49
|
+
export const Icon = {
|
|
50
|
+
args: { title: "Bookmark" },
|
|
51
|
+
render: (args) => (_jsx(ToggleButton, { ...args, children: _jsx(SystemIcon.BookmarkSimpleIcon, {}) })),
|
|
52
|
+
play: async ({ canvasElement }) => {
|
|
53
|
+
const toggleButton = within(canvasElement).getByRole("button");
|
|
54
|
+
await expect(toggleButton).toHaveAttribute("data-state", "off");
|
|
55
|
+
await userEvent.click(toggleButton);
|
|
56
|
+
await expect(toggleButton).toHaveAttribute("data-state", "on");
|
|
57
|
+
await userEvent.click(toggleButton);
|
|
58
|
+
await expect(toggleButton).toHaveAttribute("data-state", "off");
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
export const WithTooltip = {
|
|
62
|
+
render: (args) => (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { children: _jsx(ToggleButton, { ...args, children: _jsx(SystemIcon.BookmarkSimpleIcon, {}) }) }), _jsx(TooltipContent, { sideOffset: 8, children: "Bookmark" })] })),
|
|
63
|
+
};
|
|
64
|
+
export const Text = {
|
|
65
|
+
render: (args) => _jsx(ToggleButton, { ...args, children: "Bookmark" }),
|
|
66
|
+
};
|
|
67
|
+
export const IconGroup = {
|
|
68
|
+
args: { size: "small" },
|
|
69
|
+
render: (args) => (_jsxs(ToggleButtonGroup, { defaultValue: "bookmark", disabled: args.disabled, size: args.size, children: [_jsx(ToggleButtonGroupItem, { value: "bookmark", title: "Bookmarks", children: _jsx(SystemIcon.BookmarkSimpleIcon, {}) }), _jsx(ToggleButtonGroupItem, { value: "grid", title: "Grid view", children: _jsx(SystemIcon.GridFourIcon, {}) }), _jsx(ToggleButtonGroupItem, { value: "list", title: "List view", children: _jsx(SystemIcon.ListIcon, {}) })] })),
|
|
70
|
+
};
|
|
71
|
+
export const TextGroup = {
|
|
72
|
+
args: { size: "small" },
|
|
73
|
+
render: (args) => (_jsxs(ToggleButtonGroup, { defaultValue: "first", disabled: args.disabled, size: args.size, children: [_jsx(ToggleButtonGroupItem, { value: "first", children: "Bookmark" }), _jsx(ToggleButtonGroupItem, { value: "second", children: "Bookmark" }), _jsx(ToggleButtonGroupItem, { value: "third", children: "Bookmark" })] })),
|
|
74
|
+
};
|
|
75
|
+
export const Disabled = {
|
|
76
|
+
args: { disabled: true, title: "Bookmark" },
|
|
77
|
+
render: Icon.render,
|
|
78
|
+
};
|
|
79
|
+
//# sourceMappingURL=ToggleButton.stories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToggleButton.stories.js","sourceRoot":"","sources":["../../../stories/molecules/ToggleButton.stories.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n SystemIcon,\n ToggleButton,\n ToggleButtonGroup,\n ToggleButtonGroupItem,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"@/.\";\nimport type { Meta, StoryObj } from \"@storybook/nextjs-vite\";\nimport { expect, userEvent, within } from \"storybook/test\";\n\nconst meta: Meta<typeof ToggleButton> = {\n title: \"Molecules/Toggle Button\",\n component: ToggleButton,\n tags: [\"autodocs\"],\n args: {\n disabled: false,\n size: \"medium\",\n },\n argTypes: {\n children: {\n description: \"Icon or text displayed inside the toggle button.\",\n control: false,\n },\n pressed: {\n description: \"Pressed state when the toggle is controlled.\",\n control: \"boolean\",\n },\n onPressedChange: {\n description: \"Called when the pressed state changes.\",\n control: false,\n },\n size: {\n description: \"Size of the toggle button.\",\n table: { defaultValue: { summary: '\"medium\"' } },\n control: \"radio\",\n options: [\"small\", \"medium\", \"large\"],\n },\n disabled: {\n description: \"Prevents the toggle button from being pressed.\",\n table: { defaultValue: { summary: \"false\" } },\n control: \"boolean\",\n },\n title: {\n description: \"Native browser tooltip text for the button.\",\n control: \"text\",\n },\n type: {\n description: \"Native button behavior when used inside a form.\",\n table: { defaultValue: { summary: '\"button\"' } },\n control: \"radio\",\n options: [\"button\", \"submit\", \"reset\"],\n },\n },\n};\n\nexport default meta;\n\ntype Story = StoryObj<typeof meta>;\n\nexport const Icon: Story = {\n args: { title: \"Bookmark\" },\n render: (args) => (\n <ToggleButton {...args}>\n <SystemIcon.BookmarkSimpleIcon />\n </ToggleButton>\n ),\n play: async ({ canvasElement }) => {\n const toggleButton = within(canvasElement).getByRole(\"button\");\n await expect(toggleButton).toHaveAttribute(\"data-state\", \"off\");\n await userEvent.click(toggleButton);\n await expect(toggleButton).toHaveAttribute(\"data-state\", \"on\");\n await userEvent.click(toggleButton);\n await expect(toggleButton).toHaveAttribute(\"data-state\", \"off\");\n },\n};\n\nexport const WithTooltip: Story = {\n render: (args) => (\n <Tooltip>\n <TooltipTrigger>\n <ToggleButton {...args}>\n <SystemIcon.BookmarkSimpleIcon />\n </ToggleButton>\n </TooltipTrigger>\n <TooltipContent sideOffset={8}>Bookmark</TooltipContent>\n </Tooltip>\n ),\n};\n\nexport const Text: Story = {\n render: (args) => <ToggleButton {...args}>Bookmark</ToggleButton>,\n};\n\nexport const IconGroup: Story = {\n args: { size: \"small\" },\n render: (args) => (\n <ToggleButtonGroup\n defaultValue=\"bookmark\"\n disabled={args.disabled}\n size={args.size}\n >\n <ToggleButtonGroupItem value=\"bookmark\" title=\"Bookmarks\">\n <SystemIcon.BookmarkSimpleIcon />\n </ToggleButtonGroupItem>\n <ToggleButtonGroupItem value=\"grid\" title=\"Grid view\">\n <SystemIcon.GridFourIcon />\n </ToggleButtonGroupItem>\n <ToggleButtonGroupItem value=\"list\" title=\"List view\">\n <SystemIcon.ListIcon />\n </ToggleButtonGroupItem>\n </ToggleButtonGroup>\n ),\n};\n\nexport const TextGroup: Story = {\n args: { size: \"small\" },\n render: (args) => (\n <ToggleButtonGroup\n defaultValue=\"first\"\n disabled={args.disabled}\n size={args.size}\n >\n <ToggleButtonGroupItem value=\"first\">Bookmark</ToggleButtonGroupItem>\n <ToggleButtonGroupItem value=\"second\">Bookmark</ToggleButtonGroupItem>\n <ToggleButtonGroupItem value=\"third\">Bookmark</ToggleButtonGroupItem>\n </ToggleButtonGroup>\n ),\n};\n\nexport const Disabled: Story = {\n args: { disabled: true, title: \"Bookmark\" },\n render: Icon.render,\n};\n"]}
|