Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

57 linesCodeBlameRaw
1import { Switch as Primitive } from "radix-ui";
2import { type ComponentProps, type ReactNode, useId } from "react";
3
4import { cn } from "../../lib/cn";
5
6// shadcn/ui's switch, styled with g1t's tokens. Like a checkbox, inside a
7// <Form> a `name` posts `value` (default "on") when on and nothing when off.
8
9export function Switch({ className, size = "default", ...props }: ComponentProps<typeof Primitive.Root> & { size?: "sm" | "default" }) {
10 return (
11 <Primitive.Root
12 data-size={size}
13 className={cn(
14 "peer group/switch inline-flex shrink-0 items-center rounded-full border border-transparent p-px outline-none transition-colors",
15 "data-[size=default]:h-5 data-[size=default]:w-9 data-[size=sm]:h-4 data-[size=sm]:w-7",
16 "bg-line-strong data-[state=checked]:bg-accent",
17 "focus-visible:ring-2 focus-visible:ring-accent/40 focus-visible:ring-offset-1 focus-visible:ring-offset-bg focus-visible:outline-none",
18 "disabled:cursor-not-allowed disabled:opacity-50",
19 className,
20 )}
21 {...props}
22 >
23 <Primitive.Thumb
24 className={cn(
25 "pointer-events-none block rounded-full bg-fg shadow-sm ring-0 transition-transform duration-200",
26 "group-data-[size=default]/switch:size-4 group-data-[size=sm]/switch:size-3",
27 "data-[state=unchecked]:translate-x-0 group-data-[size=default]/switch:data-[state=checked]:translate-x-4 group-data-[size=sm]/switch:data-[state=checked]:translate-x-3",
28 )}
29 />
30 </Primitive.Root>
31 );
32}
33
34/**
35 * A setting that is on or off, as a card: a title, what it means, and the
36 * switch. The whole card toggles it.
37 */
38export function SwitchCard({ title, children, className, ...props }: ComponentProps<typeof Primitive.Root> & { title: ReactNode; children?: ReactNode }) {
39 const generated = useId();
40 const id = props.id ?? generated;
41 return (
42 <label
43 htmlFor={id}
44 className={cn(
45 "flex cursor-pointer items-start justify-between gap-4 rounded-xl border border-line bg-surface p-4 transition-colors hover:border-line-strong",
46 "has-data-[state=checked]:border-accent/40 has-disabled:cursor-not-allowed has-disabled:opacity-60",
47 className,
48 )}
49 >
50 <span className="min-w-0">
51 <span className="block text-sm font-medium text-fg">{title}</span>
52 {children && <span className="mt-1 block text-sm text-muted">{children}</span>}
53 </span>
54 <Switch id={id} className="mt-0.5" {...props} />
55 </label>
56 );
57}