Skip to content

Commit fa64bf5

Browse files
committed
Improvement
1 parent 80e1fb1 commit fa64bf5

11 files changed

Lines changed: 558 additions & 256 deletions

src/callout.tsx

Lines changed: 29 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -19,74 +19,10 @@ const CalloutContext = React.createContext<{
1919
});
2020

2121
const colors = {
22-
zinc: [
23-
'[--callout:var(--color-zinc-500)]',
24-
'[--callout-border:color-mix(in_oklab,_var(--callout)_20%,_white)]',
25-
'dark:[--callout-border:color-mix(in_oklab,_var(--callout)_50%,_black)]',
26-
'[--callout-bg:color-mix(in_oklab,_var(--callout)_5%,_white)]',
27-
'dark:[--callout-bg:color-mix(in_oklab,_var(--callout)_40%,_black)]',
28-
'[--callout-heading:color-mix(in_oklab,_var(--callout)_30%,_black)]',
29-
'dark:[--callout-heading:color-mix(in_oklab,_var(--callout)_50%,_white)]',
30-
'[--callout-description:color-mix(in_oklab,_var(--callout)_95%,_black)]',
31-
'[--callout-icon:color-mix(in_oklab,_var(--callout)_90%,_black)]',
32-
'[--link:color-mix(in_oklab,_var(--callout)_50%,_black)]',
33-
'dark:[--link:color-mix(in_oklab,_var(--callout)_80%,_black)]',
34-
],
35-
red: [
36-
'[--callout:var(--color-red-500)]',
37-
'[--callout-border:color-mix(in_oklab,_var(--callout)_30%,_white)]',
38-
'dark:[--callout-border:color-mix(in_oklab,_var(--callout)_40%,_black)]',
39-
'[--callout-bg:color-mix(in_oklab,_var(--callout)_10%,_white)]',
40-
'dark:[--callout-bg:color-mix(in_oklab,_var(--callout)_25%,_black)]',
41-
'[--callout-heading:color-mix(in_oklab,_var(--callout)_70%,_black)]',
42-
'dark:[--callout-heading:color-mix(in_oklab,_var(--callout)_85%,_black)]',
43-
'[--callout-description:color-mix(in_oklab,_var(--callout)_75%,_black)]',
44-
'dark:[--callout-description:color-mix(in_oklab,_var(--callout)_80%,_black)]',
45-
'[--callout-icon:color-mix(in_oklab,_var(--callout)_90%,_black)]',
46-
'[--link:color-mix(in_oklab,_var(--callout)_50%,_black)]',
47-
'dark:[--link:color-mix(in_oklab,_var(--callout)_80%,_black)]',
48-
],
49-
blue: [
50-
'[--callout:var(--color-blue-500)]',
51-
'[--callout-border:color-mix(in_oklab,_var(--callout)_35%,_white)]',
52-
'dark:[--callout-border:color-mix(in_oklab,_var(--callout)_50%,_black)]',
53-
'[--callout-bg:color-mix(in_oklab,_var(--callout)_10%,_white)]',
54-
'dark:[--callout-bg:color-mix(in_oklab,_var(--callout)_25%,_black)]',
55-
'[--callout-heading:color-mix(in_oklab,_var(--callout)_70%,_black)]',
56-
'dark:[--callout-heading:color-mix(in_oklab,_var(--callout)_80%,_black)]',
57-
'[--callout-description:color-mix(in_oklab,_var(--callout)_80%,_black)]',
58-
'dark:[--callout-description:color-mix(in_oklab,_var(--callout)_75%,_black)]',
59-
'[--callout-icon:color-mix(in_oklab,_var(--callout)_90%,_black)]',
60-
'[--link:color-mix(in_oklab,_var(--callout)_50%,_black)]',
61-
'dark:[--link:color-mix(in_oklab,_var(--callout)_80%,_black)]',
62-
],
63-
yellow: [
64-
'[--callout:var(--color-yellow-500)]',
65-
'[--callout-border:color-mix(in_oklab,_var(--callout)_35%,_white)]',
66-
'dark:[--callout-border:color-mix(in_oklab,_var(--callout)_35%,_black)]',
67-
'[--callout-bg:color-mix(in_oklab,_var(--callout)_10%,_white)]',
68-
'dark:[--callout-bg:color-mix(in_oklab,_var(--callout)_25%,_black)]',
69-
'[--callout-heading:color-mix(in_oklab,_var(--callout)_55%,_black)]',
70-
'dark:[--callout-heading:color-mix(in_oklab,_var(--callout)_85%,_black)]',
71-
'[--callout-description:color-mix(in_oklab,_var(--callout)_60%,_black)]',
72-
'dark:[--callout-description:color-mix(in_oklab,_var(--callout)_75%,_black)]',
73-
'[--callout-icon:color-mix(in_oklab,_var(--callout)_90%,_black)]',
74-
'[--link:color-mix(in_oklab,_var(--callout)_50%,_black)]',
75-
'dark:[--link:color-mix(in_oklab,_var(--callout)_80%,_black)]',
76-
],
77-
green: [
78-
'[--callout:var(--color-green-500)]',
79-
'[--callout-border:color-mix(in_oklab,_var(--callout)_40%,_white)]',
80-
'dark:[--callout-border:color-mix(in_oklab,_var(--callout)_35%,_black)]',
81-
'[--callout-bg:color-mix(in_oklab,_var(--callout)_10%,_white)]',
82-
'dark:[--callout-bg:color-mix(in_oklab,_var(--callout)_25%,_black)]',
83-
'[--callout-heading:color-mix(in_oklab,_var(--callout)_70%,_black)]',
84-
'dark:[--callout-heading:color-mix(in_oklab,_var(--callout)_90%,_black)]',
85-
'[--callout-description:color-mix(in_oklab,_var(--callout)_65%,_black)]',
86-
'[--callout-icon:color-mix(in_oklab,_var(--callout)_90%,_black)]',
87-
'[--link:color-mix(in_oklab,_var(--callout)_50%,_black)]',
88-
'dark:[--link:color-mix(in_oklab,_var(--callout)_80%,_black)]',
89-
],
22+
red: ['[--callout:var(--color-red-500)]'],
23+
blue: ['[--callout:var(--color-blue-500)]'],
24+
yellow: ['[--callout:var(--color-yellow-500)]'],
25+
green: ['[--callout:var(--color-green-500)]'],
9026
};
9127

9228
export type CalloutColor = keyof typeof colors;
@@ -128,21 +64,9 @@ export default function Callout({
12864
'aria-describedby': `des_${labelId}`,
12965
})}
13066
className={twMerge(
131-
'[--callout-icon:var(--muted)]',
132-
'[--callout-border:var(--border)]',
133-
134-
color
135-
? [
136-
colors[color],
137-
'dark:selection:bg-(--callout) dark:selection:text-white',
138-
]
139-
: [
140-
'[&:has(>[data-ui=callout-heading])]:[--callout-description:var(--muted)]',
141-
],
142-
143-
'group w-full border-(--callout-border) bg-(--callout-bg)',
67+
color ? colors[color] : [],
68+
'group w-full',
14469
'grid grid-cols-[auto_1fr_auto_auto] px-4 py-2',
145-
14670
center
14771
? [
14872
'grid-cols-[auto_auto_auto_auto]',
@@ -152,6 +76,23 @@ export default function Callout({
15276
]
15377
: 'rounded-lg border',
15478
'[&:has([data-ui=callout-heading]+[data-ui=callout-description])]:[--callout-content-row-end:3]',
79+
[
80+
'border-(--callout-border,var(--border)) bg-(--callout-bg)',
81+
'[--callout-border:color-mix(in_oklab,_var(--callout)_30%,_white)]',
82+
'dark:[--callout-border:color-mix(in_oklab,_var(--callout)_40%,_black)]',
83+
'[--callout-bg:color-mix(in_oklab,_var(--callout)_5%,_white)]',
84+
'dark:[--callout-bg:color-mix(in_oklab,_var(--callout)_25%,_black)]',
85+
'[--callout-heading:color-mix(in_oklab,_var(--callout)_65%,_black)]',
86+
'dark:[--callout-heading:color-mix(in_oklab,_var(--callout)_80%,_black)]',
87+
'[--callout-description:color-mix(in_oklab,_var(--callout)_75%,_black)]',
88+
'dark:[--callout-description:color-mix(in_oklab,_var(--callout)_80%,_black)]',
89+
'[--callout-icon:color-mix(in_oklab,_var(--callout)_90%,_black)]',
90+
'[--link:color-mix(in_oklab,_var(--callout)_50%,_black)]',
91+
'dark:[--link:color-mix(in_oklab,_var(--callout)_80%,_black)]',
92+
93+
'dark:selection:bg-(--callout,color-mix(in_oklab,_var(--background)_75%,_white)) dark:selection:text-white',
94+
],
95+
15596
className,
15697
)}
15798
/>
@@ -174,7 +115,7 @@ export function CalloutIcon({
174115
'flex',
175116
'py-2',
176117
'me-3',
177-
'[&_[data-ui=icon]:not([class*=text-])]:text-(--callout-icon)',
118+
'[&_[data-ui=icon]:not([class*=text-])]:text-(--callout-icon,var(--muted))',
178119
'[&_[data-ui=icon]:not([class*=size-])]:w-5',
179120
'[&_[data-ui=icon]:not([class*=size-])]:h-lh',
180121
className,
@@ -200,6 +141,7 @@ export function CalloutTitle({
200141
displayLevel={displayLevel}
201142
data-ui="callout-heading"
202143
className={twMerge(
144+
'peer',
203145
'col-start-2',
204146
'-col-end-2',
205147
inline && ['sm:-col-end-3'],
@@ -228,7 +170,8 @@ export function CalloutDescription({
228170
id={id ?? ariaDescribedBy}
229171
data-ui="callout-description"
230172
className={twMerge(
231-
'text-(--callout-description)',
173+
'text-(--callout-description,var(--foreground))',
174+
'peer-[*]:text-(--callout-description,var(--muted))',
232175
'col-start-2',
233176
'-col-end-2 py-2',
234177
inline && ['sm:-col-end-3'],
@@ -249,7 +192,7 @@ export function CalloutActions({
249192
{...props}
250193
data-ui="callout-actions"
251194
className={twMerge(
252-
'flex flex-wrap gap-2 ps-(--callout-indent)',
195+
'flex flex-wrap gap-3 ps-(--callout-indent)',
253196
'col-start-2',
254197
'-col-end-2',
255198
'py-2',
@@ -289,7 +232,7 @@ export function CalloutControl({
289232
variant={variant}
290233
className={composeRenderProps(props.className, (className) =>
291234
twMerge(
292-
'text-(--callout-icon)',
235+
'text-(--callout-icon,var(--muted))',
293236
'hover:bg-transparent',
294237
'hover:text-(--callout-heading)',
295238
'px-2 py-1.5 dark:hover:bg-transparent',

src/checkbox.tsx

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ export function Checkbox(props: CheckboxProps) {
263263
renderProps.isDisabled && 'opacity-50',
264264
noCheckToggle && [
265265
renderProps.isFocusVisible &&
266-
'outline-ring outline-2 outline-offset-2',
266+
'outline-(var(--checkbox,--ring)) outline-2 outline-offset-2',
267267
],
268268
getCheckboxStyle({
269269
variant,
@@ -283,10 +283,7 @@ export function Checkbox(props: CheckboxProps) {
283283
<CheckToggle
284284
check={check}
285285
renderProps={renderProps}
286-
className={twMerge(
287-
placement === 'end' ? 'me-3' : 'ms-3',
288-
!check && 'size-4.5 sm:size-4',
289-
)}
286+
className={twMerge(placement === 'end' ? 'me-3' : 'ms-3')}
290287
/>
291288
)}
292289

@@ -316,27 +313,42 @@ export function CheckToggle({
316313
{...props}
317314
data-check-indicator
318315
className={twMerge([
319-
'size-4',
320-
'flex shrink-0 items-center justify-center rounded-sm shadow ring ring-zinc-950/15 dark:ring-white/20',
321-
renderProps?.isReadOnly
322-
? 'opacity-50'
323-
: renderProps?.isHovered && 'ring-zinc-950/25 dark:ring-white/25',
324-
renderProps?.isSelected || renderProps?.isIndeterminate
325-
? 'ring-accent bg-accent shadow-[inset_0_1px_0_0_rgba(255,255,255,0.1)] dark:ring-0'
326-
: 'dark:bg-white/5 dark:[--contract:1.05]',
316+
'[--__checkbox:var(--checkbox,var(--accent))]',
317+
'[--__checkbox-size:var(--checkbox-size,max(--spacing(4),--spacing(4.5)))]',
318+
'sm:[--__checkbox-size:var(--checkbox-size,--spacing(4))]',
319+
320+
'size-(--__checkbox-size)',
321+
322+
'flex shrink-0 items-center justify-center rounded-sm shadow',
323+
324+
'[----check:lch(from_var(--__checkbox)_calc((64.28_-_l)_*_infinity)_0_0)]',
325+
'[--checkbox-focus-ring:color-mix(in_oklab,_var(--__checkbox)_65%,_var(----check))]',
326+
327+
// Readonly
328+
'in-[&:is([data-ui=content],label)[data-readonly=true]]:opacity-50',
329+
330+
// Focus visible
331+
'in-[&:is([data-ui=content],label)[data-focus-visible=true]]:outline-(--checkbox-focus-ring)',
332+
'in-[&:is([data-ui=content],label)[data-focus-visible=true]]:outline-2',
333+
'in-[&:is([data-ui=content],label)[data-focus-visible=true]]:outline-offset-3',
327334

328335
renderProps?.isInvalid && 'ring-red-600 dark:ring-red-600',
329-
renderProps?.isFocusVisible &&
330-
'outline-ring outline-2 outline-offset-3',
331-
332-
// when used in menu item as the selected indicator
333-
'in-[&[data-ui=content][data-hovered=true]]:ring-zinc-950/25',
334-
'in-[&[data-ui=content][data-hovered=true]]:dark:ring-white/25',
335-
'in-[&[data-ui=content][data-selected=true]]:ring-accent',
336-
'in-[&[data-ui=content][data-selected=true]]:dark:ring-0',
337-
'in-[&[data-ui=content][data-selected=true]]:bg-accent',
338-
'in-[&[data-ui=content][data-selected=true]]:dark:bg-accent',
339-
'in-[&[data-ui=content][data-selected=true]]:shadow-[inset_0_1px_0_0_rgba(255,255,255,0.1)]',
336+
337+
'ring-1',
338+
'ring-(--checkbox-ring)',
339+
'[--checkbox-ring:var(--color-zinc-400)]/50',
340+
'dark:[--checkbox-ring:white]/20',
341+
342+
// Hover
343+
'in-[&:is([data-ui=content],label)[data-hovered=true]]:[--checkbox-ring:var(--color-zinc-400)]/75',
344+
'dark:in-[&:is([data-ui=content],label)[data-hovered=true]]:[--checkbox-ring:white]/30',
345+
346+
// Selected
347+
'in-[&:is([data-ui=content],label)[data-selected=true]]:shadow-[inset_0_1px_0_0_rgba(255,255,255,0.25)]',
348+
'in-[&:is([data-ui=content],label)[data-selected=true]]:[--checkbox-ring:color-mix(in_oklab,_var(--__checkbox)_90%,_black)]',
349+
// 'in-[&:is([data-ui=content],label)[data-selected=true]]:ring-(--checkbox-ring)',
350+
'dark:in-[&:is([data-ui=content],label)[data-selected=true]]:ring-transparent',
351+
'in-[&:is([data-ui=content],label)[data-selected=true]]:bg-(--__checkbox)',
340352

341353
className,
342354
])}
@@ -351,7 +363,8 @@ export function CheckToggle({
351363
<>
352364
<CheckIcon
353365
className={twMerge(
354-
'hidden size-4 text-[lch(from_var(--accent)_calc((49.44_-_l)_*_infinity)_0_0)]',
366+
'size-(--__checkbox-size)',
367+
'hidden text-(----check)',
355368
renderProps?.isSelected &&
356369
!renderProps.isIndeterminate &&
357370
'inline',
@@ -361,7 +374,8 @@ export function CheckToggle({
361374

362375
<MinusIcon
363376
className={twMerge(
364-
'hidden size-4 text-[lch(from_var(--accent)_calc((49.44_-_l)_*_infinity)_0_0)]',
377+
'size-(--__checkbox-size)',
378+
'hidden text-(----check)',
365379
renderProps?.isIndeterminate && 'inline',
366380
)}
367381
/>

src/switch.tsx

Lines changed: 50 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -152,23 +152,7 @@ export function Switch(props: SwitchProps | CustomRenderSwitchProps) {
152152
{(renderProps) => (
153153
<>
154154
<SwitchToggle
155-
className={twMerge([
156-
'h-6 w-11',
157-
placement === 'end' ? 'me-3' : 'ms-3',
158-
159-
'[&>[data-ui=handle]]:size-5',
160-
renderProps.isSelected &&
161-
'rtl:[&>[data-ui=handle]]-translate-x-5 [&>[data-ui=handle]]:translate-x-5',
162-
163-
size === 'lg'
164-
? []
165-
: [
166-
'sm:h-5 sm:w-8',
167-
'sm:[&>[data-ui=handle]]:size-4',
168-
renderProps.isSelected &&
169-
'sm:[&>[data-ui=handle]]:translate-x-3 sm:rtl:[&>[data-ui=handle]]:-translate-x-3',
170-
],
171-
])}
155+
className={twMerge([placement === 'end' ? 'me-3' : 'ms-3'])}
172156
renderProps={renderProps}
173157
/>
174158
{typeof children === 'function' ? children(renderProps) : children}
@@ -192,46 +176,64 @@ export function SwitchToggle({
192176
{...props}
193177
data-check-indicator
194178
className={twMerge(
195-
'flex h-5 w-8 shrink-0 cursor-default items-center rounded-full bg-zinc-200 p-0.5 ring-1 ring-zinc-300/90 dark:bg-zinc-700 dark:ring-0 dark:inset-ring-1 dark:inset-ring-white/10',
196-
197-
renderProps?.isReadOnly
198-
? 'opacity-50'
199-
: renderProps?.isHovered &&
200-
'ring-zinc-400/70 dark:inset-ring-white/15',
201-
renderProps?.isSelected &&
202-
'bg-accent dark:bg-accent ring-accent inset-ring-[rgba(255,255,255,0.1)]',
203-
renderProps?.isDisabled && 'bg-gray-200 dark:bg-zinc-700',
204-
renderProps?.isFocusVisible &&
205-
'outline-ring outline-2 outline-offset-3',
206-
207-
// When it is inside menu item and the item is selected
208-
'in-[&[data-ui=content][data-hovered=true]]:ring-zinc-400/70',
209-
'in-[&[data-ui=content][data-hovered=true]]:dark:inset-ring-white/15',
210-
211-
'in-[&[data-ui=content][data-selected=true]]:bg-accent',
212-
'in-[&[data-ui=content][data-selected=true]]:dark:bg-accent',
213-
'in-[&[data-ui=content][data-selected=true]]:ring-accent',
214-
'in-[&[data-ui=content][data-selected=true]]:inset-ring-[rgba(255,255,255,0.1)]',
215-
179+
'[--__thumb-size:var(--thumb-size,--spacing(4))]',
180+
'[--__switch-bg:var(--switch-bg,var(--accent))]',
181+
'h-[calc(var(--__thumb-size)+calc(--spacing(0.5)*2))]',
182+
'w-[calc(calc(var(--__thumb-size)+calc(--spacing(0.5)))*2)]',
183+
'flex shrink-0 items-center rounded-full p-0.5',
184+
185+
'[--handle-selected:lch(from_var(--__switch-bg)_calc((64.28_-_l)_*_infinity)_0_0)]',
186+
'[--switch-focus-ring:color-mix(in_oklab,_var(--__switch-bg)_65%,_var(--handle-selected))]',
187+
188+
// Readonly
189+
'in-[&:is([data-ui=content],label)[data-readonly=true]]:opacity-50',
190+
191+
// Focus visible
192+
'in-[&:is([data-ui=content],label)[data-focus-visible=true]]:outline-(--switch-focus-ring)',
193+
'in-[&:is([data-ui=content],label)[data-focus-visible=true]]:outline-2',
194+
'in-[&:is([data-ui=content],label)[data-focus-visible=true]]:outline-offset-3',
195+
196+
'ring-1',
197+
'ring-(--switch-ring)',
198+
'[--switch-ring:var(--color-zinc-400)]/50',
199+
200+
// When hover
201+
'in-[&:is([data-ui=content],label)[data-hovered=true]]:[--switch-ring:var(--color-zinc-400)]/75',
202+
203+
// When selected
204+
'in-[&:is([data-ui=content],label)[data-selected=true]]:[--switch-ring:color-mix(in_oklab,_var(--__switch-bg)_90%,_black)]',
205+
206+
// Dark
207+
// Use inset ring
208+
'dark:ring-0',
209+
'dark:inset-ring-1',
210+
'dark:inset-ring-white/10',
211+
// When hover
212+
'dark:in-[&:is([data-ui=content],label)[data-hovered=true]]:inset-ring-white/30',
213+
// When selected
214+
'dark:in-[&:is([data-ui=content],label)[data-selected=true]]:shadow-[inset_0_1px_0_0_rgba(255,255,255,0.25)]',
215+
216+
// Bg
217+
'bg-zinc-200 dark:bg-zinc-700',
218+
219+
// Selected
220+
'in-[&:is([data-ui=content],label)[data-selected=true]]:bg-(--__switch-bg)',
221+
'in-[&:is([data-ui=content],label)[data-selected=true]]:dark:bg-(--__switch-bg)',
222+
'in-[&:is([data-ui=content],label)[data-selected=true]]:ring-(--switch-ring)',
216223
className,
217224
)}
218225
>
219226
<span
220227
data-ui="handle"
221228
className={twMerge(
222-
'size-4',
229+
'size-(--__thumb-size)',
223230
'rounded-full bg-white shadow-[0_1px_1px_rgba(0,0,0,0.25)] transition-all ease-in-out',
224-
225231
// When it is inside menu item and the item is selected
226-
'in-[&[data-ui=content][data-selected=true]]:translate-x-3',
227-
'in-[&[data-ui=content][data-selected=true]]:rtl:-translate-x-3',
228-
'in-[&[data-ui=content][data-selected=true]]:bg-[lch(from_var(--accent)_calc((49.44_-_l)_*_infinity)_0_0)]',
229-
230-
renderProps?.isSelected && [
231-
'translate-x-3 bg-[lch(from_var(--accent)_calc((49.44_-_l)_*_infinity)_0_0)] rtl:-translate-x-3',
232-
],
232+
'in-[&:is([data-ui=content],label)[data-selected=true]]:translate-x-(--__thumb-size)',
233+
'in-[&:is([data-ui=content],label)[data-selected=true]]:rtl:-translate-x-(--__thumb-size)',
234+
'in-[&:is([data-ui=content],label)[data-selected=true]]:bg-(--handle-selected)',
233235
)}
234236
/>
235237
</div>
236238
);
237-
}
239+
}

0 commit comments

Comments
 (0)