feat(htmx-css): ToggleGroup support + padding/primary parity
Generator (scripts/generate-htmx-css.ts): track `viaVariants` per slot so
slots that compose another component's variant system (e.g. ToggleGroupItem
via toggleVariants) inherit the referenced CVA's base + variant rules under
their own selector. Previously toggle-group-item's CSS contained only its
override classes, shipping with no padding/height/hover/active state.
Toggle (components/ui/toggle.tsx):
- data-[state=on] now uses bg-primary (orange) instead of bg-accent (grey),
matching every other "commit" affordance in the palette.
- Horizontal padding aligned with Button: px-4/px-3/px-6 per size, plus
has-[>svg]:px-* for icon-only toggles.
ToggleGroup (components/ui/toggle-group.tsx): drop min-w-0 flex-1 shrink-0
from the item override. Items now size to content instead of being clamped
into equal narrow columns where longer labels overflowed the bg box.
Showcase: add ToggleGroup section to the React page (component-matrix.tsx)
and 1:1 HTMX mirror (public/htmx.html) with a new JS bridge branch for
single/multi-select. compare-all.sh extended with the new section; 22/22
pass at ≥99.97%.
Docs: GAPS.md captures the generator gap, overflow root cause, color
rationale, and padding parity with before/after numbers.
This commit is contained in:
@@ -7,6 +7,7 @@ import { Checkbox } from "@/components/ui/checkbox"
|
||||
import { Switch } from "@/components/ui/switch"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
|
||||
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
@@ -455,6 +456,69 @@ export function ComponentMatrix() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Toggle Group */}
|
||||
<div id="sub-toggle-group">
|
||||
<h4 className="font-sans text-sm font-semibold uppercase tracking-wide text-muted-foreground mb-4">
|
||||
Toggle Group
|
||||
</h4>
|
||||
<div className="border border-border rounded-md p-6 bg-card">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<p className="font-sans text-xs text-muted-foreground mb-2">Single, outline</p>
|
||||
<ToggleGroup type="single" variant="outline" defaultValue="light" aria-label="Theme">
|
||||
<ToggleGroupItem value="system" aria-label="System">System</ToggleGroupItem>
|
||||
<ToggleGroupItem value="light" aria-label="Light">Light</ToggleGroupItem>
|
||||
<ToggleGroupItem value="dark" aria-label="Dark">Dark</ToggleGroupItem>
|
||||
</ToggleGroup>
|
||||
</div>
|
||||
<div>
|
||||
<p className="font-sans text-xs text-muted-foreground mb-2">Single, default</p>
|
||||
<ToggleGroup type="single" defaultValue="grid" aria-label="Layout">
|
||||
<ToggleGroupItem value="list" aria-label="List">List</ToggleGroupItem>
|
||||
<ToggleGroupItem value="grid" aria-label="Grid">Grid</ToggleGroupItem>
|
||||
<ToggleGroupItem value="board" aria-label="Board" disabled>Board</ToggleGroupItem>
|
||||
</ToggleGroup>
|
||||
</div>
|
||||
<div>
|
||||
<p className="font-sans text-xs text-muted-foreground mb-2">Multiple</p>
|
||||
<ToggleGroup type="multiple" variant="outline" defaultValue={["bold"]} aria-label="Text formatting">
|
||||
<ToggleGroupItem value="bold" aria-label="Bold">Bold</ToggleGroupItem>
|
||||
<ToggleGroupItem value="italic" aria-label="Italic">Italic</ToggleGroupItem>
|
||||
<ToggleGroupItem value="underline" aria-label="Underline">Underline</ToggleGroupItem>
|
||||
</ToggleGroup>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<p className="font-sans text-xs text-muted-foreground mb-2">Small</p>
|
||||
<ToggleGroup type="single" variant="outline" size="sm" defaultValue="light" aria-label="Theme (sm)">
|
||||
<ToggleGroupItem value="system">System</ToggleGroupItem>
|
||||
<ToggleGroupItem value="light">Light</ToggleGroupItem>
|
||||
<ToggleGroupItem value="dark">Dark</ToggleGroupItem>
|
||||
</ToggleGroup>
|
||||
</div>
|
||||
<div>
|
||||
<p className="font-sans text-xs text-muted-foreground mb-2">Default</p>
|
||||
<ToggleGroup type="single" variant="outline" defaultValue="light" aria-label="Theme (default)">
|
||||
<ToggleGroupItem value="system">System</ToggleGroupItem>
|
||||
<ToggleGroupItem value="light">Light</ToggleGroupItem>
|
||||
<ToggleGroupItem value="dark">Dark</ToggleGroupItem>
|
||||
</ToggleGroup>
|
||||
</div>
|
||||
<div>
|
||||
<p className="font-sans text-xs text-muted-foreground mb-2">Large</p>
|
||||
<ToggleGroup type="single" variant="outline" size="lg" defaultValue="light" aria-label="Theme (lg)">
|
||||
<ToggleGroupItem value="system">System</ToggleGroupItem>
|
||||
<ToggleGroupItem value="light">Light</ToggleGroupItem>
|
||||
<ToggleGroupItem value="dark">Dark</ToggleGroupItem>
|
||||
</ToggleGroup>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Tooltips */}
|
||||
<div>
|
||||
<h4 className="font-sans text-sm font-semibold uppercase tracking-wide text-muted-foreground mb-4">
|
||||
|
||||
@@ -60,7 +60,7 @@ function ToggleGroupItem({
|
||||
variant: context.variant || variant,
|
||||
size: context.size || size,
|
||||
}),
|
||||
'min-w-0 flex-1 shrink-0 rounded-none shadow-none first:rounded-l-md last:rounded-r-md focus:z-10 focus-visible:z-10 data-[variant=outline]:border-l-0 data-[variant=outline]:first:border-l',
|
||||
'rounded-none shadow-none first:rounded-l-md last:rounded-r-md focus:z-10 focus-visible:z-10 data-[variant=outline]:border-l-0 data-[variant=outline]:first:border-l',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -7,7 +7,7 @@ import { cva, type VariantProps } from 'class-variance-authority'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const toggleVariants = cva(
|
||||
"inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium hover:bg-muted hover:text-muted-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] outline-none transition-[color,box-shadow] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive whitespace-nowrap",
|
||||
"inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium hover:bg-muted hover:text-muted-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-primary data-[state=on]:text-primary-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] outline-none transition-[color,box-shadow] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive whitespace-nowrap",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
@@ -16,9 +16,9 @@ const toggleVariants = cva(
|
||||
'border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground',
|
||||
},
|
||||
size: {
|
||||
default: 'h-9 px-2 min-w-9',
|
||||
sm: 'h-8 px-1.5 min-w-8',
|
||||
lg: 'h-10 px-2.5 min-w-10',
|
||||
default: 'h-9 px-4 min-w-9 has-[>svg]:px-3',
|
||||
sm: 'h-8 px-3 min-w-8 has-[>svg]:px-2.5',
|
||||
lg: 'h-10 px-6 min-w-10 has-[>svg]:px-4',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
|
||||
Reference in New Issue
Block a user