lucentia-ui 0.2.8 → 0.2.9
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/dist/components/Button/types.d.ts +5 -2
- package/dist/components/Extra/ThemeSwitch/ThemeSwitch.module.css +14 -13
- package/dist/components/IconButton/IconButton.d.ts +3 -0
- package/dist/components/IconButton/IconButton.js +18 -0
- package/dist/components/IconButton/IconButton.module.css +154 -0
- package/dist/components/IconButton/IconButton.stories.d.ts +9 -0
- package/dist/components/IconButton/IconButton.stories.js +60 -0
- package/dist/components/IconButton/index.d.ts +2 -0
- package/dist/components/IconButton/index.js +2 -0
- package/dist/components/IconButton/types.d.ts +13 -0
- package/dist/components/IconButton/types.js +1 -0
- package/dist/icons/Home.d.ts +8 -0
- package/dist/icons/Home.js +5 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +1 -1
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import type React from "react";
|
|
2
|
+
export type ButtonVariant = "ghost" | "primary" | "secondary" | "danger";
|
|
3
|
+
export type ButtonSize = "sm" | "md";
|
|
1
4
|
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
2
|
-
variant?:
|
|
3
|
-
size?:
|
|
5
|
+
variant?: ButtonVariant;
|
|
6
|
+
size?: ButtonSize;
|
|
4
7
|
fullWidth?: boolean;
|
|
5
8
|
}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
font-size: 18px;
|
|
3
3
|
position: relative;
|
|
4
4
|
display: inline-block;
|
|
5
|
-
width:
|
|
6
|
-
height:
|
|
5
|
+
width: 72px;
|
|
6
|
+
height: 40px;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
/* input単体にスタイルを当てる */
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
left: 0;
|
|
21
21
|
right: 0;
|
|
22
22
|
bottom: 0;
|
|
23
|
-
background
|
|
23
|
+
background: var(--color-surface);
|
|
24
|
+
box-shadow: var(--shadow-sm-in);
|
|
24
25
|
transition: 0.4s;
|
|
25
26
|
border-radius: 30px;
|
|
26
27
|
overflow: hidden;
|
|
@@ -28,12 +29,12 @@
|
|
|
28
29
|
|
|
29
30
|
.circle {
|
|
30
31
|
position: absolute;
|
|
31
|
-
height: 1.
|
|
32
|
-
width: 1.
|
|
32
|
+
height: 1.1em;
|
|
33
|
+
width: 1.1em;
|
|
33
34
|
border-radius: 20px;
|
|
34
|
-
left: 0.
|
|
35
|
-
bottom: 0.
|
|
36
|
-
background-color:
|
|
35
|
+
left: 0.6em;
|
|
36
|
+
bottom: 0.45em;
|
|
37
|
+
background-color: var(--color-primary);
|
|
37
38
|
transition: 0.4s;
|
|
38
39
|
}
|
|
39
40
|
|
|
@@ -67,9 +68,9 @@
|
|
|
67
68
|
left: -100%;
|
|
68
69
|
top: 50%;
|
|
69
70
|
opacity: 0;
|
|
70
|
-
background
|
|
71
|
-
width:
|
|
72
|
-
height:
|
|
71
|
+
background: var(--color-background);
|
|
72
|
+
width: 1rem;
|
|
73
|
+
height: 1rem;
|
|
73
74
|
border-radius: 99999px;
|
|
74
75
|
transform: translateY(-50%);
|
|
75
76
|
transition: all 0.4s;
|
|
@@ -82,8 +83,8 @@
|
|
|
82
83
|
left: 50%;
|
|
83
84
|
width: 0.25rem;
|
|
84
85
|
height: 0.25rem;
|
|
85
|
-
background-color:
|
|
86
|
-
border-radius:
|
|
86
|
+
background-color: var(--color-primary);
|
|
87
|
+
border-radius: 4rem;
|
|
87
88
|
transition: all 0.4s;
|
|
88
89
|
}
|
|
89
90
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import styles from "./IconButton.module.css";
|
|
5
|
+
export const IconButton = React.forwardRef((props, ref) => {
|
|
6
|
+
const { icon, children, variant = "ghost", size = "md", className, ...rest } = props;
|
|
7
|
+
// a11y guard (dev only)
|
|
8
|
+
if (process.env.NODE_ENV !== "production" &&
|
|
9
|
+
!children &&
|
|
10
|
+
!rest["aria-label"]) {
|
|
11
|
+
console.warn("IconButton: icon-only usage requires `aria-label`.");
|
|
12
|
+
}
|
|
13
|
+
return (_jsxs("button", { ref: ref, className: clsx(styles.iconButton, styles[variant], styles[size], {
|
|
14
|
+
[styles.iconOnly]: !children,
|
|
15
|
+
[styles.withText]: !!children,
|
|
16
|
+
}, className), ...rest, children: [_jsx("span", { className: styles.icon, children: icon }), children && _jsx("span", { className: styles.text, children: children })] }));
|
|
17
|
+
});
|
|
18
|
+
IconButton.displayName = "IconButton";
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
.iconButton {
|
|
2
|
+
display: inline-flex;
|
|
3
|
+
align-items: center;
|
|
4
|
+
justify-content: center;
|
|
5
|
+
gap: 0.5rem;
|
|
6
|
+
width: fit-content;
|
|
7
|
+
height: fit-content;
|
|
8
|
+
font-family: var(--font);
|
|
9
|
+
font-weight: var(--font-weight-medium);
|
|
10
|
+
border: 2px solid transparent;
|
|
11
|
+
cursor: pointer;
|
|
12
|
+
|
|
13
|
+
border-radius: var(--radius-sm);
|
|
14
|
+
|
|
15
|
+
transition:
|
|
16
|
+
box-shadow 0.2s ease,
|
|
17
|
+
opacity 0.2s ease,
|
|
18
|
+
background 0.25s ease-in-out,
|
|
19
|
+
color 0.25s ease;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
/* ===== Variant ===== */
|
|
25
|
+
.ghost {
|
|
26
|
+
background: var(--color-surface);
|
|
27
|
+
color: var(--color-on-surface);
|
|
28
|
+
}
|
|
29
|
+
.ghost:hover:not(:disabled) {
|
|
30
|
+
background: var(--color-surface-container);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
.primary {
|
|
35
|
+
background: var(--color-primary-container);
|
|
36
|
+
color: var(--color-on-primary-container);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.sm.primary:hover:not(:disabled) {
|
|
40
|
+
border: 2px solid var(--color-primary);
|
|
41
|
+
box-shadow:
|
|
42
|
+
0 0 2px var(--color-primary),
|
|
43
|
+
0 0 4px var(--color-primary);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.md.primary:hover:not(:disabled) {
|
|
47
|
+
border: 2px solid var(--color-primary);
|
|
48
|
+
box-shadow:
|
|
49
|
+
0 0 4px var(--color-primary),
|
|
50
|
+
0 0 8px var(--color-primary);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.md.primary:hover:not(:disabled) {
|
|
54
|
+
border: 2px solid var(--color-primary);
|
|
55
|
+
box-shadow:
|
|
56
|
+
0 0 4px var(--color-primary),
|
|
57
|
+
0 0 8px var(--color-primary);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.secondary {
|
|
61
|
+
background: var(--color-secondary-container);
|
|
62
|
+
color: var(--color-on-secondary-container);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.sm.secondary:hover:not(:disabled) {
|
|
66
|
+
border: 2px solid var(--color-secondary);
|
|
67
|
+
box-shadow:
|
|
68
|
+
0 0 2px var(--color-secondary),
|
|
69
|
+
0 0 4px var(--color-secondary);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.md.secondary:hover:not(:disabled) {
|
|
73
|
+
border: 2px solid var(--color-secondary);
|
|
74
|
+
box-shadow:
|
|
75
|
+
0 0 4px var(--color-secondary),
|
|
76
|
+
0 0 8px var(--color-secondary);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
.danger {
|
|
81
|
+
background: var(--color-error-container);
|
|
82
|
+
color: var(--color-on-error-container);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.sm.danger:hover:not(:disabled) {
|
|
86
|
+
border: 2px solid var(--color-error);
|
|
87
|
+
box-shadow:
|
|
88
|
+
0 0 2px var(--color-error),
|
|
89
|
+
0 0 4px var(--color-error);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.md.danger:hover:not(:disabled) {
|
|
93
|
+
border: 2px solid var(--color-error);
|
|
94
|
+
box-shadow:
|
|
95
|
+
0 0 4px var(--color-error),
|
|
96
|
+
0 0 8px var(--color-error);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.md.danger:active:not(:disabled) {
|
|
100
|
+
box-shadow: none;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
/* ===== Size ===== */
|
|
105
|
+
|
|
106
|
+
.sm {
|
|
107
|
+
padding: var(--space-xs) var(--space-lg);
|
|
108
|
+
font-size: var(--font-size-14);
|
|
109
|
+
box-shadow: var(--shadow-sm);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.md {
|
|
113
|
+
padding: var(--space-sm) var(--space-2xl);
|
|
114
|
+
font-size: var(--font-size-16);
|
|
115
|
+
box-shadow: var(--shadow-md);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/* icon-only */
|
|
119
|
+
.sm.iconOnly {
|
|
120
|
+
padding: var(--space-xs) var(--space-md);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.md.iconOnly {
|
|
124
|
+
padding: var(--space-sm) var(--space-md);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
.icon {
|
|
130
|
+
display: inline-flex;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.text {
|
|
134
|
+
white-space: nowrap;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
/* ===== State ===== */
|
|
140
|
+
|
|
141
|
+
.sm.iconButton:active:not(:disabled),
|
|
142
|
+
.md.iconButton:active:not(:disabled),
|
|
143
|
+
.iconButton[data-state="pressed"] {
|
|
144
|
+
box-shadow: none;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.iconButton:focus-visible {
|
|
148
|
+
outline: none;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.iconButton:disabled {
|
|
152
|
+
opacity: 0.5;
|
|
153
|
+
cursor: not-allowed;
|
|
154
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { IconButton } from "./IconButton";
|
|
3
|
+
declare const meta: Meta<typeof IconButton>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof IconButton>;
|
|
6
|
+
export declare const Default: Story;
|
|
7
|
+
export declare const State: Story;
|
|
8
|
+
export declare const Variants: Story;
|
|
9
|
+
export declare const Sizes: Story;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { IconButton } from "./IconButton";
|
|
3
|
+
// Storybook only
|
|
4
|
+
import { HomeIcon } from "../../icons/Home";
|
|
5
|
+
const meta = {
|
|
6
|
+
title: "Components/IconButton",
|
|
7
|
+
component: IconButton,
|
|
8
|
+
args: {
|
|
9
|
+
children: "IconButton",
|
|
10
|
+
variant: "ghost",
|
|
11
|
+
size: "md",
|
|
12
|
+
},
|
|
13
|
+
argTypes: {
|
|
14
|
+
variant: {
|
|
15
|
+
control: "radio",
|
|
16
|
+
options: ["ghost", "primary", "secondary", "danger"],
|
|
17
|
+
description: "Buttonの表示バリエーション",
|
|
18
|
+
},
|
|
19
|
+
size: {
|
|
20
|
+
control: "radio",
|
|
21
|
+
options: ["sm", "md"],
|
|
22
|
+
description: "Buttonのサイズ",
|
|
23
|
+
},
|
|
24
|
+
disabled: {
|
|
25
|
+
control: "boolean",
|
|
26
|
+
description: "無効状態",
|
|
27
|
+
},
|
|
28
|
+
onClick: {
|
|
29
|
+
action: "clicked",
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
export default meta;
|
|
34
|
+
export const Default = {
|
|
35
|
+
render: () => _jsx(IconButton, { icon: _jsx(HomeIcon, {}), variant: "ghost" }),
|
|
36
|
+
};
|
|
37
|
+
export const State = {
|
|
38
|
+
render: () => (_jsxs("div", { style: {
|
|
39
|
+
display: "flex",
|
|
40
|
+
flexDirection: "column",
|
|
41
|
+
alignItems: "flex-start",
|
|
42
|
+
gap: 32,
|
|
43
|
+
}, children: [_jsx(IconButton, { icon: _jsx(HomeIcon, {}), variant: "ghost", children: "Default" }), _jsx(IconButton, { icon: _jsx(HomeIcon, {}), variant: "ghost", style: { background: "var(--color-surface-container)" }, "data-state": "pressed", children: "Pressed" }), _jsx(IconButton, { icon: _jsx(HomeIcon, {}), variant: "ghost", disabled: true, children: "Disabled" })] })),
|
|
44
|
+
};
|
|
45
|
+
export const Variants = {
|
|
46
|
+
render: () => (_jsxs("div", { style: {
|
|
47
|
+
display: "flex",
|
|
48
|
+
flexDirection: "column",
|
|
49
|
+
alignItems: "flex-start",
|
|
50
|
+
gap: 32,
|
|
51
|
+
}, children: [_jsx(IconButton, { icon: _jsx(HomeIcon, {}), variant: "ghost", children: "Ghost" }), _jsx(IconButton, { icon: _jsx(HomeIcon, {}), variant: "primary", children: "Primary" }), _jsx(IconButton, { icon: _jsx(HomeIcon, {}), variant: "secondary", children: "Secondary" }), _jsx(IconButton, { icon: _jsx(HomeIcon, {}), variant: "danger", children: "Danger" })] })),
|
|
52
|
+
};
|
|
53
|
+
export const Sizes = {
|
|
54
|
+
render: () => (_jsxs("div", { style: {
|
|
55
|
+
display: "flex",
|
|
56
|
+
flexDirection: "column",
|
|
57
|
+
alignItems: "flex-start",
|
|
58
|
+
gap: 32,
|
|
59
|
+
}, children: [_jsx(IconButton, { icon: _jsx(HomeIcon, { size: 20 }), size: "sm", children: "Small" }), _jsx(IconButton, { icon: _jsx(HomeIcon, {}), size: "md", children: "Medium" })] })),
|
|
60
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type React from "react";
|
|
2
|
+
import type { ButtonVariant, ButtonSize } from "../Button/types";
|
|
3
|
+
export interface IconButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "children"> {
|
|
4
|
+
/** Icon element (required) */
|
|
5
|
+
icon: React.ReactNode;
|
|
6
|
+
/** Optional text */
|
|
7
|
+
children?: React.ReactNode;
|
|
8
|
+
/** Inherit from Button */
|
|
9
|
+
variant?: ButtonVariant;
|
|
10
|
+
size?: ButtonSize;
|
|
11
|
+
/** icon-only の場合に必須 */
|
|
12
|
+
"aria-label"?: string;
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
export const HomeIcon = ({ size = 24, color = "currentColor", className = "", }) => {
|
|
3
|
+
return (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", className: className, children: _jsx("path", { d: "M13.5 14H10.5C9.94772 14 9.5 14.4477 9.5 15V20.5C9.5 21.0523 9.05228 21.5 8.5 21.5H4C3.44772 21.5 3 21.0523 3 20.5V10.931C3 10.6559 3.11335 10.3929 3.31338 10.204L11.3134 2.64848C11.6988 2.28449 12.3012 2.28449 12.6866 2.64848L20.6866 10.204C20.8866 10.3929 21 10.6559 21 10.931V20.5C21 21.0523 20.5523 21.5 20 21.5H15.5C14.9477 21.5 14.5 21.0523 14.5 20.5V15C14.5 14.4477 14.0523 14 13.5 14Z", fill: "currentColor" }) }));
|
|
4
|
+
};
|
|
5
|
+
export default HomeIcon;
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export * from "./components/Checkbox";
|
|
|
5
5
|
export * from "./components/Divider";
|
|
6
6
|
export * from "./components/Radio";
|
|
7
7
|
export * from "./components/Input";
|
|
8
|
+
export * from "./components/IconButton";
|
|
8
9
|
export * from "./components/Textarea";
|
|
9
10
|
export * from "./components/Typography";
|
|
10
11
|
export * from "./components/Select";
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ export * from "./components/Checkbox";
|
|
|
6
6
|
export * from "./components/Divider";
|
|
7
7
|
export * from "./components/Radio";
|
|
8
8
|
export * from "./components/Input";
|
|
9
|
+
export * from "./components/IconButton";
|
|
9
10
|
export * from "./components/Textarea";
|
|
10
11
|
export * from "./components/Typography";
|
|
11
12
|
export * from "./components/Select";
|
package/package.json
CHANGED