lucentia-ui 0.2.7 → 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.
Files changed (35) hide show
  1. package/dist/components/Button/Button.d.ts +1 -1
  2. package/dist/components/Button/Button.js +2 -2
  3. package/dist/components/Button/Button.module.css +6 -0
  4. package/dist/components/Button/types.d.ts +6 -2
  5. package/dist/components/Checkbox/Checkbox.module.css +4 -4
  6. package/dist/components/Extra/Clock/Clock.d.ts +1 -0
  7. package/dist/components/Extra/Clock/Clock.js +27 -0
  8. package/dist/components/Extra/Clock/Clock.module.css +88 -0
  9. package/dist/components/Extra/Clock/Clock.stories.d.ts +6 -0
  10. package/dist/components/Extra/Clock/Clock.stories.js +7 -0
  11. package/dist/components/Extra/Clock/index.d.ts +1 -0
  12. package/dist/components/Extra/Clock/index.js +1 -0
  13. package/dist/components/Extra/ThemeSwitch/ThemeSwitch.d.ts +3 -0
  14. package/dist/components/Extra/ThemeSwitch/ThemeSwitch.js +17 -0
  15. package/dist/components/Extra/ThemeSwitch/ThemeSwitch.module.css +99 -0
  16. package/dist/components/Extra/ThemeSwitch/ThemeSwitch.stories.d.ts +7 -0
  17. package/dist/components/Extra/ThemeSwitch/ThemeSwitch.stories.js +13 -0
  18. package/dist/components/Extra/ThemeSwitch/types.d.ts +13 -0
  19. package/dist/components/Extra/ThemeSwitch/types.js +1 -0
  20. package/dist/components/IconButton/IconButton.d.ts +3 -0
  21. package/dist/components/IconButton/IconButton.js +18 -0
  22. package/dist/components/IconButton/IconButton.module.css +154 -0
  23. package/dist/components/IconButton/IconButton.stories.d.ts +9 -0
  24. package/dist/components/IconButton/IconButton.stories.js +60 -0
  25. package/dist/components/IconButton/index.d.ts +2 -0
  26. package/dist/components/IconButton/index.js +2 -0
  27. package/dist/components/IconButton/types.d.ts +13 -0
  28. package/dist/components/IconButton/types.js +1 -0
  29. package/dist/components/Radio/Radio.module.css +2 -2
  30. package/dist/components/Switch/Switch.module.css +5 -5
  31. package/dist/icons/Home.d.ts +8 -0
  32. package/dist/icons/Home.js +5 -0
  33. package/dist/index.d.ts +1 -0
  34. package/dist/index.js +1 -0
  35. package/package.json +1 -1
@@ -1,2 +1,2 @@
1
1
  import { ButtonProps } from "./types";
2
- export declare const Button: ({ variant, size, className, ...props }: ButtonProps) => import("react/jsx-runtime").JSX.Element;
2
+ export declare const Button: ({ variant, size, fullWidth, className, ...props }: ButtonProps) => import("react/jsx-runtime").JSX.Element;
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import styles from "./Button.module.css";
3
3
  import clsx from "clsx";
4
- export const Button = ({ variant = "ghost", size = "md", className, ...props }) => {
5
- return (_jsx("button", { className: clsx(styles.button, styles[variant], styles[size], className), ...props }));
4
+ export const Button = ({ variant = "ghost", size = "md", fullWidth = false, className, ...props }) => {
5
+ return (_jsx("button", { className: clsx(styles.button, styles[variant], styles[size], fullWidth && styles.fullWidth, className), ...props }));
6
6
  };
@@ -109,6 +109,12 @@
109
109
  box-shadow: var(--shadow-md);
110
110
  }
111
111
 
112
+
113
+ /* ===== full width ===== */
114
+ .fullWidth {
115
+ width: 100%;
116
+ }
117
+
112
118
  /* ===== State ===== */
113
119
 
114
120
  .sm.button:active:not(:disabled),
@@ -1,4 +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?: "ghost" | "primary" | "secondary" | "danger";
3
- size?: "sm" | "md";
5
+ variant?: ButtonVariant;
6
+ size?: ButtonSize;
7
+ fullWidth?: boolean;
4
8
  }
@@ -19,21 +19,21 @@
19
19
  }
20
20
 
21
21
  .control {
22
- width: 32px;
23
- height: 32px;
22
+ width: 28px;
23
+ height: 28px;
24
24
  border-radius: var(--radius-sm);
25
25
  background: var(--color-surface-container);
26
26
  box-shadow: var(--shadow-md-in);
27
27
  position: relative;
28
28
  background-repeat: no-repeat;
29
29
  background-position: center;
30
- background-size: 32px 32px;
30
+ background-size: 24px 24px;
31
31
  transition: background-color 0.2s ease;
32
32
  }
33
33
 
34
34
  /* checked */
35
35
  .input:checked + .control {
36
- background-color: var(--color-primary);
36
+ background: var(--color-primary);
37
37
  background-image: var(--icon-check);
38
38
  }
39
39
  /* focus */
@@ -0,0 +1 @@
1
+ export declare function Clock(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,27 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useState } from "react";
4
+ import styles from "./Clock.module.css";
5
+ export function Clock() {
6
+ const [time, setTime] = useState(null);
7
+ useEffect(() => {
8
+ const update = () => setTime(new Date());
9
+ update(); // 初回
10
+ const timer = setInterval(update, 1000);
11
+ return () => clearInterval(timer);
12
+ }, []);
13
+ if (!time) {
14
+ return _jsx("div", { className: styles.clock });
15
+ }
16
+ const seconds = time.getSeconds();
17
+ const minutes = time.getMinutes();
18
+ const hours = time.getHours() % 12;
19
+ const secondDeg = seconds * 6;
20
+ const minuteDeg = minutes * 6 + seconds * 0.1;
21
+ const hourDeg = hours * 30 + minutes * 0.5;
22
+ return (_jsxs("div", { className: styles.clock, children: [_jsx("div", { className: styles.dial, children: Array.from({ length: 60 }).map((_, i) => (_jsx("span", { className: [
23
+ styles.tick,
24
+ i % 5 === 0 ? styles.major : styles.minor,
25
+ i % 15 === 0 ? styles.quarter : "",
26
+ ].join(" "), style: { transform: `rotate(${i * 6}deg)` } }, i))) }), _jsx("div", { className: `${styles.hand} ${styles.hour}`, style: { transform: `rotate(${hourDeg}deg)` } }), _jsx("div", { className: `${styles.hand} ${styles.minute}`, style: { transform: `rotate(${minuteDeg}deg)` } }), _jsx("div", { className: `${styles.hand} ${styles.second}`, style: { transform: `rotate(${secondDeg}deg)` } }), _jsx("div", { className: styles.center })] }));
27
+ }
@@ -0,0 +1,88 @@
1
+ .clock {
2
+ position: relative;
3
+ width: 240px;
4
+ height: 240px;
5
+ border-radius: 50%;
6
+ background: var(--color-background);
7
+ border: 2px solid var(--color-surface);
8
+ box-sizing: border-box;
9
+ box-shadow: var(--shadow-md),var(--shadow-md-in);
10
+ }
11
+
12
+ /* 共通の針 */
13
+ .hand {
14
+ position: absolute;
15
+ left: 50%;
16
+ bottom: 50%;
17
+ transform-origin: bottom center;
18
+ transform: translateX(-50%);
19
+ box-shadow: 0px 0px 4px var(--color-shadow-d);
20
+ border-radius: 2px;
21
+ }
22
+
23
+ /* 時針 */
24
+ .hour {
25
+ width: 5px;
26
+ height: 64px;
27
+ background: var(--color-secondary);
28
+ }
29
+
30
+ /* 分針 */
31
+ .minute {
32
+ width: 5px;
33
+ height: 104px;
34
+ background: var(--color-secondary);
35
+ }
36
+
37
+ /* 秒針 */
38
+ .second {
39
+ width: 2px;
40
+ height: 100px;
41
+ background: var(--color-error);
42
+ }
43
+
44
+ /* 中心の丸 */
45
+ .center {
46
+ position: absolute;
47
+ top: 50%;
48
+ left: 50%;
49
+ width: 12px;
50
+ height: 12px;
51
+ background: var(--color-background);
52
+ box-shadow: var(--shadow-sm);
53
+ border-radius: 50%;
54
+ transform: translate(-50%, -50%);
55
+ z-index: 10;
56
+ }
57
+
58
+
59
+
60
+ /* ===== 文字盤 ===== */
61
+
62
+ .dial {
63
+ position: absolute;
64
+ inset: 0;
65
+ border-radius: 50%;
66
+ }
67
+
68
+ /* 共通目盛り */
69
+ .tick {
70
+ position: absolute;
71
+ left: 50%;
72
+ top: 8px;
73
+ transform-origin: center 112px;
74
+ background: var(--color-on-surface-variant);
75
+ }
76
+
77
+ /* 5分ごとの目盛 */
78
+ .major {
79
+ width: 2.5px;
80
+ height: 14px;
81
+ }
82
+
83
+ /* 12・3・6・9 */
84
+ .quarter {
85
+ height: 21px;
86
+ width: 3px;
87
+ background: var(--color-on-surface-variant);
88
+ }
@@ -0,0 +1,6 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Clock } from "./Clock";
3
+ declare const meta: Meta<typeof Clock>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof Clock>;
6
+ export declare const Default: Story;
@@ -0,0 +1,7 @@
1
+ import { Clock } from "./Clock";
2
+ const meta = {
3
+ title: "Components/Extra/Clock",
4
+ component: Clock,
5
+ };
6
+ export default meta;
7
+ export const Default = {};
@@ -0,0 +1 @@
1
+ export * from "./Clock";
@@ -0,0 +1 @@
1
+ export * from "./Clock";
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ import type { ThemeSwitchProps } from "./types";
3
+ export declare const ThemeSwitch: React.FC<ThemeSwitchProps>;
@@ -0,0 +1,17 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import styles from "./ThemeSwitch.module.css";
3
+ import clsx from "clsx";
4
+ export const ThemeSwitch = ({ checked, defaultChecked, onChange, onCheckedChange, disabled = false, id, name, className, }) => {
5
+ const handleChange = (e) => {
6
+ if (disabled)
7
+ return;
8
+ onChange === null || onChange === void 0 ? void 0 : onChange(e);
9
+ onCheckedChange === null || onCheckedChange === void 0 ? void 0 : onCheckedChange(e.target.checked);
10
+ };
11
+ return (_jsxs("label", { className: clsx(styles.themeSwitch, className), style: {
12
+ opacity: disabled ? 0.6 : 1,
13
+ cursor: disabled ? "not-allowed" : "pointer",
14
+ }, children: [_jsx("input", { type: "checkbox", id: id, name: name,
15
+ // CSS Modules側のクラス名と一致させる(styles.input もしくは styles.themeSwitchCheckbox)
16
+ className: styles.themeSwitchCheckbox, checked: checked, defaultChecked: defaultChecked, disabled: disabled, onChange: handleChange }), _jsx("span", { className: styles.slider, children: _jsxs("span", { className: styles.circle, children: [[...Array(8)].map((_, i) => (_jsx("span", { className: clsx(styles.shine, styles[`shine-${i + 1}`]) }, i))), _jsx("span", { className: styles.moon })] }) })] }));
17
+ };
@@ -0,0 +1,99 @@
1
+ .themeSwitch {
2
+ font-size: 18px;
3
+ position: relative;
4
+ display: inline-block;
5
+ width: 72px;
6
+ height: 40px;
7
+ }
8
+
9
+ /* input単体にスタイルを当てる */
10
+ .input {
11
+ opacity: 0;
12
+ width: 0;
13
+ height: 0;
14
+ }
15
+
16
+ .slider {
17
+ position: absolute;
18
+ cursor: pointer;
19
+ top: 0;
20
+ left: 0;
21
+ right: 0;
22
+ bottom: 0;
23
+ background: var(--color-surface);
24
+ box-shadow: var(--shadow-sm-in);
25
+ transition: 0.4s;
26
+ border-radius: 30px;
27
+ overflow: hidden;
28
+ }
29
+
30
+ .circle {
31
+ position: absolute;
32
+ height: 1.1em;
33
+ width: 1.1em;
34
+ border-radius: 20px;
35
+ left: 0.6em;
36
+ bottom: 0.45em;
37
+ background-color: var(--color-primary);
38
+ transition: 0.4s;
39
+ }
40
+
41
+ /* ThemeSwitch.module.css */
42
+
43
+ /* inputのクラス名をTSXと合わせる */
44
+ .themeSwitchCheckbox {
45
+ opacity: 0;
46
+ width: 0;
47
+ height: 0;
48
+ position: absolute;
49
+ }
50
+
51
+ /* チェック時の隣接セレクタを調整 */
52
+ .themeSwitchCheckbox:checked + .slider .circle {
53
+ transform: rotate(0deg) translateX(1.5em) !important;
54
+ }
55
+
56
+ .themeSwitchCheckbox:checked + .slider .circle .shine {
57
+ transform: translate(0%, 0%) !important;
58
+ }
59
+
60
+ .themeSwitchCheckbox:checked + .slider .circle .moon {
61
+ left: -10%;
62
+ opacity: 1;
63
+ transform: translateY(-60%);
64
+ }
65
+
66
+ .moon {
67
+ position: absolute;
68
+ left: -100%;
69
+ top: 50%;
70
+ opacity: 0;
71
+ background: var(--color-background);
72
+ width: 1rem;
73
+ height: 1rem;
74
+ border-radius: 99999px;
75
+ transform: translateY(-50%);
76
+ transition: all 0.4s;
77
+ }
78
+
79
+ .shine {
80
+ display: block;
81
+ position: absolute;
82
+ top: 50%;
83
+ left: 50%;
84
+ width: 0.25rem;
85
+ height: 0.25rem;
86
+ background-color: var(--color-primary);
87
+ border-radius: 4rem;
88
+ transition: all 0.4s;
89
+ }
90
+
91
+ /* 個別のshine配置 */
92
+ .shine-1 { transform: translate(-50%, -375%); }
93
+ .shine-2 { transform: translate(175%, -275%); }
94
+ .shine-3 { transform: translate(275%, -50%); }
95
+ .shine-4 { transform: translate(175%, 175%); }
96
+ .shine-5 { transform: translate(-50%, 275%); }
97
+ .shine-6 { transform: translate(-275%, 175%); }
98
+ .shine-7 { transform: translate(-375%, -50%); }
99
+ .shine-8 { transform: translate(-275%, -275%); }
@@ -0,0 +1,7 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { ThemeSwitch } from "./ThemeSwitch";
3
+ declare const meta: Meta<typeof ThemeSwitch>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof ThemeSwitch>;
6
+ export declare const Default: Story;
7
+ export declare const State: Story;
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { ThemeSwitch } from "./ThemeSwitch";
3
+ const meta = {
4
+ title: "Components/Extra/ThemeSwitch",
5
+ component: ThemeSwitch,
6
+ };
7
+ export default meta;
8
+ export const Default = {};
9
+ export const State = {
10
+ render: () => {
11
+ return (_jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 16 }, children: [_jsx(ThemeSwitch, { defaultChecked: false }), _jsx(ThemeSwitch, { defaultChecked: true })] }));
12
+ },
13
+ };
@@ -0,0 +1,13 @@
1
+ import type { ChangeEvent } from "react";
2
+ export type ThemeSwitchProps = {
3
+ /** controlled */
4
+ checked?: boolean;
5
+ /** uncontrolled */
6
+ defaultChecked?: boolean;
7
+ onChange?: (e: ChangeEvent<HTMLInputElement>) => void;
8
+ onCheckedChange?: (checked: boolean) => void;
9
+ disabled?: boolean;
10
+ id?: string;
11
+ name?: string;
12
+ className?: string;
13
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ import type { IconButtonProps } from "./types";
3
+ export declare const IconButton: React.ForwardRefExoticComponent<IconButtonProps & React.RefAttributes<HTMLButtonElement>>;
@@ -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,2 @@
1
+ export * from "./IconButton";
2
+ export * from "./types";
@@ -0,0 +1,2 @@
1
+ export * from "./IconButton";
2
+ export * from "./types";
@@ -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 {};
@@ -15,8 +15,8 @@
15
15
  }
16
16
 
17
17
  .control {
18
- width: 32px;
19
- height: 32px;
18
+ width: 28px;
19
+ height: 28px;
20
20
  border-radius: 50%;
21
21
  background: var(--color-surface);
22
22
  box-shadow: var(--shadow-md-in);
@@ -1,8 +1,8 @@
1
1
  .switch {
2
2
  position: relative;
3
3
  display: inline-block;
4
- width: 72px;
5
- height: 40px;
4
+ width: 64px;
5
+ height: 36px;
6
6
  }
7
7
 
8
8
  /* input は見えなくするが状態は保持 */
@@ -27,8 +27,8 @@
27
27
  .slider::before {
28
28
  content: "";
29
29
  position: absolute;
30
- height: 24px;
31
- width: 24px;
30
+ height: 20px;
31
+ width: 20px;
32
32
  left: 8px;
33
33
  top: 8px;
34
34
  background: var(--color-on-primary);
@@ -43,7 +43,7 @@
43
43
  }
44
44
 
45
45
  .switch input:checked + .slider::before {
46
- transform: translateX(32px);
46
+ transform: translateX(28px);
47
47
  }
48
48
 
49
49
  /* ===== Focus ===== */
@@ -0,0 +1,8 @@
1
+ import React from "react";
2
+ interface IconProps {
3
+ size?: number;
4
+ color?: string;
5
+ className?: string;
6
+ }
7
+ export declare const HomeIcon: React.FC<IconProps>;
8
+ export default HomeIcon;
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lucentia-ui",
3
- "version": "0.2.7",
3
+ "version": "0.2.9",
4
4
  "description": "React UI design token and component system based on neumorphism, featuring two color themes: light and dark.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",