Box Shadow Editor
ridiculous/box-shadow-editorFreeComponent
Ridiculously typed CSS box-shadow editor — a comma-separated list of shadow layers, each validated at compile time (2–4 lengths, at most one inset, an optional trailing color). Ships a live preview with a draggable light source and elevation scrubber.
Install it
npx shadcn@latest add http://ridiculous.turtlesocks.dev/r/box-shadow-editor.jsonSource
1"use client"23import { useEffect, useRef, useState } from "react"4import { Button } from "@/components/ui/button"5import {6 Popover,7 PopoverContent,8 PopoverTrigger,9} from "@/components/ui/popover"10import { cn } from "@/lib/utils"11import {12 boxShadowLayerCount,13 defaultLayer,14 formatBoxShadow,15 parseBoxShadow,16} from "./box-shadow-editor.helpers"17import type { BoxShadowString, ShadowLayer } from "./box-shadow-editor.types"18import { BoxShadowPreview } from "./box-shadow-preview"19import { ShadowLayerRow } from "./shadow-layer-row"2021// Re-export the extracted sub-components + their prop types so the public22// entry surface (and existing deep imports) is unchanged by the file split.23export type { BoxShadowPreviewProps } from "./box-shadow-preview"24export { BoxShadowPreview } from "./box-shadow-preview"25export type { ShadowLayerRowProps } from "./shadow-layer-row"26export { ShadowLayerRow } from "./shadow-layer-row"27export type { ShadowLengthEditorProps } from "./shadow-length-editor"28export { ShadowLengthEditor } from "./shadow-length-editor"2930// ---------------------------------------------------------------------------31// Shared props32// ---------------------------------------------------------------------------3334export interface BoxShadowEditorPanelProps {35 value: BoxShadowString | (string & {})36 onChange: (value: BoxShadowString) => void37 className?: string38 "aria-label"?: string39}4041export type BoxShadowEditorProps = BoxShadowEditorPanelProps4243// ---------------------------------------------------------------------------44// BoxShadowEditor — popover-wrapped45// ---------------------------------------------------------------------------4647export function BoxShadowEditor(props: BoxShadowEditorProps) {48 const {49 value,50 className,51 "aria-label": ariaLabel = "Edit a CSS box-shadow",52 } = props53 const count = boxShadowLayerCount(String(value))54 const applied = String(value) === "none" ? undefined : String(value)5556 return (57 <Popover>58 <PopoverTrigger asChild>59 <Button60 variant="outline"61 className={cn("h-9 gap-2 px-3 font-mono", className)}62 aria-label={ariaLabel}63 >64 <span65 aria-hidden="true"66 className="inline-block h-4 w-4 rounded-sm bg-background"67 style={{ boxShadow: applied }}68 />69 <span className="text-[10px] text-muted-foreground">70 {count} {count === 1 ? "layer" : "layers"}71 </span>72// … truncated
What it pulls in
Other registry items
Files it writes
More from ridiculous
All 22 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| All ridiculous componentsall | ridiculous | Components | Free | no deps | |
| Anchor Position Editoranchor-position-editor | ridiculous | Components | Free | no deps · 9 files | |
| Background Editorbackground-editor | ridiculous | Components | Free | no deps · 9 files | |
| Calc Editorcalc-editor | ridiculous | Components | Free | no deps · 4 files | |
| Clip Path Editorclip-path-editor | ridiculous | Components | Free | no deps · 20 files | |
| Color Functioncolor-function | ridiculous | Components | Free | no deps · 10 files | |
| Color Pickercolor-picker | ridiculous | Components | Free | no deps · 11 files | |
| Easing Pickereasing-picker | ridiculous | Components | Free | no deps · 17 files |
