@xonic0506/sonic-ui 0.4.1 → 0.4.3
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/DESIGN.md +4 -2
- package/dist/components/button-variants.d.ts +5 -0
- package/dist/components/button-variants.js +26 -0
- package/dist/components/button.d.ts +1 -1
- package/dist/components/button.js +10 -31
- package/dist/components/illustration.js +0 -1
- package/dist/components/popup-styles.js +0 -1
- package/dist/illustrations/error-403.webp +0 -0
- package/dist/illustrations/error-404.webp +0 -0
- package/dist/illustrations/error-500.webp +0 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +32 -32
- package/dist/lib/cn.js +0 -1
- package/package.json +1 -1
package/DESIGN.md
CHANGED
|
@@ -320,6 +320,8 @@ Figma Core 페이지의 컴포넌트 속성 이름 = React props 이름이에요
|
|
|
320
320
|
| ghost | 없음 | `text/default` | 없음 | `bg/subtle` |
|
|
321
321
|
| danger | `bg/danger` | `text/on-danger` | 없음 | 없음 (v0.1에는 danger hover 토큰이 없음) |
|
|
322
322
|
|
|
323
|
+
**페이지 이동은 버튼 모양이어도 링크예요.** `<Button render={<a />}>`는 `<a>`에 `role="button"`이 붙어 화면 낭독기가 버튼으로 읽어요. 링크 요소에 `buttonVariants({ variant, size })` 클래스만 입혀요: `<NextLink href="/" className={buttonVariants({ variant: 'secondary' })}>홈으로 가기</NextLink>`.
|
|
324
|
+
|
|
323
325
|
공통: radius `radius/md`, 아이콘과 글자 사이 `space/2`, disabled는 `opacity/disabled`(45%), focus는 2px `border/focus` + offset 2px, 색 전환은 `duration/fast`.
|
|
324
326
|
|
|
325
327
|
### Input
|
|
@@ -481,7 +483,7 @@ const retryRef = useRef<HTMLButtonElement>(null);
|
|
|
481
483
|
```tsx
|
|
482
484
|
// Next.js app/not-found.tsx
|
|
483
485
|
export default function NotFound() {
|
|
484
|
-
return <ErrorPage status={404} action={<
|
|
486
|
+
return <ErrorPage status={404} action={<NextLink href="/" className={buttonVariants()}>홈으로 가기</NextLink>} />;
|
|
485
487
|
}
|
|
486
488
|
```
|
|
487
489
|
|
|
@@ -829,7 +831,7 @@ Sonic 팀은 Figma Pro 요금제라 Code Connect(Organization 이상)를 쓸 수
|
|
|
829
831
|
|
|
830
832
|
| Figma 컴포넌트 (Core 페이지) | node id | 코드 | 파일 |
|
|
831
833
|
|---|---|---|---|
|
|
832
|
-
| Button | `5:52` | `<Button variant size disabled>` | `src/components/button.tsx` |
|
|
834
|
+
| Button | `5:52` | `<Button variant size disabled>` (페이지 이동은 링크에 `buttonVariants({ variant, size })`) | `src/components/button.tsx` |
|
|
833
835
|
| Button Icon | `23:2294` | `<Button size="icon-*" variant disabled aria-label>` + 아이콘 자식 | `src/components/button.tsx` |
|
|
834
836
|
| Input | `5:61` | `<Input invalid disabled placeholder>` | `src/components/input.tsx` |
|
|
835
837
|
| Text | `5:110` | `<Text variant tone as>` | `src/components/text.tsx` |
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** 링크를 버튼 모양으로 그릴 때: <NextLink className={buttonVariants({ variant: 'secondary' })} /> */
|
|
2
|
+
export declare const buttonVariants: (props?: ({
|
|
3
|
+
variant?: "danger" | "ghost" | "primary" | "secondary" | null | undefined;
|
|
4
|
+
size?: "icon-lg" | "icon-md" | "icon-sm" | "lg" | "md" | "sm" | null | undefined;
|
|
5
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { cva as e } from "class-variance-authority";
|
|
2
|
+
//#region src/components/button-variants.ts
|
|
3
|
+
var t = e("sn:box-border sn:inline-flex sn:items-center sn:justify-center sn:gap-2 sn:whitespace-nowrap sn:rounded-md sn:border sn:border-transparent sn:font-sans sn:cursor-pointer sn:select-none sn:transition-colors sn:duration-(--sn-duration-fast) sn:ease-standard sn:focus-visible:outline-2 sn:focus-visible:outline-offset-2 sn:focus-visible:outline-focus sn:data-disabled:not-data-loading:cursor-not-allowed sn:data-disabled:not-data-loading:opacity-(--sn-opacity-disabled) sn:data-loading:cursor-progress sn:[&_svg]:pointer-events-none sn:[&_svg]:shrink-0", {
|
|
4
|
+
variants: {
|
|
5
|
+
variant: {
|
|
6
|
+
primary: "sn:bg-primary sn:text-on-primary sn:hover:not-data-disabled:bg-primary-hover",
|
|
7
|
+
secondary: "sn:border-default sn:bg-surface sn:text-default sn:hover:not-data-disabled:bg-subtle",
|
|
8
|
+
ghost: "sn:bg-transparent sn:text-default sn:hover:not-data-disabled:bg-subtle",
|
|
9
|
+
danger: "sn:bg-danger sn:text-on-danger"
|
|
10
|
+
},
|
|
11
|
+
size: {
|
|
12
|
+
sm: "sn:h-7 sn:px-2 sn:text-label sn:[&_svg]:size-4",
|
|
13
|
+
md: "sn:h-8 sn:px-3 sn:text-body-strong sn:[&_svg]:size-4",
|
|
14
|
+
lg: "sn:h-10 sn:px-4 sn:text-body-strong sn:[&_svg]:size-5",
|
|
15
|
+
"icon-sm": "sn:size-7 sn:p-0 sn:[&_svg]:size-4",
|
|
16
|
+
"icon-md": "sn:size-8 sn:p-0 sn:[&_svg]:size-4",
|
|
17
|
+
"icon-lg": "sn:size-10 sn:p-0 sn:[&_svg]:size-5"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
defaultVariants: {
|
|
21
|
+
variant: "primary",
|
|
22
|
+
size: "md"
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
//#endregion
|
|
26
|
+
export { t as buttonVariants };
|
|
@@ -2,7 +2,7 @@ import * as React from 'react';
|
|
|
2
2
|
interface ButtonBaseProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'className'> {
|
|
3
3
|
variant?: 'primary' | 'secondary' | 'ghost' | 'danger';
|
|
4
4
|
className?: string;
|
|
5
|
-
/** 다른 요소로 렌더링할
|
|
5
|
+
/** 다른 요소로 렌더링할 때. 링크는 role="button"이 붙으니 buttonVariants를 쓰세요 */
|
|
6
6
|
render?: React.ReactElement;
|
|
7
7
|
/** 진행 중: 스피너 표시, 클릭 막기, 포커스 유지, aria-busy */
|
|
8
8
|
loading?: boolean;
|
|
@@ -1,35 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn as e } from "../lib/cn.js";
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
3
|
+
import { buttonVariants as t } from "./button-variants.js";
|
|
4
|
+
import * as n from "react";
|
|
5
|
+
import { Button as r } from "@base-ui/react/button";
|
|
6
6
|
import { LoaderCircle as i } from "lucide-react";
|
|
7
7
|
import { Fragment as a, jsx as o, jsxs as s } from "react/jsx-runtime";
|
|
8
8
|
//#region src/components/button.tsx
|
|
9
|
-
var c =
|
|
10
|
-
variants: {
|
|
11
|
-
variant: {
|
|
12
|
-
primary: "sn:bg-primary sn:text-on-primary sn:hover:not-data-disabled:bg-primary-hover",
|
|
13
|
-
secondary: "sn:border-default sn:bg-surface sn:text-default sn:hover:not-data-disabled:bg-subtle",
|
|
14
|
-
ghost: "sn:bg-transparent sn:text-default sn:hover:not-data-disabled:bg-subtle",
|
|
15
|
-
danger: "sn:bg-danger sn:text-on-danger"
|
|
16
|
-
},
|
|
17
|
-
size: {
|
|
18
|
-
sm: "sn:h-7 sn:px-2 sn:text-label sn:[&_svg]:size-4",
|
|
19
|
-
md: "sn:h-8 sn:px-3 sn:text-body-strong sn:[&_svg]:size-4",
|
|
20
|
-
lg: "sn:h-10 sn:px-4 sn:text-body-strong sn:[&_svg]:size-5",
|
|
21
|
-
"icon-sm": "sn:size-7 sn:p-0 sn:[&_svg]:size-4",
|
|
22
|
-
"icon-md": "sn:size-8 sn:p-0 sn:[&_svg]:size-4",
|
|
23
|
-
"icon-lg": "sn:size-10 sn:p-0 sn:[&_svg]:size-5"
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
defaultVariants: {
|
|
27
|
-
variant: "primary",
|
|
28
|
-
size: "md"
|
|
29
|
-
}
|
|
30
|
-
}), l = t.forwardRef(function({ variant: t, size: r, className: l, render: u, loading: d, disabled: f, children: p, ...m }, h) {
|
|
9
|
+
var c = n.forwardRef(function({ variant: n, size: c, className: l, render: u, loading: d, disabled: f, children: p, ...m }, h) {
|
|
31
10
|
let g = /* @__PURE__ */ o(i, { className: "sn:animate-[sn-spin_var(--sn-duration-loop)_linear_infinite] sn:motion-reduce:animate-none" });
|
|
32
|
-
return /* @__PURE__ */ o(
|
|
11
|
+
return /* @__PURE__ */ o(r, {
|
|
33
12
|
ref: h,
|
|
34
13
|
render: u,
|
|
35
14
|
nativeButton: !u || u.type === "button",
|
|
@@ -37,13 +16,13 @@ var c = r("sn:box-border sn:inline-flex sn:items-center sn:justify-center sn:gap
|
|
|
37
16
|
focusableWhenDisabled: d,
|
|
38
17
|
"aria-busy": d || void 0,
|
|
39
18
|
"data-loading": d ? "" : void 0,
|
|
40
|
-
className: e(
|
|
41
|
-
variant:
|
|
42
|
-
size:
|
|
19
|
+
className: e(t({
|
|
20
|
+
variant: n,
|
|
21
|
+
size: c
|
|
43
22
|
}), l),
|
|
44
23
|
...m,
|
|
45
|
-
children: d &&
|
|
24
|
+
children: d && c?.startsWith("icon-") ? g : d ? /* @__PURE__ */ s(a, { children: [g, p] }) : p
|
|
46
25
|
});
|
|
47
26
|
});
|
|
48
27
|
//#endregion
|
|
49
|
-
export {
|
|
28
|
+
export { c as Button };
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use client";
|
|
2
1
|
//#region src/components/popup-styles.ts
|
|
3
2
|
var e = "sn:box-border sn:min-w-(--anchor-width) sn:max-h-(--available-height) sn:overflow-y-auto sn:origin-(--transform-origin) sn:rounded-lg sn:border sn:border-default sn:bg-surface sn:p-1 sn:font-sans sn:text-body sn:text-default sn:outline-none sn:transition-[opacity,scale] sn:duration-(--sn-duration-normal) sn:ease-standard sn:data-starting-style:scale-98 sn:data-starting-style:opacity-0 sn:data-ending-style:scale-98 sn:data-ending-style:opacity-0 sn:motion-reduce:transition-none", t = "sn:group sn:flex sn:h-8 sn:cursor-default sn:items-center sn:gap-2 sn:rounded-md sn:px-2 sn:outline-none sn:select-none sn:data-highlighted:bg-subtle sn:data-disabled:opacity-(--sn-opacity-disabled) sn:[&_svg]:size-4 sn:[&_svg]:shrink-0", n = "sn:box-border sn:inline-flex sn:size-4 sn:shrink-0 sn:items-center sn:justify-center sn:rounded-sm sn:border sn:border-strong sn:bg-surface sn:text-on-primary sn:[&_svg]:size-3";
|
|
4
3
|
//#endregion
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { Button, type ButtonProps } from './components/button';
|
|
2
|
+
export { buttonVariants } from './components/button-variants';
|
|
2
3
|
export { Input, type InputProps } from './components/input';
|
|
3
4
|
export { Textarea, type TextareaProps } from './components/textarea';
|
|
4
5
|
export { Checkbox, CheckboxGroup, type CheckboxProps, type CheckboxGroupProps } from './components/checkbox';
|
package/dist/index.js
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
import { Button as
|
|
3
|
-
import { Input as
|
|
4
|
-
import { Textarea as
|
|
5
|
-
import { Checkbox as
|
|
6
|
-
import { Radio as
|
|
7
|
-
import { Switch as
|
|
8
|
-
import { Select as
|
|
9
|
-
import { Text as
|
|
10
|
-
import { Card as
|
|
11
|
-
import { Avatar as
|
|
12
|
-
import { Field as
|
|
13
|
-
import { Skeleton as
|
|
14
|
-
import { EmptyState as
|
|
15
|
-
import { ErrorState as
|
|
16
|
-
import { ErrorPage as
|
|
17
|
-
import { Dialog as
|
|
18
|
-
import { AlertDialog as
|
|
19
|
-
import { Menu as
|
|
20
|
-
import { Popover as
|
|
21
|
-
import { Tooltip as
|
|
22
|
-
import { Tab as
|
|
23
|
-
import { Separator as
|
|
24
|
-
import { ToastProvider as
|
|
25
|
-
import { Badge as
|
|
26
|
-
import { Progress as
|
|
27
|
-
import { Link as
|
|
28
|
-
import { Table as
|
|
29
|
-
import { ToggleGroup as
|
|
30
|
-
import { Accordion as
|
|
31
|
-
import { FileDropzone as
|
|
32
|
-
export {
|
|
1
|
+
import { buttonVariants as e } from "./components/button-variants.js";
|
|
2
|
+
import { Button as t } from "./components/button.js";
|
|
3
|
+
import { Input as n } from "./components/input.js";
|
|
4
|
+
import { Textarea as r } from "./components/textarea.js";
|
|
5
|
+
import { Checkbox as i, CheckboxGroup as a } from "./components/checkbox.js";
|
|
6
|
+
import { Radio as o, RadioGroup as s } from "./components/radio-group.js";
|
|
7
|
+
import { Switch as c } from "./components/switch.js";
|
|
8
|
+
import { Select as l } from "./components/select.js";
|
|
9
|
+
import { Text as u } from "./components/text.js";
|
|
10
|
+
import { Card as d, CardBody as f, CardDescription as p, CardFooter as m, CardHeader as h, CardTitle as g } from "./components/card.js";
|
|
11
|
+
import { Avatar as _ } from "./components/avatar.js";
|
|
12
|
+
import { Field as v } from "./components/field.js";
|
|
13
|
+
import { Skeleton as y } from "./components/skeleton.js";
|
|
14
|
+
import { EmptyState as b } from "./components/empty-state.js";
|
|
15
|
+
import { ErrorState as x } from "./components/error-state.js";
|
|
16
|
+
import { ErrorPage as S } from "./components/error-page.js";
|
|
17
|
+
import { Dialog as C, DialogClose as w, DialogDescription as T, DialogFooter as E, DialogPopup as D, DialogTitle as O, DialogTrigger as k } from "./components/dialog.js";
|
|
18
|
+
import { AlertDialog as A, AlertDialogClose as j, AlertDialogDescription as M, AlertDialogFooter as N, AlertDialogPopup as P, AlertDialogTitle as F, AlertDialogTrigger as I } from "./components/alert-dialog.js";
|
|
19
|
+
import { Menu as L, MenuItem as R, MenuPopup as z, MenuSeparator as B, MenuTrigger as V } from "./components/menu.js";
|
|
20
|
+
import { Popover as H, PopoverClose as U, PopoverDescription as W, PopoverPopup as G, PopoverTitle as K, PopoverTrigger as q } from "./components/popover.js";
|
|
21
|
+
import { Tooltip as J } from "./components/tooltip.js";
|
|
22
|
+
import { Tab as Y, Tabs as X, TabsList as Z, TabsPanel as Q } from "./components/tabs.js";
|
|
23
|
+
import { Separator as $ } from "./components/separator.js";
|
|
24
|
+
import { ToastProvider as ee, useToast as te } from "./components/toast.js";
|
|
25
|
+
import { Badge as ne } from "./components/badge.js";
|
|
26
|
+
import { Progress as re } from "./components/progress.js";
|
|
27
|
+
import { Link as ie } from "./components/link.js";
|
|
28
|
+
import { Table as ae, TableBody as oe, TableCell as se, TableHead as ce, TableHeader as le, TableRow as ue } from "./components/table.js";
|
|
29
|
+
import { ToggleGroup as de, ToggleGroupItem as fe } from "./components/toggle-group.js";
|
|
30
|
+
import { Accordion as pe, AccordionItem as me, AccordionPanel as he, AccordionTrigger as ge } from "./components/accordion.js";
|
|
31
|
+
import { FileDropzone as _e, FileList as ve, formatBytes as ye } from "./components/file-upload.js";
|
|
32
|
+
export { pe as Accordion, me as AccordionItem, he as AccordionPanel, ge as AccordionTrigger, A as AlertDialog, j as AlertDialogClose, M as AlertDialogDescription, N as AlertDialogFooter, P as AlertDialogPopup, F as AlertDialogTitle, I as AlertDialogTrigger, _ as Avatar, ne as Badge, t as Button, d as Card, f as CardBody, p as CardDescription, m as CardFooter, h as CardHeader, g as CardTitle, i as Checkbox, a as CheckboxGroup, C as Dialog, w as DialogClose, T as DialogDescription, E as DialogFooter, D as DialogPopup, O as DialogTitle, k as DialogTrigger, b as EmptyState, S as ErrorPage, x as ErrorState, v as Field, _e as FileDropzone, ve as FileList, n as Input, ie as Link, L as Menu, R as MenuItem, z as MenuPopup, B as MenuSeparator, V as MenuTrigger, H as Popover, U as PopoverClose, W as PopoverDescription, G as PopoverPopup, K as PopoverTitle, q as PopoverTrigger, re as Progress, o as Radio, s as RadioGroup, l as Select, $ as Separator, y as Skeleton, c as Switch, Y as Tab, ae as Table, oe as TableBody, se as TableCell, ce as TableHead, le as TableHeader, ue as TableRow, X as Tabs, Z as TabsList, Q as TabsPanel, u as Text, r as Textarea, ee as ToastProvider, de as ToggleGroup, fe as ToggleGroupItem, J as Tooltip, e as buttonVariants, ye as formatBytes, te as useToast };
|
package/dist/lib/cn.js
CHANGED