1import { useState } from "react";2
3import { StatusToggle } from "@/components/features/pxl/tasks/status-toggle";4
5export default function StatusToggleDemo() {6 const [status, setStatus] = useState<"open" | "in-progress" | "done">("open");7
8 const toggle = () => {9 setStatus(10 status === "open"11 ? "in-progress"12 : status === "in-progress"13 ? "done"14 : "open",15 );16 };17
18 return (19 <div className="flex flex-col gap-4">20 <StatusToggle onClick={toggle} value={status} />21 </div>22 );23}Installation
Section titled “Installation”pnpm dlx shadcn@latest add pxl-ui/registry/tasks/status-toggle
Copy and paste the following code into your project.
1import { Button } from "@base-ui/react/button";2import { cva, type VariantProps } from "class-variance-authority";3import type { ComponentProps, SVGProps } from "react";4
5import type { TaskNotes } from "@/lib/schemas/pxl/tasknotes";6import { cn } from "@/lib/utils";7
8const statusToggleVariants = cva(9 "group/button inline-flex shrink-0 items-center justify-center bg-clip-padding font-medium whitespace-nowrap outline-none select-none focus-visible:border-ring focus-visible:ring-1 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-1 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='fill-'])]:fill-current pixel-border pixel-color-foreground pixel-size-md transition-all animation-duration-1000 hover:animate-pulse",10 {11 defaultVariants: {12 size: "icon",13 },14 variants: {15 size: {16 icon: "size-4",17 "icon-xs": "size-3",18 "icon-sm": "size-3.5",19 "icon-md": "size-4",20 "icon-lg": "size-4.5",21 },22 },23 },24);25
26const ToggleIcon = {27 InProgress(props: SVGProps<SVGSVGElement>) {28 return (29 <svg fill="currentColor" viewBox="0 0 24 24"30 {...props}>31 <path d="M14 16h-4v-2h4v2Zm-4-2H8v-4h2v4Zm6 0h-2v-4h2v4Zm-2-4h-4V8h4v2Z" />32 </svg>33 );34 },35 Done(props: SVGProps<SVGSVGElement>) {36 return (37 <svg38 xmlns="http://www.w3.org/2000/svg"39 fill="currentColor" viewBox="0 0 24 24"40 {...props}>41 <path d="M10 18H8v-2h2v2Zm-2-2H6v-2h2v2Zm4-2v2h-2v-2h2Zm-6 0H4v-2h2v2Zm8 0h-2v-2h2v2Zm2-2h-2v-2h2v2Zm2-2h-2V8h2v2Zm2-2h-2V6h2v2Z"/>42 </svg>43 );44 },45};46
47function StatusToggle({48 size = "icon",49 value = "open",50 ...props51}: Button.Props &52 VariantProps<typeof statusToggleVariants> & {53 value: "open" | "in-progress" | "done";54 }) {55 return (56 <Button57 type="button"58 data-slot="button"59 data-size={size}60 className={cn(statusToggleVariants({ size }))}61 {...props}62 >63 {value === "in-progress" && (<ToggleIcon.InProgress className="size-full" />)}64 {value === "done" && <ToggleIcon.Done className="size-full" />}65 </Button>66 );67}68
69function TaskNotesStatusToggle({70 task,71 ...props72}: VariantProps<typeof statusToggleVariants> & {73 task: TaskNotes.Task;74}) {75 return (76 <StatusToggle77 {...props}78 value={task.status === "none" ? "open" : task.status}79 />80 );81}82StatusToggle.TaskNotes = TaskNotesStatusToggle;83
84export { StatusToggle };Update the import paths to match your project setup.
import { StatusToggle } from "@/components/features/pxl/tasks/status-toggle";<StatusToggle value="in-progress" />