sudo: selects drawn as a native select with our own chevron, the browser's arrow hidden
1 file+18−20/1 viewed
| 3 | 3 | * sets a `style` attribute: the content security policy allows no inline | |
| 4 | 4 | * styles, so sizes and colours that vary are drawn as SVG attributes. | |
| 5 | 5 | */ | |
| 6 | − | import { AlertTriangle, CheckCircle2, Info } from "lucide-react"; | |
| 6 | + | import { AlertTriangle, CheckCircle2, ChevronDown, Info } from "lucide-react"; | |
| 7 | 7 | import type { ComponentProps, ReactNode } from "react"; | |
| 8 | 8 | import { Link, type LinkProps, useRouteLoaderData } from "react-router"; | |
| 9 | 9 | ||
| ⋯ | |||
| 53 | 53 | return <textarea {...NOT_A_CREDENTIAL} {...props} className={`${CONTROL} ${className}`} />; | |
| 54 | 54 | } | |
| 55 | 55 | ||
| 56 | + | /** Classes that size or place the control, which belong on its wrapper. */ | |
| 57 | + | const LAYOUT = /^(?:[a-z0-9]+:)*(?:w-|min-w-|max-w-|flex-|shrink|grow|basis-|self-|col-|row-|order-|m[trblxy]?-)/; | |
| 58 | + | ||
| 59 | + | /** | |
| 60 | + | * A native select drawn as shadcn's NativeSelect: the browser's own arrow | |
| 61 | + | * hidden, a chevron of ours in its place. Native because sudo ships no | |
| 62 | + | * JavaScript, so it still opens, types to search and works on phones. | |
| 63 | + | */ | |
| 56 | 64 | export function Select({ className = "", ...props }: ComponentProps<"select">) { | |
| 57 | − | return <select {...props} className={`${CONTROL} ${className}`} />; | |
| 65 | + | const classes = className.split(/\s+/).filter(Boolean); | |
| 66 | + | const outer = classes.filter((name) => LAYOUT.test(name)).join(" "); | |
| 67 | + | const inner = classes.filter((name) => !LAYOUT.test(name)).join(" "); | |
| 68 | + | return ( | |
| 69 | + | <span className={`relative block w-full ${outer}`}> | |
| 70 | + | <select {...props} className={`${CONTROL} cursor-pointer appearance-none pr-9 ${inner}`} /> | |
| 71 | + | <ChevronDown aria-hidden className="pointer-events-none absolute top-1/2 right-3 size-4 -translate-y-1/2 text-muted" /> | |
| 72 | + | </span> | |
| 73 | + | ); | |
| 58 | 74 | } | |
| 59 | 75 | ||
| 60 | 76 | type Variant = "primary" | "quiet" | "danger" | "lavender"; | |