@pantoia/ui 0.12.1 → 0.14.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.
- package/avatar-group/index.module.css +3 -0
- package/avatar-group/index.tsx +52 -0
- package/bottom-sheet/index.tsx +15 -1
- package/combobox/index.tsx +7 -3
- package/context-menu/index.tsx +16 -4
- package/dialog/index.tsx +15 -1
- package/drawer/index.tsx +15 -1
- package/dropdown-menu/index.tsx +106 -47
- package/modal/index.tsx +7 -2
- package/package.json +1 -1
- package/popover/index.tsx +12 -4
- package/registry.json +73 -3
- package/select/index.tsx +7 -1
- package/skills/pantoia-design/SKILL.md +7 -3
- package/swatch-picker/index.module.css +8 -0
- package/swatch-picker/index.tsx +176 -0
- package/toast/index.module.css +11 -8
- package/toast/index.tsx +64 -37
- package/toggle/index.tsx +49 -11
- package/toggle-group/index.tsx +76 -0
- package/tokens.css +9 -0
- package/tooltip/index.tsx +9 -2
- package/utilities.css +1 -1
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { Radio } from '@base-ui/react/radio'
|
|
4
|
+
import { RadioGroup } from '@base-ui/react/radio-group'
|
|
5
|
+
import { Toggle as TogglePrimitive } from '@base-ui/react/toggle'
|
|
6
|
+
import { ToggleGroup as ToggleGroupPrimitive } from '@base-ui/react/toggle-group'
|
|
7
|
+
import { createContext, use, type ReactNode } from 'react'
|
|
8
|
+
|
|
9
|
+
import { toggle, type ToggleColor, type ToggleShape, type ToggleSize, type ToggleSurface } from '../toggle'
|
|
10
|
+
import { tv } from '../tv'
|
|
11
|
+
|
|
12
|
+
interface Shared {
|
|
13
|
+
size: ToggleSize
|
|
14
|
+
shape: ToggleShape
|
|
15
|
+
surface: ToggleSurface
|
|
16
|
+
multiple: boolean
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const Context = createContext<Shared>({ size: 'sm', shape: 'pill', surface: 'bare', multiple: false })
|
|
20
|
+
|
|
21
|
+
const toggleGroup = tv({ base: 'flex flex-wrap gap-2' })
|
|
22
|
+
|
|
23
|
+
interface ToggleGroupLook {
|
|
24
|
+
size?: ToggleSize
|
|
25
|
+
shape?: ToggleShape
|
|
26
|
+
surface?: ToggleSurface
|
|
27
|
+
className?: string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type ToggleGroupSingleProps = Omit<RadioGroup.Props<string | null>, 'className'> & ToggleGroupLook & {
|
|
31
|
+
multiple?: false
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type ToggleGroupMultipleProps = Omit<ToggleGroupPrimitive.Props<string>, 'className' | 'multiple'> & ToggleGroupLook & {
|
|
35
|
+
multiple: true
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type ToggleGroupProps = ToggleGroupSingleProps | ToggleGroupMultipleProps
|
|
39
|
+
|
|
40
|
+
export function ToggleGroup({ size = 'sm', shape = 'pill', surface = 'bare', className, ...rest }: ToggleGroupProps) {
|
|
41
|
+
const root = toggleGroup({ className })
|
|
42
|
+
|
|
43
|
+
if (rest.multiple) {
|
|
44
|
+
return (
|
|
45
|
+
<Context value={{ size, shape, surface, multiple: true }}>
|
|
46
|
+
<ToggleGroupPrimitive<string> {...rest} className={root} />
|
|
47
|
+
</Context>
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const { multiple: _multiple, ...single } = rest
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<Context value={{ size, shape, surface, multiple: false }}>
|
|
55
|
+
<RadioGroup<string | null> {...single} className={root} />
|
|
56
|
+
</Context>
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface ToggleGroupItemProps {
|
|
61
|
+
value: string
|
|
62
|
+
color?: ToggleColor
|
|
63
|
+
disabled?: boolean
|
|
64
|
+
'aria-label'?: string
|
|
65
|
+
className?: string
|
|
66
|
+
children?: ReactNode
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function ToggleGroupItem({ color, className, ...rest }: ToggleGroupItemProps) {
|
|
70
|
+
const { size, shape, surface, multiple } = use(Context)
|
|
71
|
+
const look = toggle({ size, shape, color, surface, className })
|
|
72
|
+
|
|
73
|
+
if (multiple) return <TogglePrimitive {...rest} className={look} />
|
|
74
|
+
|
|
75
|
+
return <Radio.Root {...rest} nativeButton render={<button type="button" />} className={look} />
|
|
76
|
+
}
|
package/tokens.css
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
--pds-bg-neutral-knob: #ffffff;
|
|
18
18
|
--pds-bg-neutral-knob-off: #ffffff;
|
|
19
19
|
--pds-bg-neutral-thumb: #ffffff;
|
|
20
|
+
--pds-bg-neutral-toast: rgba(25,31,40,0.94);
|
|
20
21
|
--pds-bg-neutral-track: var(--pds-gray-300);
|
|
21
22
|
--pds-bg-neutral-selected: rgba(2,32,71,0.05);
|
|
22
23
|
--pds-bg-neutral-selected-hover: rgba(0,27,55,0.1);
|
|
@@ -30,6 +31,7 @@
|
|
|
30
31
|
|
|
31
32
|
--pds-fg-brand-contrast: var(--pds-brand-700);
|
|
32
33
|
--pds-fg-brand-solid-contrast: #ffffff;
|
|
34
|
+
--pds-fg-neutral-toast-contrast: var(--pds-white);
|
|
33
35
|
--pds-fg-danger: var(--pds-red-500);
|
|
34
36
|
--pds-fg-danger-contrast: var(--pds-red-700);
|
|
35
37
|
--pds-fg-info: var(--pds-blue-500);
|
|
@@ -48,6 +50,7 @@
|
|
|
48
50
|
--pds-line-info: var(--pds-blue-500);
|
|
49
51
|
--pds-line-info-weak: var(--pds-blue-200);
|
|
50
52
|
--pds-line-neutral-solid: var(--pds-gray-900);
|
|
53
|
+
--pds-line-neutral-toast: transparent;
|
|
51
54
|
--pds-line-strong: var(--pds-gray-300);
|
|
52
55
|
--pds-line-success: var(--pds-green-500);
|
|
53
56
|
--pds-line-success-weak: var(--pds-green-200);
|
|
@@ -83,6 +86,7 @@
|
|
|
83
86
|
--pds-bg-neutral-knob: #2c2c35;
|
|
84
87
|
--pds-bg-neutral-knob-off: var(--pds-gray-800);
|
|
85
88
|
--pds-bg-neutral-thumb: #3c3c47;
|
|
89
|
+
--pds-bg-neutral-toast: rgba(0,0,0,0.92);
|
|
86
90
|
--pds-bg-neutral-track: var(--pds-gray-300);
|
|
87
91
|
--pds-bg-neutral-selected: rgba(217,217,255,0.11);
|
|
88
92
|
--pds-bg-neutral-selected-hover: rgba(222,222,255,0.19);
|
|
@@ -96,6 +100,7 @@
|
|
|
96
100
|
|
|
97
101
|
--pds-fg-brand-contrast: var(--pds-brand-700);
|
|
98
102
|
--pds-fg-brand-solid-contrast: #ffffff;
|
|
103
|
+
--pds-fg-neutral-toast-contrast: var(--pds-white);
|
|
99
104
|
--pds-fg-danger: var(--pds-red-500);
|
|
100
105
|
--pds-fg-danger-contrast: var(--pds-red-700);
|
|
101
106
|
--pds-fg-info: var(--pds-blue-500);
|
|
@@ -114,6 +119,7 @@
|
|
|
114
119
|
--pds-line-info: var(--pds-blue-500);
|
|
115
120
|
--pds-line-info-weak: var(--pds-blue-200);
|
|
116
121
|
--pds-line-neutral-solid: var(--pds-gray-900);
|
|
122
|
+
--pds-line-neutral-toast: rgba(255,255,255,0.1);
|
|
117
123
|
--pds-line-strong: var(--pds-gray-300);
|
|
118
124
|
--pds-line-success: var(--pds-green-500);
|
|
119
125
|
--pds-line-success-weak: var(--pds-green-200);
|
|
@@ -148,6 +154,7 @@
|
|
|
148
154
|
--color-bg-neutral-knob: var(--pds-bg-neutral-knob);
|
|
149
155
|
--color-bg-neutral-knob-off: var(--pds-bg-neutral-knob-off);
|
|
150
156
|
--color-bg-neutral-thumb: var(--pds-bg-neutral-thumb);
|
|
157
|
+
--color-bg-neutral-toast: var(--pds-bg-neutral-toast);
|
|
151
158
|
--color-bg-neutral-track: var(--pds-bg-neutral-track);
|
|
152
159
|
--color-bg-neutral-selected: var(--pds-bg-neutral-selected);
|
|
153
160
|
--color-bg-neutral-selected-hover: var(--pds-bg-neutral-selected-hover);
|
|
@@ -160,6 +167,7 @@
|
|
|
160
167
|
--color-bg-warning-weak: var(--pds-bg-warning-weak);
|
|
161
168
|
--color-fg-brand-contrast: var(--pds-fg-brand-contrast);
|
|
162
169
|
--color-fg-brand-solid-contrast: var(--pds-fg-brand-solid-contrast);
|
|
170
|
+
--color-fg-neutral-toast-contrast: var(--pds-fg-neutral-toast-contrast);
|
|
163
171
|
--color-fg-danger: var(--pds-fg-danger);
|
|
164
172
|
--color-fg-danger-contrast: var(--pds-fg-danger-contrast);
|
|
165
173
|
--color-fg-info: var(--pds-fg-info);
|
|
@@ -177,6 +185,7 @@
|
|
|
177
185
|
--color-line-info: var(--pds-line-info);
|
|
178
186
|
--color-line-info-weak: var(--pds-line-info-weak);
|
|
179
187
|
--color-line-neutral-solid: var(--pds-line-neutral-solid);
|
|
188
|
+
--color-line-neutral-toast: var(--pds-line-neutral-toast);
|
|
180
189
|
--color-line-strong: var(--pds-line-strong);
|
|
181
190
|
--color-line-success: var(--pds-line-success);
|
|
182
191
|
--color-line-success-weak: var(--pds-line-success-weak);
|
package/tooltip/index.tsx
CHANGED
|
@@ -46,7 +46,9 @@ export function TooltipTrigger(props: TooltipTriggerProps) {
|
|
|
46
46
|
return <TooltipPrimitive.Trigger delay={inProvider ? undefined : 100} {...props} aria-describedby={open ? id : undefined} />
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
type TooltipPlacement = Pick<ComponentProps<typeof TooltipPrimitive.Positioner>, 'sideOffset' | 'alignOffset' | 'collisionAvoidance'>
|
|
50
|
+
|
|
51
|
+
export type TooltipContentProps = Omit<ComponentProps<typeof TooltipPrimitive.Popup>, 'className'> & TooltipPlacement & {
|
|
50
52
|
side?: 'top' | 'right' | 'bottom' | 'left'
|
|
51
53
|
arrow?: boolean
|
|
52
54
|
className?: string
|
|
@@ -69,6 +71,9 @@ const tooltipArrow = tv({
|
|
|
69
71
|
export function TooltipContent({
|
|
70
72
|
side = 'top',
|
|
71
73
|
arrow = true,
|
|
74
|
+
sideOffset,
|
|
75
|
+
alignOffset,
|
|
76
|
+
collisionAvoidance,
|
|
72
77
|
className,
|
|
73
78
|
children,
|
|
74
79
|
...rest
|
|
@@ -79,7 +84,9 @@ export function TooltipContent({
|
|
|
79
84
|
<TooltipPrimitive.Portal>
|
|
80
85
|
<TooltipPrimitive.Positioner
|
|
81
86
|
side={side}
|
|
82
|
-
sideOffset={arrow ? 11 : 6}
|
|
87
|
+
sideOffset={sideOffset ?? (arrow ? 11 : 6)}
|
|
88
|
+
alignOffset={alignOffset}
|
|
89
|
+
collisionAvoidance={collisionAvoidance}
|
|
83
90
|
className="z-overlay min-w-max will-change-transform"
|
|
84
91
|
>
|
|
85
92
|
<TooltipPrimitive.Popup {...rest} id={id} role="tooltip" className={tooltipContent({ className })}>
|
package/utilities.css
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
@custom-variant checked (&:where([data-checked], [data-indeterminate]));
|
|
14
14
|
@custom-variant open (&[data-open]);
|
|
15
15
|
@custom-variant closed (&[data-closed]);
|
|
16
|
-
@custom-variant on (
|
|
16
|
+
@custom-variant on (&:is([aria-pressed="true"], [aria-checked="true"]));
|
|
17
17
|
@custom-variant side-top (&[data-side="top"]);
|
|
18
18
|
@custom-variant side-right (&[data-side="right"]);
|
|
19
19
|
@custom-variant side-bottom (&[data-side="bottom"]);
|