@vvedantb/ui 0.16.0 → 0.16.2
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/README.md
CHANGED
|
@@ -642,6 +642,8 @@ The root `cn` knows these are radius classes, so `cn("rounded-lg", "rounded-menu
|
|
|
642
642
|
| `DropdownMenu` and `ContextMenu` item, sub-trigger, checkbox item and radio item | `rounded-md`, `calc(var(--radius) - 2px)` (14px) | `rounded-menu-item` (8px) |
|
|
643
643
|
| Menu surface | `rounded-lg` (16px) | unchanged |
|
|
644
644
|
|
|
645
|
+
From 0.16.2, `Select` and `RadixSelect` items (`rounded-lg`, 16px), `CommandItem` (`rounded-md`, 14px) and `ComposerSlashMenu` rows (`rounded-lg`, 16px) also use `rounded-menu-item` (8px).
|
|
646
|
+
|
|
645
647
|
### Sidebar panel nav rows
|
|
646
648
|
|
|
647
649
|
Rows in the panel beside the rail. Rail tiles are unchanged.
|
|
@@ -1002,7 +1004,7 @@ import { DatePicker, DateTimePicker, MonthPicker } from "@vvedantb/ui";
|
|
|
1002
1004
|
- `MonthPicker`: `value` "YYYY-MM" or "", with year navigation and a month grid. `min` and `max` are "YYYY-MM".
|
|
1003
1005
|
- `Calendar`: the styled `DayPicker` for custom layouts (every `DayPicker` prop). `parseDateValue` and `formatDateValue` convert between "YYYY-MM-DD" and a local `Date`.
|
|
1004
1006
|
|
|
1005
|
-
## Slider (0.16.0)
|
|
1007
|
+
## Slider (0.16.0, dark contrast and className props 0.16.1)
|
|
1006
1008
|
|
|
1007
1009
|
shadcn's slider on `@radix-ui/react-slider` (a peer dependency), with package tokens.
|
|
1008
1010
|
|
|
@@ -1014,7 +1016,7 @@ import { LabeledSliderRow, Slider } from "@vvedantb/ui";
|
|
|
1014
1016
|
<LabeledSliderRow id="temperature" label="Temperature" value={temp} onValueChange={setTemp} max={2} step={0.1} formatValue={(v) => v.map((n) => n.toFixed(1)).join("–")} minLabel="Precise" maxLabel="Creative" />
|
|
1015
1017
|
```
|
|
1016
1018
|
|
|
1017
|
-
- `Slider`: every Radix `Root` prop (`value`, `defaultValue`, `min`, `max`, `step`, `orientation`, `disabled`, `onValueChange`, `onValueCommit`, and so on). It renders one thumb per value, so `[n]` gives one thumb and `[a, b]` a range. The track is `bg-default
|
|
1019
|
+
- `Slider`: every Radix `Root` prop (`value`, `defaultValue`, `min`, `max`, `step`, `orientation`, `disabled`, `onValueChange`, `onValueCommit`, and so on). It renders one thumb per value, so `[n]` gives one thumb and `[a, b]` a range. The track is `bg-default` (`dark:bg-muted/40`), the range `bg-primary`, and the thumb a `size-4` circle on `bg-background` with `border-border` (`dark:bg-foreground dark:border-muted`, a light thumb in dark mode) and the `Switch` focus ring. `trackClassName`, `rangeClassName` and `thumbClassName` merge after the defaults, so caller classes win; override a `dark:` default with a `dark:` class. Disabled dims to 50%. A vertical slider needs a height from its parent or `className` (default `min-h-40`). The ref goes to `Root`.
|
|
1018
1020
|
- Names: `id`, `aria-label`, `aria-labelledby` and `aria-valuetext` go to the first thumb, the focusable `role="slider"` element, not `Root`. `thumbLabels` sets `aria-label` per thumb and wins over `aria-label` on the first. Without a name, Radix labels a two-thumb range "Minimum" and "Maximum". The thumb is a `<span>`, so `<Label htmlFor>` does not name it; pass `aria-labelledby` with the label's `id`.
|
|
1019
1021
|
- `LabeledSliderRow`: the `LabeledSwitchRow` layout with the slider below. `id`, `label`, `description`, `icon`, `value`, `onValueChange`, `onValueCommit`, `min`, `max`, `step`, `disabled`, `thumbLabels`, `className`. `formatValue` sets the right-aligned value (default: values joined by an en dash). `minLabel` and `maxLabel` add captions under the ends. The label names the first thumb through `aria-labelledby`, unless `thumbLabels` is set.
|
|
1020
1022
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vvedantb/ui",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Shared React 19 UI for web apps: one JavaScript entry (primitives, shell pieces, app helpers including the Convex and Clerk provider, VITE env parsing and ensure-user, artifact viewers over the @vvedantb/server artifacts core, native tokens), design-token CSS, shared Tailwind v4 CSS and a Tailwind preset.",
|
|
6
6
|
"type": "module",
|
|
@@ -108,7 +108,7 @@ export function ComposerSlashMenu({
|
|
|
108
108
|
onSelectItem(item);
|
|
109
109
|
}}
|
|
110
110
|
className={
|
|
111
|
-
"mx-1 flex w-[calc(100%-0.5rem)] min-w-0 items-center rounded-
|
|
111
|
+
"mx-1 flex w-[calc(100%-0.5rem)] min-w-0 items-center rounded-menu-item px-2 py-1.5 text-left text-sm max-sm:py-2.5 " +
|
|
112
112
|
"transition-[background-color] active:scale-[0.99] active:duration-100 active:ease-out " +
|
|
113
113
|
(isSelected
|
|
114
114
|
? "bg-primary/15 font-medium text-foreground dark:bg-primary/25"
|
package/src/ui/command.tsx
CHANGED
|
@@ -28,7 +28,7 @@ Command.displayName = CommandPrimitive.displayName;
|
|
|
28
28
|
// The list is pinned rather than `max-h`: a palette that resizes on every
|
|
29
29
|
// keystroke shifts the whole dialog under the cursor.
|
|
30
30
|
const commandDialogPinnedClass =
|
|
31
|
-
"[&_[cmdk-list]]:h-80 [&_[cmdk-list]]:max-h-[60dvh] [&_[cmdk-group-heading]]:px-2.5 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-semibold [&_[cmdk-group-heading]]:uppercase [&_[cmdk-group-heading]]:tracking-widest [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-1.5 [&_[cmdk-input-wrapper]_svg]:h-4 [&_[cmdk-input-wrapper]_svg]:w-4 [&_[cmdk-input]]:h-11 [&_[cmdk-item]]:rounded-
|
|
31
|
+
"[&_[cmdk-list]]:h-80 [&_[cmdk-list]]:max-h-[60dvh] [&_[cmdk-group-heading]]:px-2.5 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-semibold [&_[cmdk-group-heading]]:uppercase [&_[cmdk-group-heading]]:tracking-widest [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-1.5 [&_[cmdk-input-wrapper]_svg]:h-4 [&_[cmdk-input-wrapper]_svg]:w-4 [&_[cmdk-input]]:h-11 [&_[cmdk-item]]:rounded-menu-item [&_[cmdk-item]]:px-2.5 [&_[cmdk-item]]:py-2 [&_[cmdk-item]_svg]:h-4 [&_[cmdk-item]_svg]:w-4";
|
|
32
32
|
|
|
33
33
|
// The list sizes itself and items keep the caller's styling.
|
|
34
34
|
const commandDialogAutoClass =
|
|
@@ -155,7 +155,7 @@ const CommandItem = React.forwardRef<
|
|
|
155
155
|
<CommandPrimitive.Item
|
|
156
156
|
ref={ref}
|
|
157
157
|
className={cn(
|
|
158
|
-
"relative flex cursor-default gap-2 select-none items-center rounded-
|
|
158
|
+
"relative flex cursor-default gap-2 select-none items-center rounded-menu-item px-2.5 py-2 text-sm outline-none transition-colors data-[disabled=true]:pointer-events-none data-[selected=true]:bg-surface-tertiary/80 data-[selected=true]:text-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
159
159
|
className,
|
|
160
160
|
)}
|
|
161
161
|
{...props}
|
package/src/ui/radix-select.tsx
CHANGED
|
@@ -117,7 +117,7 @@ function SelectItem({
|
|
|
117
117
|
<SelectPrimitive.Item
|
|
118
118
|
data-slot="select-item"
|
|
119
119
|
className={cn(
|
|
120
|
-
"[&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-pointer select-none items-center gap-2 rounded-
|
|
120
|
+
"[&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-pointer select-none items-center gap-2 rounded-menu-item py-2 pl-2.5 pr-8 text-sm outline-hidden [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 last:[span]:*:flex last:[span]:*:items-center last:[span]:*:gap-2",
|
|
121
121
|
menuItemClass,
|
|
122
122
|
className,
|
|
123
123
|
)}
|
package/src/ui/select.tsx
CHANGED
|
@@ -122,7 +122,7 @@ const SelectItem = React.forwardRef<
|
|
|
122
122
|
<SelectPrimitive.Item
|
|
123
123
|
ref={ref}
|
|
124
124
|
className={cn(
|
|
125
|
-
"relative flex w-full cursor-pointer select-none items-center rounded-
|
|
125
|
+
"relative flex w-full cursor-pointer select-none items-center rounded-menu-item py-2 max-sm:min-h-10 pl-2.5 pr-8 text-sm outline-none transition-[background-color,color] focus:bg-default focus:text-foreground data-[highlighted]:bg-default data-[highlighted]:text-foreground data-[disabled]:pointer-events-none data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50",
|
|
126
126
|
className,
|
|
127
127
|
)}
|
|
128
128
|
{...props}
|
package/src/ui/slider.tsx
CHANGED
|
@@ -5,6 +5,12 @@ import { cn } from "../utils/cn";
|
|
|
5
5
|
type SliderProps = React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root> & {
|
|
6
6
|
/** Accessible name per thumb, by index. Wins over `aria-label` on the first thumb. */
|
|
7
7
|
thumbLabels?: string[];
|
|
8
|
+
/** Classes for the track, merged after the defaults so they win (`bg-default dark:bg-muted/40`). */
|
|
9
|
+
trackClassName?: string;
|
|
10
|
+
/** Classes for the filled range, merged after the defaults so they win (`bg-primary`). */
|
|
11
|
+
rangeClassName?: string;
|
|
12
|
+
/** Classes for every thumb, merged after the defaults so they win (`bg-background dark:bg-foreground dark:border-muted`). */
|
|
13
|
+
thumbClassName?: string;
|
|
8
14
|
};
|
|
9
15
|
|
|
10
16
|
// `id`, `aria-label`, `aria-labelledby` and `aria-valuetext` go to the first
|
|
@@ -19,6 +25,9 @@ const Slider = React.forwardRef<React.ComponentRef<typeof SliderPrimitive.Root>,
|
|
|
19
25
|
"aria-labelledby": ariaLabelledBy,
|
|
20
26
|
"aria-valuetext": ariaValueText,
|
|
21
27
|
thumbLabels,
|
|
28
|
+
trackClassName,
|
|
29
|
+
rangeClassName,
|
|
30
|
+
thumbClassName,
|
|
22
31
|
...props
|
|
23
32
|
},
|
|
24
33
|
ref,
|
|
@@ -33,8 +42,18 @@ const Slider = React.forwardRef<React.ComponentRef<typeof SliderPrimitive.Root>,
|
|
|
33
42
|
{...props}
|
|
34
43
|
ref={ref}
|
|
35
44
|
>
|
|
36
|
-
<SliderPrimitive.Track
|
|
37
|
-
|
|
45
|
+
<SliderPrimitive.Track
|
|
46
|
+
className={cn(
|
|
47
|
+
"relative grow overflow-hidden rounded-full bg-default dark:bg-muted/40 data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5",
|
|
48
|
+
trackClassName,
|
|
49
|
+
)}
|
|
50
|
+
>
|
|
51
|
+
<SliderPrimitive.Range
|
|
52
|
+
className={cn(
|
|
53
|
+
"absolute bg-primary data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full",
|
|
54
|
+
rangeClassName,
|
|
55
|
+
)}
|
|
56
|
+
/>
|
|
38
57
|
</SliderPrimitive.Track>
|
|
39
58
|
{Array.from({ length: count }, (_, i) => (
|
|
40
59
|
<SliderPrimitive.Thumb
|
|
@@ -43,7 +62,10 @@ const Slider = React.forwardRef<React.ComponentRef<typeof SliderPrimitive.Root>,
|
|
|
43
62
|
aria-label={thumbLabels?.[i] ?? (i === 0 ? ariaLabel : undefined)}
|
|
44
63
|
aria-labelledby={i === 0 ? ariaLabelledBy : undefined}
|
|
45
64
|
aria-valuetext={i === 0 ? ariaValueText : undefined}
|
|
46
|
-
className=
|
|
65
|
+
className={cn(
|
|
66
|
+
"block size-4 shrink-0 rounded-full border border-border bg-background shadow-sm transition-[box-shadow] duration-200 ease-smooth focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring data-[disabled]:cursor-not-allowed dark:border-muted dark:bg-foreground",
|
|
67
|
+
thumbClassName,
|
|
68
|
+
)}
|
|
47
69
|
/>
|
|
48
70
|
))}
|
|
49
71
|
</SliderPrimitive.Root>
|