@pantoia/ui 0.10.4 → 0.11.0

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.
@@ -0,0 +1,4 @@
1
+ .seed {
2
+ background-color: oklch(var(--pds-avatar-seed-bg) var(--avatar-hue));
3
+ color: oklch(var(--pds-avatar-seed-fg) var(--avatar-hue));
4
+ }
@@ -0,0 +1,104 @@
1
+ 'use client'
2
+
3
+ import { Avatar as AvatarPrimitive } from '@base-ui/react/avatar'
4
+ import type { ComponentProps, CSSProperties } from 'react'
5
+
6
+ import { tv } from '../tv'
7
+
8
+ import s from './index.module.css'
9
+
10
+ const HANGUL = /\p{Script=Hangul}/u
11
+ const LATIN = /\p{Script=Latin}+/gu
12
+ const LETTER = /[\p{Script=Hangul}\p{Script=Latin}]/u
13
+
14
+ export function initials(name: string): string | null {
15
+ const first = LETTER.exec(name)?.[0]
16
+ if (!first) return null
17
+ if (HANGUL.test(first)) return first
18
+
19
+ const words = name.match(LATIN) ?? []
20
+ const text = words.length > 1 ? words[0]![0]! + words[1]![0]! : words[0]!.slice(0, 2)
21
+
22
+ return text.toUpperCase()
23
+ }
24
+
25
+ const FNV_OFFSET = 0x811c9dc5
26
+ const FNV_PRIME = 0x01000193
27
+
28
+ export function fnv1a(seed: string): number {
29
+ let hash = FNV_OFFSET
30
+
31
+ for (const byte of new TextEncoder().encode(seed.toLowerCase())) {
32
+ hash ^= byte
33
+ hash = Math.imul(hash, FNV_PRIME) >>> 0
34
+ }
35
+
36
+ return hash >>> 0
37
+ }
38
+
39
+ export function hueOf(seed: string): number {
40
+ const hue = fnv1a(seed) % 295
41
+ return hue >= 75 ? hue + 65 : hue
42
+ }
43
+
44
+ export const avatar = tv({
45
+ base: 'inline-flex shrink-0 select-none items-center justify-center overflow-hidden rounded-full font-medium',
46
+
47
+ variants: {
48
+ color: {
49
+ neutral: 'bg-bg-neutral-solid/10 text-fg',
50
+ brand: 'bg-bg-brand-weak text-fg-brand-contrast',
51
+ info: 'bg-bg-info-weak text-fg-info-contrast',
52
+ success: 'bg-bg-success-weak text-fg-success-contrast',
53
+ warning: 'bg-bg-warning-weak text-fg-warning-contrast',
54
+ danger: 'bg-bg-danger-weak text-fg-danger-contrast',
55
+ seed: '',
56
+ },
57
+ size: {
58
+ xs: 'size-5 text-t10',
59
+ sm: 'size-6 text-t10',
60
+ md: 'size-8 text-t13',
61
+ lg: 'size-10 text-t16',
62
+ xl: 'size-14 text-t20',
63
+ },
64
+ },
65
+
66
+ defaultVariants: { color: 'neutral', size: 'md' },
67
+ })
68
+
69
+ type AvatarTone =
70
+ | { color?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'danger', seed?: never }
71
+ | { seed: string, color?: never }
72
+
73
+ export type AvatarProps = Omit<ComponentProps<typeof AvatarPrimitive.Root>, 'className' | 'color' | 'children'> & AvatarTone & {
74
+ src?: string
75
+ name?: string
76
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'
77
+ className?: string
78
+ }
79
+
80
+ export function Avatar({ src, name, color, seed, size, className, style, ...rest }: AvatarProps) {
81
+ const text = name ? initials(name) : null
82
+ const seeded = seed !== undefined
83
+
84
+ return (
85
+ <AvatarPrimitive.Root
86
+ role={name ? 'img' : undefined}
87
+ aria-label={name}
88
+ {...rest}
89
+ style={seeded ? { ...style, '--avatar-hue': hueOf(seed) } as CSSProperties : style}
90
+ className={avatar({ color: seeded ? 'seed' : color, size, className: seeded ? [s.seed, className] : className })}
91
+ >
92
+ {src && <AvatarPrimitive.Image src={src} alt="" className="size-full object-cover" />}
93
+
94
+ <AvatarPrimitive.Fallback aria-hidden="true" className="flex size-full items-center justify-center">
95
+ {text ?? (
96
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" className="size-3/5">
97
+ <circle cx="12" cy="8" r="4" />
98
+ <path d="M4 21a8 8 0 0 1 16 0" />
99
+ </svg>
100
+ )}
101
+ </AvatarPrimitive.Fallback>
102
+ </AvatarPrimitive.Root>
103
+ )
104
+ }
package/badge/index.tsx CHANGED
@@ -8,12 +8,16 @@ export const badge = tv({
8
8
 
9
9
  variants: {
10
10
  color: {
11
- neutral: 'bg-bg-neutral-solid/10 text-fg',
12
- brand: 'bg-bg-brand-weak text-fg-brand-contrast',
13
- info: 'bg-bg-info-weak text-fg-info-contrast',
14
- success: 'bg-bg-success-weak text-fg-success-contrast',
15
- warning: 'bg-bg-warning-weak text-fg-warning-contrast',
16
- danger: 'bg-bg-danger-weak text-fg-danger-contrast',
11
+ neutral: '',
12
+ brand: '',
13
+ info: '',
14
+ success: '',
15
+ warning: '',
16
+ danger: '',
17
+ },
18
+ emphasis: {
19
+ weak: '',
20
+ solid: '',
17
21
  },
18
22
  shape: {
19
23
  square: 'rounded-r4',
@@ -21,14 +25,31 @@ export const badge = tv({
21
25
  },
22
26
  },
23
27
 
24
- defaultVariants: { color: 'neutral', shape: 'square' },
28
+ compoundVariants: [
29
+ { color: 'neutral', emphasis: 'weak', class: 'bg-bg-neutral-solid/10 text-fg' },
30
+ { color: 'brand', emphasis: 'weak', class: 'bg-bg-brand-weak text-fg-brand-contrast' },
31
+ { color: 'info', emphasis: 'weak', class: 'bg-bg-info-weak text-fg-info-contrast' },
32
+ { color: 'success', emphasis: 'weak', class: 'bg-bg-success-weak text-fg-success-contrast' },
33
+ { color: 'warning', emphasis: 'weak', class: 'bg-bg-warning-weak text-fg-warning-contrast' },
34
+ { color: 'danger', emphasis: 'weak', class: 'bg-bg-danger-weak text-fg-danger-contrast' },
35
+
36
+ { color: 'neutral', emphasis: 'solid', class: 'bg-bg-neutral-solid text-fg-neutral-solid-contrast' },
37
+ { color: 'brand', emphasis: 'solid', class: 'bg-bg-brand-solid text-fg-brand-solid-contrast' },
38
+ { color: 'info', emphasis: 'solid', class: 'bg-bg-info-solid text-fg-info-solid-contrast' },
39
+ { color: 'success', emphasis: 'solid', class: 'bg-bg-success-solid text-white' },
40
+ { color: 'warning', emphasis: 'solid', class: 'bg-bg-warning-solid text-white' },
41
+ { color: 'danger', emphasis: 'solid', class: 'bg-bg-danger-solid text-white' },
42
+ ],
43
+
44
+ defaultVariants: { color: 'neutral', emphasis: 'weak', shape: 'square' },
25
45
  })
26
46
 
27
47
  export interface BadgeProps extends Omit<HTMLAttributes<HTMLSpanElement>, 'color'> {
28
48
  color?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'danger'
49
+ emphasis?: 'weak' | 'solid'
29
50
  shape?: 'square' | 'pill'
30
51
  }
31
52
 
32
- export function Badge({ color, shape, className, ...rest }: BadgeProps) {
33
- return <span {...rest} className={badge({ color, shape, className })} />
53
+ export function Badge({ color, emphasis, shape, className, ...rest }: BadgeProps) {
54
+ return <span {...rest} className={badge({ color, emphasis, shape, className })} />
34
55
  }
@@ -0,0 +1,16 @@
1
+ @keyframes slide-in { from { translate: 0 var(--bottom-sheet-slide); } }
2
+ @keyframes slide-out { to { translate: 0 var(--bottom-sheet-slide); } }
3
+
4
+ .panel {
5
+ --bottom-sheet-slide: 100%;
6
+ transform: translateY(var(--drawer-swipe-movement-y, 0px));
7
+ transition: transform var(--dur-enter) var(--ease-enter);
8
+ }
9
+
10
+ .panel[data-open] { animation: slide-in var(--dur-enter) var(--ease-enter); }
11
+ .panel[data-closed] { animation: slide-out var(--dur-exit) var(--ease-exit); }
12
+ .panel[data-swiping] { transition-duration: 0ms; }
13
+
14
+ @media (prefers-reduced-motion: reduce) {
15
+ .panel { --bottom-sheet-slide: 0%; }
16
+ }
@@ -0,0 +1,101 @@
1
+ 'use client'
2
+
3
+ import { Drawer as DrawerPrimitive } from '@base-ui/react/drawer'
4
+ import type { ComponentProps, ReactNode } from 'react'
5
+
6
+ import { tv } from '../tv'
7
+
8
+ import s from './index.module.css'
9
+
10
+ export type BottomSheetProps = Omit<DrawerPrimitive.Root.Props, 'swipeDirection'>
11
+
12
+ export function BottomSheet(props: BottomSheetProps) {
13
+ return <DrawerPrimitive.Root {...props} swipeDirection="down" />
14
+ }
15
+
16
+ export type BottomSheetTriggerProps = ComponentProps<typeof DrawerPrimitive.Trigger>
17
+
18
+ export function BottomSheetTrigger(props: BottomSheetTriggerProps) {
19
+ return <DrawerPrimitive.Trigger {...props} />
20
+ }
21
+
22
+ export type BottomSheetCloseProps = ComponentProps<typeof DrawerPrimitive.Close>
23
+
24
+ export function BottomSheetClose(props: BottomSheetCloseProps) {
25
+ return <DrawerPrimitive.Close {...props} />
26
+ }
27
+
28
+ export const bottomSheetContent = tv({
29
+ base: 'sheet text-fg z-overlay fixed inset-x-0 bottom-0 mx-auto rounded-t-r20'
30
+ + ' flex max-h-11/12 w-full flex-col gap-stack overflow-y-auto px-4 pb-4 sm:max-w-120'
31
+ + ' focus-visible:outline-none',
32
+ })
33
+
34
+ export type BottomSheetContentProps = Omit<ComponentProps<typeof DrawerPrimitive.Popup>, 'className'> & {
35
+ className?: string
36
+ }
37
+
38
+ export function BottomSheetContent({ className, children, ...rest }: BottomSheetContentProps) {
39
+ return (
40
+ <DrawerPrimitive.Portal>
41
+ <DrawerPrimitive.Backdrop className="bg-bg-overlay z-overlay fixed inset-0 open:animate-fade-in closed:animate-fade-out" />
42
+
43
+ <DrawerPrimitive.Viewport>
44
+ <DrawerPrimitive.Popup {...rest} className={`${s.panel} ${bottomSheetContent({ className })}`}>
45
+ <div aria-hidden="true" className="bg-bg-neutral-solid/20 mx-auto mt-2 h-1 w-10 shrink-0 rounded-full" />
46
+ {children}
47
+ </DrawerPrimitive.Popup>
48
+ </DrawerPrimitive.Viewport>
49
+ </DrawerPrimitive.Portal>
50
+ )
51
+ }
52
+
53
+ export const bottomSheetHeader = tv({
54
+ slots: {
55
+ root: 'flex items-start gap-stack',
56
+ lead: 'shrink-0',
57
+ body: 'flex min-w-0 grow flex-col gap-tight',
58
+ trail: 'shrink-0',
59
+ },
60
+ })
61
+
62
+ export interface BottomSheetHeaderProps {
63
+ lead?: ReactNode
64
+ trail?: ReactNode
65
+ className?: string
66
+ children?: ReactNode
67
+ }
68
+
69
+ export function BottomSheetHeader({ lead, trail, className, children }: BottomSheetHeaderProps) {
70
+ const ui = bottomSheetHeader()
71
+
72
+ return (
73
+ <div className={ui.root({ className })}>
74
+ {lead && <div className={ui.lead()}>{lead}</div>}
75
+ <div className={ui.body()}>{children}</div>
76
+ {trail && <div className={ui.trail()}>{trail}</div>}
77
+ </div>
78
+ )
79
+ }
80
+
81
+ const bottomSheetTitle = tv({ base: 'text-section min-w-0' })
82
+
83
+ export type BottomSheetTitleProps = Omit<ComponentProps<typeof DrawerPrimitive.Title>, 'className'> & {
84
+ className?: string
85
+ }
86
+
87
+ export function BottomSheetTitle({ className, ...rest }: BottomSheetTitleProps) {
88
+ return <DrawerPrimitive.Title {...rest} className={bottomSheetTitle({ className })} />
89
+ }
90
+
91
+ const bottomSheetDescription = tv({ base: 'text-prose text-fg-muted' })
92
+
93
+ export type BottomSheetDescriptionProps = Omit<ComponentProps<typeof DrawerPrimitive.Description>, 'className'> & {
94
+ className?: string
95
+ }
96
+
97
+ export function BottomSheetDescription({ className, ...rest }: BottomSheetDescriptionProps) {
98
+ return (
99
+ <DrawerPrimitive.Description {...rest} className={bottomSheetDescription({ className })} />
100
+ )
101
+ }
@@ -0,0 +1,106 @@
1
+ 'use client'
2
+
3
+ import { ContextMenu as ContextMenuPrimitive } from '@base-ui/react/context-menu'
4
+ import type { ComponentProps } from 'react'
5
+
6
+ import {
7
+ DropdownMenuCheckboxItem,
8
+ DropdownMenuGroup,
9
+ DropdownMenuItem,
10
+ DropdownMenuRadioGroup,
11
+ DropdownMenuRadioItem,
12
+ DropdownMenuSeparator,
13
+ DropdownMenuSub,
14
+ DropdownMenuSubContent,
15
+ DropdownMenuSubTrigger,
16
+ menuPanel,
17
+ type DropdownMenuCheckboxItemProps,
18
+ type DropdownMenuGroupProps,
19
+ type DropdownMenuItemProps,
20
+ type DropdownMenuRadioGroupProps,
21
+ type DropdownMenuRadioItemProps,
22
+ type DropdownMenuSeparatorProps,
23
+ type DropdownMenuSubContentProps,
24
+ type DropdownMenuSubProps,
25
+ type DropdownMenuSubTriggerProps,
26
+ } from '../dropdown-menu'
27
+
28
+ export type ContextMenuProps = ComponentProps<typeof ContextMenuPrimitive.Root>
29
+
30
+ export function ContextMenu(props: ContextMenuProps) {
31
+ return <ContextMenuPrimitive.Root {...props} />
32
+ }
33
+
34
+ export type ContextMenuTriggerProps = ComponentProps<typeof ContextMenuPrimitive.Trigger>
35
+
36
+ export function ContextMenuTrigger(props: ContextMenuTriggerProps) {
37
+ return <ContextMenuPrimitive.Trigger {...props} />
38
+ }
39
+
40
+ export type ContextMenuContentProps = Omit<ComponentProps<typeof ContextMenuPrimitive.Popup>, 'className'> & {
41
+ className?: string
42
+ }
43
+
44
+ export function ContextMenuContent({ className, ...rest }: ContextMenuContentProps) {
45
+ return (
46
+ <ContextMenuPrimitive.Portal>
47
+ <ContextMenuPrimitive.Positioner className="z-overlay min-w-max will-change-transform">
48
+ <ContextMenuPrimitive.Popup {...rest} className={menuPanel({ className })} />
49
+ </ContextMenuPrimitive.Positioner>
50
+ </ContextMenuPrimitive.Portal>
51
+ )
52
+ }
53
+
54
+ export type ContextMenuGroupProps = DropdownMenuGroupProps
55
+
56
+ export function ContextMenuGroup(props: ContextMenuGroupProps) {
57
+ return <DropdownMenuGroup {...props} />
58
+ }
59
+
60
+ export type ContextMenuItemProps = DropdownMenuItemProps
61
+
62
+ export function ContextMenuItem(props: ContextMenuItemProps) {
63
+ return <DropdownMenuItem {...props} />
64
+ }
65
+
66
+ export type ContextMenuCheckboxItemProps = DropdownMenuCheckboxItemProps
67
+
68
+ export function ContextMenuCheckboxItem(props: ContextMenuCheckboxItemProps) {
69
+ return <DropdownMenuCheckboxItem {...props} />
70
+ }
71
+
72
+ export type ContextMenuRadioGroupProps = DropdownMenuRadioGroupProps
73
+
74
+ export function ContextMenuRadioGroup(props: ContextMenuRadioGroupProps) {
75
+ return <DropdownMenuRadioGroup {...props} />
76
+ }
77
+
78
+ export type ContextMenuRadioItemProps = DropdownMenuRadioItemProps
79
+
80
+ export function ContextMenuRadioItem(props: ContextMenuRadioItemProps) {
81
+ return <DropdownMenuRadioItem {...props} />
82
+ }
83
+
84
+ export type ContextMenuSeparatorProps = DropdownMenuSeparatorProps
85
+
86
+ export function ContextMenuSeparator(props: ContextMenuSeparatorProps) {
87
+ return <DropdownMenuSeparator {...props} />
88
+ }
89
+
90
+ export type ContextMenuSubProps = DropdownMenuSubProps
91
+
92
+ export function ContextMenuSub(props: ContextMenuSubProps) {
93
+ return <DropdownMenuSub {...props} />
94
+ }
95
+
96
+ export type ContextMenuSubTriggerProps = DropdownMenuSubTriggerProps
97
+
98
+ export function ContextMenuSubTrigger(props: ContextMenuSubTriggerProps) {
99
+ return <DropdownMenuSubTrigger {...props} />
100
+ }
101
+
102
+ export type ContextMenuSubContentProps = DropdownMenuSubContentProps
103
+
104
+ export function ContextMenuSubContent(props: ContextMenuSubContentProps) {
105
+ return <DropdownMenuSubContent {...props} />
106
+ }
@@ -39,12 +39,13 @@ export function DropdownMenuTrigger(props: DropdownMenuTriggerProps) {
39
39
  }
40
40
 
41
41
  export type DropdownMenuContentProps = Omit<ComponentProps<typeof MenuPrimitive.Popup>, 'className'> & {
42
+ side?: 'top' | 'right' | 'bottom' | 'left'
42
43
  align?: 'start' | 'center' | 'end'
43
44
  arrow?: boolean
44
45
  className?: string
45
46
  }
46
47
 
47
- const menuPanel = tv({ base: PANEL })
48
+ export const menuPanel = tv({ base: PANEL })
48
49
 
49
50
  const menuArrow = tv({
50
51
  base: 'data-uncentered:invisible'
@@ -55,6 +56,7 @@ const menuArrow = tv({
55
56
  })
56
57
 
57
58
  export function DropdownMenuContent({
59
+ side = 'bottom',
58
60
  align = 'start',
59
61
  arrow = true,
60
62
  className,
@@ -64,6 +66,7 @@ export function DropdownMenuContent({
64
66
  return (
65
67
  <MenuPrimitive.Portal>
66
68
  <MenuPrimitive.Positioner
69
+ side={side}
67
70
  align={align}
68
71
  sideOffset={arrow ? 14 : 8}
69
72
  arrowPadding={16}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pantoia/ui",
3
- "version": "0.10.4",
3
+ "version": "0.11.0",
4
4
  "description": "Pantoia Design System",
5
5
  "homepage": "https://design.pantoia.com",
6
6
  "repository": {
package/registry.json CHANGED
@@ -63,6 +63,30 @@
63
63
  "radius": "rounded-r20"
64
64
  }
65
65
  },
66
+ {
67
+ "name": "avatar",
68
+ "type": "registry:ui",
69
+ "title": "Avatar",
70
+ "files": [
71
+ {
72
+ "path": "avatar/index.tsx",
73
+ "type": "registry:ui"
74
+ },
75
+ {
76
+ "path": "avatar/index.module.css",
77
+ "type": "registry:ui"
78
+ }
79
+ ],
80
+ "dependencies": [
81
+ "@base-ui/react"
82
+ ],
83
+ "registryDependencies": [
84
+ "tv"
85
+ ],
86
+ "meta": {
87
+ "layer": "ui"
88
+ }
89
+ },
66
90
  {
67
91
  "name": "badge",
68
92
  "type": "registry:ui",
@@ -83,6 +107,30 @@
83
107
  ]
84
108
  }
85
109
  },
110
+ {
111
+ "name": "bottom-sheet",
112
+ "type": "registry:ui",
113
+ "title": "BottomSheet",
114
+ "files": [
115
+ {
116
+ "path": "bottom-sheet/index.tsx",
117
+ "type": "registry:ui"
118
+ },
119
+ {
120
+ "path": "bottom-sheet/index.module.css",
121
+ "type": "registry:ui"
122
+ }
123
+ ],
124
+ "dependencies": [
125
+ "@base-ui/react"
126
+ ],
127
+ "registryDependencies": [
128
+ "tv"
129
+ ],
130
+ "meta": {
131
+ "layer": "ui"
132
+ }
133
+ },
86
134
  {
87
135
  "name": "button",
88
136
  "type": "registry:ui",
@@ -186,6 +234,32 @@
186
234
  "layer": "derived"
187
235
  }
188
236
  },
237
+ {
238
+ "name": "context-menu",
239
+ "type": "registry:ui",
240
+ "title": "ContextMenu",
241
+ "files": [
242
+ {
243
+ "path": "context-menu/index.tsx",
244
+ "type": "registry:ui"
245
+ }
246
+ ],
247
+ "dependencies": [
248
+ "@base-ui/react"
249
+ ],
250
+ "registryDependencies": [
251
+ "dropdown-menu"
252
+ ],
253
+ "meta": {
254
+ "layer": "derived",
255
+ "sizes": [
256
+ "ContextMenuItem",
257
+ "ContextMenuCheckboxItem",
258
+ "ContextMenuRadioItem",
259
+ "ContextMenuSubTrigger"
260
+ ]
261
+ }
262
+ },
189
263
  {
190
264
  "name": "dialog",
191
265
  "type": "registry:ui",
@@ -148,12 +148,15 @@ className 그 한 곳만 바뀐다
148
148
  |---|---|---|---|
149
149
  | Accordion | accordion | Accordion, AccordionItem, AccordionTrigger, AccordionContent | - |
150
150
  | AlertDialog | alert-dialog | AlertDialog, AlertDialogTrigger, AlertDialogContent, AlertDialogTitle, AlertDialogDescription, AlertDialogHeader, AlertDialogFooter, AlertDialogAction, AlertDialogCancel | - |
151
- | Badge | badge | Badge | color, shape |
151
+ | Avatar | avatar | Avatar | color, size |
152
+ | Badge | badge | Badge | color, emphasis, shape |
153
+ | BottomSheet | bottom-sheet | BottomSheet, BottomSheetTrigger, BottomSheetClose, BottomSheetContent, BottomSheetHeader, BottomSheetTitle, BottomSheetDescription | - |
152
154
  | Button | button | Button | color, emphasis, size, shape |
153
155
  | Callout | callout | Callout | color |
154
156
  | Checkbox | checkbox | CheckboxGroup, Checkbox | color |
155
157
  | Combobox | combobox | Combobox, ComboboxAnchor, ComboboxInput, ComboboxTrigger, ComboboxCancel, ComboboxContent, ComboboxViewport, ComboboxCollection, ComboboxItem, ComboboxItemText, ComboboxItemDescription, ComboboxGroup, ComboboxEmpty, ComboboxSeparator | surface, size |
156
158
  | CommandPalette | command-palette | CommandPalette | - |
159
+ | ContextMenu | context-menu | ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuCheckboxItem, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuSub, ContextMenuSubTrigger, ContextMenuSubContent | color |
157
160
  | Dialog | dialog | Dialog, DialogTrigger, DialogClose, DialogContent, DialogTitle, DialogDescription, DialogHeader, DialogFooter | size |
158
161
  | Drawer | drawer | Drawer, DrawerTrigger, DrawerClose, DrawerContent, DrawerHeader, DrawerTitle, DrawerDescription | side |
159
162
  | DropdownMenu | dropdown-menu | DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuCheckboxItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent | color |
@@ -176,16 +179,20 @@ className 그 한 곳만 바뀐다
176
179
  컴포넌트를 고를 때 헷갈리는 짝은 이렇다.
177
180
 
178
181
  ```
179
- Dialog와 AlertDialog 내용을 보여 주면 Dialog, 되돌릴 수 없는 일을 한 번 더 물으면 AlertDialog
180
- Dialog와 Drawer 화면 가운데면 Dialog, 가장자리에서 열리면 Drawer
181
- Select와 Combobox 목록에서 고르면 Select, 입력해서 찾으면 Combobox
182
- Checkbox와 Switch 여러 개를 고르면 Checkbox, 설정을 바로 켜고 끄면 Switch
183
- Toggle과 Switch 도구 모음에서 상태를 누르면 Toggle, 설정이면 Switch
184
- Badge와 Button 누를 수 없으면 Badge, 누르면 Button
185
- Tabs와 Accordion 한 번에 하나만 보이면 Tabs, 여러 개를 펴 두면 Accordion
186
- Tooltip과 Popover 짧은 설명이면 Tooltip, 안에서 조작하면 Popover
182
+ Dialog와 AlertDialog 내용을 보여 주면 Dialog, 되돌릴 수 없는 일을 한 번 더 물으면 AlertDialog
183
+ Dialog와 Drawer 화면 가운데면 Dialog, 가장자리에서 열리면 Drawer
184
+ Drawer와 BottomSheet 왼쪽이나 오른쪽에서 열리면 Drawer, 아래에서 올라오면 BottomSheet
185
+ DropdownMenu와 ContextMenu 트리거를 누르면 DropdownMenu, 영역을 오른쪽 클릭하거나 길게 누르면 ContextMenu
186
+ Select와 Combobox 목록에서 고르면 Select, 입력해서 찾으면 Combobox
187
+ Checkbox와 Switch 여러 개를 고르면 Checkbox, 설정을 바로 켜고 끄면 Switch
188
+ Toggle과 Switch 도구 모음에서 상태를 누르면 Toggle, 설정이면 Switch
189
+ Badge와 Button 누를 수 없으면 Badge, 누르면 Button
190
+ Tabs와 Accordion 한 번에 하나만 보이면 Tabs, 여러 개를 펴 두면 Accordion
191
+ Tooltip과 Popover 짧은 설명이면 Tooltip, 안에서 조작하면 Popover
187
192
  ```
188
193
 
194
+ Avatar의 배경색은 color나 seed 중 하나로 정한다. seed에는 사용자 id처럼 바뀌지 않는 값을 넘기고, 같은 seed는 어느 앱에서나 같은 색이다.
195
+
189
196
  Field는 라벨, 도움말, 오류 메시지를 입력 컨트롤에 묶는다. Input, Textarea, NumberField, Select, Combobox와 함께 쓴다.
190
197
 
191
198
  Select는 고른 항목의 `SelectItemText`나 글자를 트리거에 보인다. `SelectItem`을 다른 컴포넌트로 감싸면 `items`로 라벨을 넘긴다.
package/tokens.css CHANGED
@@ -33,6 +33,7 @@
33
33
  --pds-fg-danger-contrast: var(--pds-red-700);
34
34
  --pds-fg-info: var(--pds-blue-500);
35
35
  --pds-fg-info-contrast: var(--pds-blue-700);
36
+ --pds-fg-info-solid-contrast: var(--pds-gray-50);
36
37
  --pds-fg-neutral-solid-contrast: var(--pds-gray-50);
37
38
  --pds-fg-success: var(--pds-green-500);
38
39
  --pds-fg-success-contrast: var(--pds-green-700);
@@ -97,6 +98,7 @@
97
98
  --pds-fg-danger-contrast: var(--pds-red-700);
98
99
  --pds-fg-info: var(--pds-blue-500);
99
100
  --pds-fg-info-contrast: var(--pds-blue-700);
101
+ --pds-fg-info-solid-contrast: var(--pds-gray-900);
100
102
  --pds-fg-neutral-solid-contrast: var(--pds-gray-50);
101
103
  --pds-fg-success: var(--pds-green-500);
102
104
  --pds-fg-success-contrast: var(--pds-green-700);
@@ -159,6 +161,7 @@
159
161
  --color-fg-danger-contrast: var(--pds-fg-danger-contrast);
160
162
  --color-fg-info: var(--pds-fg-info);
161
163
  --color-fg-info-contrast: var(--pds-fg-info-contrast);
164
+ --color-fg-info-solid-contrast: var(--pds-fg-info-solid-contrast);
162
165
  --color-fg-neutral-solid-contrast: var(--pds-fg-neutral-solid-contrast);
163
166
  --color-fg-success: var(--pds-fg-success);
164
167
  --color-fg-success-contrast: var(--pds-fg-success-contrast);
@@ -276,3 +279,6 @@
276
279
 
277
280
  :root, .light { --pds-pressed-dim: rgba(0,23,51,0.12); }
278
281
  .dark { --pds-pressed-dim: rgba(209,209,253,0.14); }
282
+
283
+ :root, .light { --pds-avatar-seed-bg: 0.92 0.06; --pds-avatar-seed-fg: 0.42 0.13; }
284
+ .dark { --pds-avatar-seed-bg: 0.38 0.08; --pds-avatar-seed-fg: 0.9 0.07; }