# Primitives

> This feature is deprecated. With the release of [Clerk Core 3](https://clerk.com/changelog/2026-03-03-core-3.md), the redesigned [hooks](https://clerk.com/docs/reference/hooks/overview.md) are the recommended replacement for building custom flows. They expose stateful objects, step methods that map directly to the flow, and structured field-level errors out of the box, so you no longer need to manage attempt status, loading states, or error parsing yourself.

## OTP Input

The following example demonstrates how to use the `otp` input type with the render prop to create a custom one-time password (OTP) input field for phone and email codes, that is animated with Framer Motion.

```tsx
<Clerk.Input
  type="otp"
  required
  className="flex justify-center gap-1"
  render={({ value, status }) => (
    <div
      data-status={status}
      className="relative h-9 w-8 rounded-md bg-white ring-1 ring-inset ring-zinc-300 data-[status=selected]:bg-sky-400/10 data-[status=selected]:shadow-[0_0_8px_2px_theme(colors.sky.400/30%)] data-[status=selected]:ring-sky-400"
    >
      <AnimatePresence>
        {value && (
          <motion.span
            initial={{ opacity: 0, scale: 0.75 }}
            animate={{ opacity: 1, scale: 1 }}
            exit={{ opacity: 0, scale: 0.75 }}
            className="absolute inset-0 flex items-center justify-center text-zinc-950"
          >
            {value}
          </motion.span>
        )}
        {value}
      </AnimatePresence>
      {status === 'cursor' && (
        <motion.div
          layoutId="otp-input-focus"
          transition={{ ease: [0.2, 0.4, 0, 1], duration: 0.2 }}
          className="absolute inset-0 z-10 rounded-[inherit] border border-sky-400 bg-sky-400/10 shadow-[0_0_8px_2px_theme(colors.sky.400/30%)]"
        />
      )}
    </div>
  )}
/>
```

---

## Sitemap

[Overview of all docs pages](https://clerk.com/docs/llms.txt)
