diff --git a/apps/ui/public/r/p-dialog-4.json b/apps/ui/public/r/p-dialog-4.json index 1641c4d89..100d0db0e 100644 --- a/apps/ui/public/r/p-dialog-4.json +++ b/apps/ui/public/r/p-dialog-4.json @@ -13,7 +13,7 @@ "files": [ { "path": "registry/default/particles/p-dialog-4.tsx", - "content": "\"use client\";\n\nimport { useState } from \"react\";\nimport {\n AlertDialog,\n AlertDialogClose,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogPopup,\n AlertDialogTitle,\n} from \"@/registry/default/ui/alert-dialog\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Dialog,\n DialogClose,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogPanel,\n DialogPopup,\n DialogTitle,\n DialogTrigger,\n} from \"@/registry/default/ui/dialog\";\nimport { Field } from \"@/registry/default/ui/field\";\nimport { Form } from \"@/registry/default/ui/form\";\nimport { Textarea } from \"@/registry/default/ui/textarea\";\n\nexport default function Particle() {\n const [dialogOpen, setDialogOpen] = useState(false);\n const [confirmOpen, setConfirmOpen] = useState(false);\n const [value, setValue] = useState(\"\");\n\n return (\n {\n if (!o && value) {\n setConfirmOpen(true);\n } else {\n setDialogOpen(o);\n }\n }}\n open={dialogOpen}\n >\n }>\n Compose\n \n \n \n New message\n Type something and try closing.\n \n {\n event.preventDefault();\n // Close the dialog when submitting\n setDialogOpen(false);\n }}\n >\n \n \n setValue(e.target.value)}\n value={value}\n />\n \n \n \n }>\n Cancel\n \n {\n setValue(\"\");\n setDialogOpen(false);\n }}\n >\n Send\n \n \n \n \n\n {/* Confirmation dialog */}\n \n \n \n Discard changes?\n \n Your message will be lost.\n \n \n \n }>\n Go back\n \n {\n setConfirmOpen(false);\n setValue(\"\");\n setDialogOpen(false);\n }}\n >\n Discard\n \n \n \n \n \n );\n}\n", + "content": "\"use client\";\n\nimport { useState } from \"react\";\nimport {\n AlertDialog,\n AlertDialogClose,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogPopup,\n AlertDialogTitle,\n} from \"@/registry/default/ui/alert-dialog\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Dialog,\n DialogClose,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogPanel,\n DialogPopup,\n DialogTitle,\n DialogTrigger,\n} from \"@/registry/default/ui/dialog\";\nimport { Field } from \"@/registry/default/ui/field\";\nimport { Form } from \"@/registry/default/ui/form\";\nimport { Textarea } from \"@/registry/default/ui/textarea\";\n\nexport default function Particle() {\n const [dialogOpen, setDialogOpen] = useState(false);\n const [confirmOpen, setConfirmOpen] = useState(false);\n const [value, setValue] = useState(\"\");\n\n return (\n {\n if (!o && value) {\n setConfirmOpen(true);\n } else {\n setDialogOpen(o);\n }\n }}\n open={dialogOpen}\n >\n }>\n Compose\n \n \n \n New message\n Type something and try closing.\n \n {\n event.preventDefault();\n // Close the dialog when submitting\n setDialogOpen(false);\n }}\n >\n \n \n setValue(e.target.value)}\n value={value}\n />\n \n \n \n }>\n Cancel\n \n {\n setValue(\"\");\n setDialogOpen(false);\n }}\n >\n Send\n \n \n \n \n\n {/* Confirmation dialog */}\n \n \n \n Discard changes?\n \n Your message will be lost.\n \n \n \n }>\n Go back\n \n {\n setConfirmOpen(false);\n setValue(\"\");\n setDialogOpen(false);\n }}\n >\n Discard\n \n \n \n \n \n );\n}\n", "type": "registry:block" } ], diff --git a/apps/ui/public/r/p-field-10.json b/apps/ui/public/r/p-field-10.json index 28f615582..f8132b01b 100644 --- a/apps/ui/public/r/p-field-10.json +++ b/apps/ui/public/r/p-field-10.json @@ -9,7 +9,7 @@ "files": [ { "path": "registry/default/particles/p-field-10.tsx", - "content": "\"use client\";\n\nimport {\n Field,\n FieldDescription,\n FieldLabel,\n} from \"@/registry/default/ui/field\";\nimport { Textarea } from \"@/registry/default/ui/textarea\";\n\nexport default function Particle() {\n return (\n \n Bio\n \n \n Write a short bio. Maximum 500 characters.\n \n \n );\n}\n", + "content": "\"use client\";\n\nimport {\n Field,\n FieldDescription,\n FieldLabel,\n} from \"@/registry/default/ui/field\";\nimport { Textarea } from \"@/registry/default/ui/textarea\";\n\nexport default function Particle() {\n return (\n \n Bio\n \n \n Write a short bio. Maximum 500 characters.\n \n \n );\n}\n", "type": "registry:block" } ], diff --git a/apps/ui/public/r/p-input-group-22.json b/apps/ui/public/r/p-input-group-22.json index 85576d7fb..ca1072eea 100644 --- a/apps/ui/public/r/p-input-group-22.json +++ b/apps/ui/public/r/p-input-group-22.json @@ -12,7 +12,7 @@ "files": [ { "path": "registry/default/particles/p-input-group-22.tsx", - "content": "\"use client\";\n\nimport { XIcon } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n InputGroup,\n InputGroupAddon,\n InputGroupInput,\n} from \"@/registry/default/ui/input-group\";\n\nexport default function Particle() {\n const [value, setValue] = useState(\"Clear me\");\n\n return (\n \n setValue(e.target.value)}\n placeholder=\"Enter text\"\n type=\"text\"\n value={value}\n />\n {value && (\n \n setValue(\"\")}\n size=\"icon-xs\"\n variant=\"ghost\"\n >\n \n \n \n )}\n \n );\n}\n", + "content": "\"use client\";\n\nimport { XIcon } from \"lucide-react\";\nimport { useRef, useState } from \"react\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n InputGroup,\n InputGroupAddon,\n InputGroupInput,\n} from \"@/registry/default/ui/input-group\";\n\nexport default function Particle() {\n const inputRef = useRef(null);\n const [value, setValue] = useState(\"Clear me\");\n\n return (\n \n setValue(e.target.value)}\n placeholder=\"Enter text\"\n ref={inputRef}\n type=\"text\"\n value={value}\n />\n {value && (\n \n {\n setValue(\"\");\n inputRef.current?.focus();\n }}\n size=\"icon-xs\"\n variant=\"ghost\"\n >\n \n \n \n )}\n \n );\n}\n", "type": "registry:block" } ], diff --git a/apps/ui/public/r/p-input-group-29.json b/apps/ui/public/r/p-input-group-29.json index ff6c5a46d..a385adb4a 100644 --- a/apps/ui/public/r/p-input-group-29.json +++ b/apps/ui/public/r/p-input-group-29.json @@ -13,7 +13,7 @@ "files": [ { "path": "registry/default/particles/p-input-group-29.tsx", - "content": "\"use client\";\n\nimport { ArrowRightIcon, MicIcon } from \"lucide-react\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n InputGroup,\n InputGroupAddon,\n InputGroupText,\n InputGroupTextarea,\n} from \"@/registry/default/ui/input-group\";\nimport {\n Tooltip,\n TooltipPopup,\n TooltipTrigger,\n} from \"@/registry/default/ui/tooltip\";\n\nexport default function Particle() {\n return (\n \n \n \n \n \n }\n >\n \n \n Record voice message\n \n \n Press Enter to send\n \n \n \n }\n >\n \n \n Send\n \n \n \n );\n}\n", + "content": "\"use client\";\n\nimport { ArrowRightIcon, MicIcon } from \"lucide-react\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n InputGroup,\n InputGroupAddon,\n InputGroupText,\n InputGroupTextarea,\n} from \"@/registry/default/ui/input-group\";\nimport {\n Tooltip,\n TooltipPopup,\n TooltipTrigger,\n} from \"@/registry/default/ui/tooltip\";\n\nexport default function Particle() {\n return (\n \n \n \n \n \n }\n >\n \n \n Record voice message\n \n \n Press Enter to send\n \n \n \n }\n >\n \n \n Send\n \n \n \n );\n}\n", "type": "registry:block" } ], diff --git a/apps/ui/public/r/p-otp-field-1.json b/apps/ui/public/r/p-otp-field-1.json index 8a3208407..ceaca4144 100644 --- a/apps/ui/public/r/p-otp-field-1.json +++ b/apps/ui/public/r/p-otp-field-1.json @@ -3,12 +3,13 @@ "name": "p-otp-field-1", "description": "Basic OTP field", "registryDependencies": [ - "@coss/otp-field" + "@coss/otp-field", + "@coss/field" ], "files": [ { "path": "registry/default/particles/p-otp-field-1.tsx", - "content": "import { OTPField, OTPFieldInput } from \"@/registry/default/ui/otp-field\";\n\nconst OTP_LENGTH = 6;\n\nconst OTP_SLOT_KEYS = Array.from(\n { length: OTP_LENGTH },\n (_, i) => `otp-slot-${i}`,\n);\n\nexport default function Particle() {\n return (\n \n {OTP_SLOT_KEYS.map((slotKey, index) => (\n \n ))}\n \n );\n}\n", + "content": "import { Field, FieldLabel } from \"@/registry/default/ui/field\";\nimport { OTPField, OTPFieldInput } from \"@/registry/default/ui/otp-field\";\n\nconst OTP_LENGTH = 6;\n\nconst OTP_SLOT_KEYS = Array.from(\n { length: OTP_LENGTH },\n (_, i) => `otp-slot-${i}`,\n);\n\nexport default function Particle() {\n return (\n \n One-time password\n \n {OTP_SLOT_KEYS.map((slotKey, index) => (\n \n ))}\n \n \n );\n}\n", "type": "registry:block" } ], diff --git a/apps/ui/public/r/p-otp-field-2.json b/apps/ui/public/r/p-otp-field-2.json index 111f67fc8..737a1068b 100644 --- a/apps/ui/public/r/p-otp-field-2.json +++ b/apps/ui/public/r/p-otp-field-2.json @@ -3,12 +3,13 @@ "name": "p-otp-field-2", "description": "Large OTP field", "registryDependencies": [ - "@coss/otp-field" + "@coss/otp-field", + "@coss/field" ], "files": [ { "path": "registry/default/particles/p-otp-field-2.tsx", - "content": "import { OTPField, OTPFieldInput } from \"@/registry/default/ui/otp-field\";\n\nconst OTP_LENGTH = 4;\n\nconst OTP_SLOT_KEYS = Array.from(\n { length: OTP_LENGTH },\n (_, i) => `otp-slot-${i}`,\n);\n\nexport default function Particle() {\n return (\n \n {OTP_SLOT_KEYS.map((slotKey, index) => (\n \n ))}\n \n );\n}\n", + "content": "import { Field, FieldLabel } from \"@/registry/default/ui/field\";\nimport { OTPField, OTPFieldInput } from \"@/registry/default/ui/otp-field\";\n\nconst OTP_LENGTH = 4;\n\nconst OTP_SLOT_KEYS = Array.from(\n { length: OTP_LENGTH },\n (_, i) => `otp-slot-${i}`,\n);\n\nexport default function Particle() {\n return (\n \n One-time password\n \n {OTP_SLOT_KEYS.map((slotKey, index) => (\n \n ))}\n \n \n );\n}\n", "type": "registry:block" } ], diff --git a/apps/ui/public/r/p-otp-field-3.json b/apps/ui/public/r/p-otp-field-3.json index bfddca9ac..8fad39cb5 100644 --- a/apps/ui/public/r/p-otp-field-3.json +++ b/apps/ui/public/r/p-otp-field-3.json @@ -3,12 +3,13 @@ "name": "p-otp-field-3", "description": "OTP field with separator", "registryDependencies": [ - "@coss/otp-field" + "@coss/otp-field", + "@coss/field" ], "files": [ { "path": "registry/default/particles/p-otp-field-3.tsx", - "content": "import {\n OTPField,\n OTPFieldInput,\n OTPFieldSeparator,\n} from \"@/registry/default/ui/otp-field\";\n\nconst OTP_LENGTH = 6;\nconst GROUP_LENGTH = 3;\n\nconst OTP_SLOT_KEYS = Array.from(\n { length: OTP_LENGTH },\n (_, i) => `otp-slot-${i}`,\n);\n\nexport default function Particle() {\n return (\n \n {OTP_SLOT_KEYS.slice(0, GROUP_LENGTH).map((slotKey, index) => (\n \n ))}\n \n {OTP_SLOT_KEYS.slice(GROUP_LENGTH).map((slotKey, index) => (\n \n ))}\n \n );\n}\n", + "content": "import { Field, FieldLabel } from \"@/registry/default/ui/field\";\nimport {\n OTPField,\n OTPFieldInput,\n OTPFieldSeparator,\n} from \"@/registry/default/ui/otp-field\";\n\nconst OTP_LENGTH = 6;\nconst GROUP_LENGTH = 3;\n\nconst OTP_SLOT_KEYS = Array.from(\n { length: OTP_LENGTH },\n (_, i) => `otp-slot-${i}`,\n);\n\nexport default function Particle() {\n return (\n \n Verification code\n \n {OTP_SLOT_KEYS.slice(0, GROUP_LENGTH).map((slotKey, index) => (\n \n ))}\n \n {OTP_SLOT_KEYS.slice(GROUP_LENGTH).map((slotKey, index) => (\n \n ))}\n \n \n );\n}\n", "type": "registry:block" } ], diff --git a/apps/ui/public/r/p-otp-field-7.json b/apps/ui/public/r/p-otp-field-7.json index 5cf70a289..4f11385a8 100644 --- a/apps/ui/public/r/p-otp-field-7.json +++ b/apps/ui/public/r/p-otp-field-7.json @@ -9,7 +9,7 @@ "files": [ { "path": "registry/default/particles/p-otp-field-7.tsx", - "content": "\"use client\";\n\nimport { useState } from \"react\";\nimport {\n Field,\n FieldDescription,\n FieldError,\n FieldLabel,\n} from \"@/registry/default/ui/field\";\nimport { OTPField, OTPFieldInput } from \"@/registry/default/ui/otp-field\";\n\nconst OTP_LENGTH = 6;\n\nconst OTP_SLOT_KEYS = Array.from(\n { length: OTP_LENGTH },\n (_, i) => `otp-slot-${i}`,\n);\n\nexport default function Particle() {\n const [value, setValue] = useState(\"\");\n const [invalid, setInvalid] = useState(false);\n const valid = value.length === OTP_LENGTH && value === \"123456\";\n\n return (\n \n Verification code\n {\n setValue(nextValue);\n setInvalid(\n nextValue.length === OTP_LENGTH ? nextValue !== \"123456\" : false,\n );\n }}\n value={value}\n >\n {OTP_SLOT_KEYS.map((slotKey, index) => (\n \n ))}\n \n {!valid && !invalid && (\n Enter `123456` to pass validation.\n )}\n {invalid && Code must be 123456.}\n {valid && Code verified.}\n \n );\n}\n", + "content": "\"use client\";\n\nimport { useState } from \"react\";\nimport {\n Field,\n FieldDescription,\n FieldError,\n FieldLabel,\n} from \"@/registry/default/ui/field\";\nimport { OTPField, OTPFieldInput } from \"@/registry/default/ui/otp-field\";\n\nconst OTP_LENGTH = 6;\n\nconst OTP_SLOT_KEYS = Array.from(\n { length: OTP_LENGTH },\n (_, i) => `otp-slot-${i}`,\n);\n\nexport default function Particle() {\n const [value, setValue] = useState(\"\");\n const [invalid, setInvalid] = useState(false);\n const valid = value.length === OTP_LENGTH && value === \"123456\";\n\n return (\n \n Verification code\n {\n setValue(nextValue);\n setInvalid(\n nextValue.length === OTP_LENGTH ? nextValue !== \"123456\" : false,\n );\n }}\n value={value}\n >\n {OTP_SLOT_KEYS.map((slotKey, index) => (\n \n ))}\n \n {!valid && !invalid && (\n Enter `123456` to pass validation.\n )}\n {invalid && Code must be 123456.}\n {valid && Code verified.}\n \n );\n}\n", "type": "registry:block" } ], diff --git a/apps/ui/public/r/p-textarea-10.json b/apps/ui/public/r/p-textarea-10.json index 9092f84aa..ab83933bf 100644 --- a/apps/ui/public/r/p-textarea-10.json +++ b/apps/ui/public/r/p-textarea-10.json @@ -8,7 +8,7 @@ "files": [ { "path": "registry/default/particles/p-textarea-10.tsx", - "content": "import { useId } from \"react\";\nimport { Textarea } from \"@/registry/default/ui/textarea\";\n\nexport default function Particle() {\n const id = useId();\n return (\n \n );\n}\n", + "content": "import { useId } from \"react\";\nimport { Textarea } from \"@/registry/default/ui/textarea\";\n\nexport default function Particle() {\n const id = useId();\n return (\n \n );\n}\n", "type": "registry:block" } ], diff --git a/apps/ui/public/r/registry.json b/apps/ui/public/r/registry.json index 336ed7cad..2183a0113 100644 --- a/apps/ui/public/r/registry.json +++ b/apps/ui/public/r/registry.json @@ -7327,7 +7327,8 @@ ], "name": "p-otp-field-1", "registryDependencies": [ - "@coss/otp-field" + "@coss/otp-field", + "@coss/field" ], "type": "registry:block" }, @@ -7345,7 +7346,8 @@ ], "name": "p-otp-field-2", "registryDependencies": [ - "@coss/otp-field" + "@coss/otp-field", + "@coss/field" ], "type": "registry:block" }, @@ -7363,7 +7365,8 @@ ], "name": "p-otp-field-3", "registryDependencies": [ - "@coss/otp-field" + "@coss/otp-field", + "@coss/field" ], "type": "registry:block" }, diff --git a/apps/ui/registry.json b/apps/ui/registry.json index 336ed7cad..2183a0113 100644 --- a/apps/ui/registry.json +++ b/apps/ui/registry.json @@ -7327,7 +7327,8 @@ ], "name": "p-otp-field-1", "registryDependencies": [ - "@coss/otp-field" + "@coss/otp-field", + "@coss/field" ], "type": "registry:block" }, @@ -7345,7 +7346,8 @@ ], "name": "p-otp-field-2", "registryDependencies": [ - "@coss/otp-field" + "@coss/otp-field", + "@coss/field" ], "type": "registry:block" }, @@ -7363,7 +7365,8 @@ ], "name": "p-otp-field-3", "registryDependencies": [ - "@coss/otp-field" + "@coss/otp-field", + "@coss/field" ], "type": "registry:block" }, diff --git a/apps/ui/registry/__index__.tsx b/apps/ui/registry/__index__.tsx index ce4a33104..c5cded686 100644 --- a/apps/ui/registry/__index__.tsx +++ b/apps/ui/registry/__index__.tsx @@ -6301,7 +6301,7 @@ export const Index: Record = { name: "p-otp-field-1", description: "Basic OTP field", type: "registry:block", - registryDependencies: ["@coss/otp-field"], + registryDependencies: ["@coss/otp-field","@coss/field"], files: [{ path: "registry/default/particles/p-otp-field-1.tsx", type: "registry:block", @@ -6319,7 +6319,7 @@ export const Index: Record = { name: "p-otp-field-2", description: "Large OTP field", type: "registry:block", - registryDependencies: ["@coss/otp-field"], + registryDependencies: ["@coss/otp-field","@coss/field"], files: [{ path: "registry/default/particles/p-otp-field-2.tsx", type: "registry:block", @@ -6337,7 +6337,7 @@ export const Index: Record = { name: "p-otp-field-3", description: "OTP field with separator", type: "registry:block", - registryDependencies: ["@coss/otp-field"], + registryDependencies: ["@coss/otp-field","@coss/field"], files: [{ path: "registry/default/particles/p-otp-field-3.tsx", type: "registry:block", diff --git a/apps/ui/registry/default/particles/p-dialog-4.tsx b/apps/ui/registry/default/particles/p-dialog-4.tsx index 059ccaa4a..7c30e5b2c 100644 --- a/apps/ui/registry/default/particles/p-dialog-4.tsx +++ b/apps/ui/registry/default/particles/p-dialog-4.tsx @@ -61,6 +61,7 @@ export default function Particle() { setValue(e.target.value)} value={value} /> diff --git a/apps/ui/registry/default/particles/p-field-10.tsx b/apps/ui/registry/default/particles/p-field-10.tsx index 5fe4949ff..6c7eec9a9 100644 --- a/apps/ui/registry/default/particles/p-field-10.tsx +++ b/apps/ui/registry/default/particles/p-field-10.tsx @@ -11,7 +11,7 @@ export default function Particle() { return ( Bio - + Write a short bio. Maximum 500 characters. diff --git a/apps/ui/registry/default/particles/p-input-group-22.tsx b/apps/ui/registry/default/particles/p-input-group-22.tsx index 4a533eada..95760893c 100644 --- a/apps/ui/registry/default/particles/p-input-group-22.tsx +++ b/apps/ui/registry/default/particles/p-input-group-22.tsx @@ -1,7 +1,7 @@ "use client"; import { XIcon } from "lucide-react"; -import { useState } from "react"; +import { useRef, useState } from "react"; import { Button } from "@/registry/default/ui/button"; import { InputGroup, @@ -10,6 +10,7 @@ import { } from "@/registry/default/ui/input-group"; export default function Particle() { + const inputRef = useRef(null); const [value, setValue] = useState("Clear me"); return ( @@ -18,6 +19,7 @@ export default function Particle() { aria-label="Text input with clear button" onChange={(e) => setValue(e.target.value)} placeholder="Enter text" + ref={inputRef} type="text" value={value} /> @@ -25,7 +27,10 @@ export default function Particle() { setValue("")} + onClick={() => { + setValue(""); + inputRef.current?.focus(); + }} size="icon-xs" variant="ghost" > diff --git a/apps/ui/registry/default/particles/p-input-group-29.tsx b/apps/ui/registry/default/particles/p-input-group-29.tsx index 881157ee0..aeab3ed2a 100644 --- a/apps/ui/registry/default/particles/p-input-group-29.tsx +++ b/apps/ui/registry/default/particles/p-input-group-29.tsx @@ -34,7 +34,7 @@ export default function Particle() { Record voice message - + Press Enter to send diff --git a/apps/ui/registry/default/particles/p-otp-field-1.tsx b/apps/ui/registry/default/particles/p-otp-field-1.tsx index 7b8ffb6c2..3b1572563 100644 --- a/apps/ui/registry/default/particles/p-otp-field-1.tsx +++ b/apps/ui/registry/default/particles/p-otp-field-1.tsx @@ -1,3 +1,4 @@ +import { Field, FieldLabel } from "@/registry/default/ui/field"; import { OTPField, OTPFieldInput } from "@/registry/default/ui/otp-field"; const OTP_LENGTH = 6; @@ -9,15 +10,20 @@ const OTP_SLOT_KEYS = Array.from( export default function Particle() { return ( - - {OTP_SLOT_KEYS.map((slotKey, index) => ( - - ))} - + + One-time password + + {OTP_SLOT_KEYS.map((slotKey, index) => ( + + ))} + + ); } diff --git a/apps/ui/registry/default/particles/p-otp-field-2.tsx b/apps/ui/registry/default/particles/p-otp-field-2.tsx index 661e45436..d8f297e1d 100644 --- a/apps/ui/registry/default/particles/p-otp-field-2.tsx +++ b/apps/ui/registry/default/particles/p-otp-field-2.tsx @@ -1,3 +1,4 @@ +import { Field, FieldLabel } from "@/registry/default/ui/field"; import { OTPField, OTPFieldInput } from "@/registry/default/ui/otp-field"; const OTP_LENGTH = 4; @@ -9,15 +10,20 @@ const OTP_SLOT_KEYS = Array.from( export default function Particle() { return ( - - {OTP_SLOT_KEYS.map((slotKey, index) => ( - - ))} - + + One-time password + + {OTP_SLOT_KEYS.map((slotKey, index) => ( + + ))} + + ); } diff --git a/apps/ui/registry/default/particles/p-otp-field-3.tsx b/apps/ui/registry/default/particles/p-otp-field-3.tsx index 85511ea8e..d14869dc8 100644 --- a/apps/ui/registry/default/particles/p-otp-field-3.tsx +++ b/apps/ui/registry/default/particles/p-otp-field-3.tsx @@ -1,3 +1,4 @@ +import { Field, FieldLabel } from "@/registry/default/ui/field"; import { OTPField, OTPFieldInput, @@ -14,22 +15,27 @@ const OTP_SLOT_KEYS = Array.from( export default function Particle() { return ( - - {OTP_SLOT_KEYS.slice(0, GROUP_LENGTH).map((slotKey, index) => ( - - ))} - - {OTP_SLOT_KEYS.slice(GROUP_LENGTH).map((slotKey, index) => ( - - ))} - + + Verification code + + {OTP_SLOT_KEYS.slice(0, GROUP_LENGTH).map((slotKey, index) => ( + + ))} + + {OTP_SLOT_KEYS.slice(GROUP_LENGTH).map((slotKey, index) => ( + + ))} + + ); } diff --git a/apps/ui/registry/default/particles/p-otp-field-7.tsx b/apps/ui/registry/default/particles/p-otp-field-7.tsx index aee736b40..4f780ebb3 100644 --- a/apps/ui/registry/default/particles/p-otp-field-7.tsx +++ b/apps/ui/registry/default/particles/p-otp-field-7.tsx @@ -45,7 +45,7 @@ export default function Particle() { {!valid && !invalid && ( Enter `123456` to pass validation. )} - {invalid && Code must be 123456.} + {invalid && Code must be 123456.} {valid && Code verified.} ); diff --git a/apps/ui/registry/default/particles/p-textarea-10.tsx b/apps/ui/registry/default/particles/p-textarea-10.tsx index 94fd3e198..3a1c41de7 100644 --- a/apps/ui/registry/default/particles/p-textarea-10.tsx +++ b/apps/ui/registry/default/particles/p-textarea-10.tsx @@ -5,6 +5,7 @@ export default function Particle() { const id = useId(); return ( - - - - - - - - + + Verification code + + + + + + + + + + ``` ## Patterns from coss particles @@ -50,8 +54,8 @@ OTP with label and controlled value: ```tsx const [value, setValue] = useState("") - - Verification code + + Verification code - + ``` Digit-only SMS-style codes use Base UI’s default `validationType` (`numeric`) and matching `inputMode`; set those props explicitly only when you need different behavior. @@ -79,7 +83,7 @@ See `p-otp-field-1` through `p-otp-field-4` and `p-otp-field-6` through `p-otp-f ## Common pitfalls - Slot count mismatch with `length`, causing broken OTP UX. -- Missing root labeling (`aria-label` or visible label), or adding per-slot labels to the first input. +- A root `aria-label` does not name the first input. Use `Field` with a visible or visually hidden `FieldLabel`; the first input inherits it. Additional slots can use per-slot labels. - Using OTP slots for arbitrary text input instead of fixed verification codes. ## Useful particle references