Code puncher Overview

The code puncher component is a composable PIN/OTP input component designed for entering verification codes, PINs, and other short alphanumeric sequences. It provides a user-friendly interface with individual input slots, automatic navigation, paste support, and comprehensive keyboard controls. The component is ideal for two-factor authentication, PIN entry, license key input, and similar use cases where users need to enter structured codes.

When to Use

Use code puncher when:

  • Collecting verification codes (OTP, SMS codes)
  • Entering PIN numbers
  • Inputting license keys or activation codes
  • Building two-factor authentication flows
  • Creating structured alphanumeric input fields

Don't use code puncher for:

  • Free-form text input (use input component)
  • Multi-line text entry (use textarea)
  • Numeric input with stepper controls (use number input)
  • Single character input (use regular input)
  • Long-form content (use textarea or rich text editor)
Examples Default code puncher

A basic 6-digit code puncher for OTP verification:

<dap-ds-code-puncher
  label="Enter verification code"
  description="We sent a 6-digit code to your email">
  <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
  <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
  <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
  <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
  <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
  <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
</dap-ds-code-puncher>
Validation feedback

Provide contextual feedback to users with validation messages:

<dap-ds-stack direction="column">
  <dap-ds-code-puncher
    label="Verification code"
    required
    feedback="Please enter all 6 digits"
    feedbackType="negative"
    status="error">
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
  </dap-ds-code-puncher>

  <dap-ds-code-puncher
    label="Verification code"
    feedback="Code verified successfully!"
    feedbackType="positive"
    status="success">
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
  </dap-ds-code-puncher>
</dap-ds-stack>
Sizes

Choose code puncher sizes based on context and visual hierarchy:

<dap-ds-stack direction="column">
  <dap-ds-code-puncher
    label="Extra small / Xs"
    description="Compact size for tight spaces"
    size="xs">
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
  </dap-ds-code-puncher>

  <dap-ds-code-puncher
    label="Small / Sm"
    description="Standard size for most forms"
    size="sm">
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
  </dap-ds-code-puncher>

  <dap-ds-code-puncher
    label="Large / Lg"
    description="Prominent size for important inputs"
    size="lg">
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
  </dap-ds-code-puncher>
</dap-ds-stack>
Code puncher states

Code puncher components support various states to communicate different conditions:

<dap-ds-stack direction="column">
  <dap-ds-code-puncher
    label="Success"
    status="success"
    feedback="Code verified successfully!"
    feedbackType="positive">
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
  </dap-ds-code-puncher>

  <dap-ds-code-puncher
    label="Error"
    status="error"
    required
    feedback="Invalid code. Please try again."
    feedbackType="negative">
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
  </dap-ds-code-puncher>

  <dap-ds-code-puncher
    label="Disabled"
    disabled>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
  </dap-ds-code-puncher>

  <dap-ds-code-puncher
    label="Readonly"
    readonly>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
  </dap-ds-code-puncher>
</dap-ds-stack>
Input patterns and masking

The code puncher supports different input patterns and masking for various use cases:

<dap-ds-stack direction="column">
  <dap-ds-code-puncher
    label="4-digit PIN (masked)"
    description="PIN is masked for security"
    mask>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
  </dap-ds-code-puncher>

  <dap-ds-code-puncher
    label="License key (alphanumeric)"
    description="Accepts letters and numbers"
    pattern="[a-zA-Z0-9]">
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
  </dap-ds-code-puncher>

  <dap-ds-code-puncher
    label="With placeholder"
    description="Shows placeholder when empty"
    placeholder="🔒">
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
  </dap-ds-code-puncher>
</dap-ds-stack>
Accessibility features

Code puncher components include comprehensive accessibility support for screen readers and keyboard navigation:

<dap-ds-stack direction="column">
  <div>
    <dap-ds-typography variant="h4">Required fields</dap-ds-typography>
    <dap-ds-typography variant="body" style={{marginBottom: 'var(--dds-spacing-300)', color: 'var(--dds-text-neutral-subtle)'}}>
      Properly announced to screen readers with aria-required
    </dap-ds-typography>
    <dap-ds-code-puncher
      label="Verification Code"
      description="This field is required for verification"
      required>
      <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
      <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
      <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
      <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
      <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
      <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    </dap-ds-code-puncher>
  </div>

  <div>
    <dap-ds-typography variant="h4">Error states</dap-ds-typography>
    <dap-ds-typography variant="body" style={{marginBottom: 'var(--dds-spacing-300)', color: 'var(--dds-text-neutral-subtle)'}}>
      Error messages are announced and associated with the input
    </dap-ds-typography>
    <dap-ds-code-puncher
      label="Verification Code"
      status="error"
      feedback="Please enter a valid 6-digit code"
      feedbackType="negative"
      required>
      <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
      <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
      <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
      <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
      <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
      <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    </dap-ds-code-puncher>
  </div>

  <div>
    <dap-ds-typography variant="h4">Keyboard navigation</dap-ds-typography>
    <dap-ds-typography variant="body" style={{marginBottom: 'var(--dds-spacing-300)', color: 'var(--dds-text-neutral-subtle)'}}>
      Arrow keys, Home, End, Backspace, and Delete are fully supported
    </dap-ds-typography>
    <dap-ds-code-puncher
      label="Verification Code"
      description="Use arrow keys to navigate, Backspace to clear">
      <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
      <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
      <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
      <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
      <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
      <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    </dap-ds-code-puncher>
  </div>
</dap-ds-stack>
Real-World Patterns Two-Factor Authentication Flow
<div style={{border: 'var(--dds-border-width-base) solid var(--dds-border-neutral-subtle)', padding: 'var(--dds-spacing-600)', borderRadius: 'var(--dds-radius-base)'}}>
<dap-ds-stack>
  <dap-ds-typography variant="h4">Verify Your Identity</dap-ds-typography>
  <dap-ds-typography variant="body" style={{marginBottom: 'var(--dds-spacing-400)', color: 'var(--dds-text-neutral-subtle)'}}>
    We've sent a 6-digit verification code to your email address. Please enter it below.
  </dap-ds-typography>
  <dap-ds-code-puncher
    label="Verification Code"
    description="Enter the 6-digit code from your email"
    required
    autocomplete="one-time-code">
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-icon name="separator"></dap-ds-icon>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
  </dap-ds-code-puncher>
  <dap-ds-button style={{marginTop: 'var(--dds-spacing-400)'}}>Verify</dap-ds-button>
</dap-ds-stack>
</div>
PIN Entry
<div style={{border: 'var(--dds-border-width-base) solid var(--dds-border-neutral-subtle)', padding: 'var(--dds-spacing-600)', borderRadius: 'var(--dds-radius-base)'}}>
<dap-ds-stack>
  <dap-ds-typography variant="h4">Enter Your PIN</dap-ds-typography>
  <dap-ds-code-puncher
    label="PIN"
    description="Enter your 4-digit PIN"
    mask
    required>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
    <dap-ds-code-puncher-slot></dap-ds-code-puncher-slot>
  </dap-ds-code-puncher>
  <dap-ds-button style={{marginTop: 'var(--dds-spacing-400)'}}>Continue</dap-ds-button>
</dap-ds-stack>
</div>
Custom Styling Quick customization with CSS custom properties

Many visual tweaks can be achieved by overriding the built-in CSS variables directly on the component instance:

<dap-ds-code-puncher
  label="Custom styled code puncher"
  description="Overrides a few CSS variables">
  <dap-ds-code-puncher-slot     style={{
    '--dds-input-border': '2px solid var(--dds-brand-300)',
    '--dds-input-border-radius': 'var(--dds-radius-rounded)',
  }}></dap-ds-code-puncher-slot>
  <dap-ds-code-puncher-slot style={{
    '--dds-input-border': '2px solid var(--dds-brand-400)',
    '--dds-input-border-radius': 'var(--dds-radius-rounded)',
  }}></dap-ds-code-puncher-slot>
  <dap-ds-code-puncher-slot style={{
    '--dds-input-border': '2px solid var(--dds-brand-500)',
    '--dds-input-border-radius': 'var(--dds-radius-rounded)',
  }}></dap-ds-code-puncher-slot>
  <dap-ds-code-puncher-slot style={{
    '--dds-input-border': '2px solid var(--dds-brand-600)',
    '--dds-input-border-radius': 'var(--dds-radius-rounded)',
  }}></dap-ds-code-puncher-slot>
</dap-ds-code-puncher>
Advanced styling with CSS parts

The code puncher component exposes several CSS parts (base, slots, label, description, feedback) that can be targeted for deep customization:

Select a presetCompact SpacingBordered ContainerNeon Glow
Copy CSSFormat CSSResetLightDark
CSS Editor
Live Preview
Paste Support

The component automatically handles paste events, cleaning common separators and distributing characters User can paste "123-456" or "123 456" and it will be automaticallycleaned and distributed across slots Supports common separators: -, ·, and whitespace

Pattern Validation

Custom patterns can be specified using regex:

<!-- Numeric only (default) -->
<dap-ds-code-puncher pattern="[0-9]">
  <!-- ... -->
</dap-ds-code-puncher>

<!-- Alphanumeric uppercase -->
<dap-ds-code-puncher pattern="[A-Z0-9]">
  <!-- ... -->
</dap-ds-code-puncher>

<!-- Letters only -->
<dap-ds-code-puncher pattern="[A-Za-z]">
  <!-- ... -->
</dap-ds-code-puncher>
Importing
import { DapDSCodePuncher } from 'dap-design-system'
Importing React
import { DapDSCodePuncherReact } from 'dap-design-system/react'
Tree-Shakeable Imports

For optimal bundle sizes, use the tree-shakeable import syntax:

import { DapDSCodePuncher } from 'dap-design-system/components'
Attributes
PropertyTypeDefaultDescription
maskbooleanfalseMask input like password. Default is false.
patternstring'[0-9]'Regex pattern for allowed characters. Default is '[0-9]'.
placeholderstring''Placeholder character for empty slots.
autocompletestring'one-time-code'Autocomplete hint. Default is 'one-time-code'.
valuestringThe complete code value.
size'xs', 'sm' , 'lg'The size of the slots. Default is 'sm'.
labelstringThe label of the component.
descriptionstringThe description of the component.
tooltipstringThe tooltip of the component.
feedbackstringThe feedback message.
feedbackType'negative', 'positive' , 'warning'The feedback type.
status'success', 'error'The status of the component.
disabledbooleanDisable all slots. Default is false.
readonlybooleanRead-only state. Default is false.
requiredbooleanRequired for form validation. Default is false.
namestringForm element name.
Slots
NameDescription
defaultSlot for code-puncher-group, code-puncher-slot, and code-puncher-separator elements.
Events
Event NameDescriptionType
dds-inputFires on each digit input.{value: string, index: number }
dds-changeFires when value changes.{value: string }
dds-completeFires when all slots are filled.{value: string }
dds-focusFires when component gains focus.void
dds-blurFires when component loses focus.void
CSS Parts
Part NameDescription
baseThe main container.
slotsThe slots container.
labelThe label element.
descriptionThe description element.
feedbackThe feedback element.
How to Use CSS Parts

You can style CSS parts using the ::part() pseudo-element selector:

/* Target a specific part */
.my-custom-dap-ds-code-puncher::part(base) {
  /* Your custom styles */
}

/* Target multiple parts */
.my-custom-dap-ds-code-puncher::part(base),
.my-custom-dap-ds-code-puncher::part(slots) {
  /* Shared styles */
}

Example usage:

<dap-ds-code-puncher class="my-custom-dap-ds-code-puncher">
  Code puncher
</dap-ds-code-puncher>
.my-custom-dap-ds-code-puncher::part(base) {
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

CSS parts allow you to style internal elements of the component while maintaining encapsulation. Learn more in our styling guide.

CSS Custom Properties

No CSS custom properties available.

Components Code Puncher <dap-ds-code-puncher/> Attributes
PropertyTypeDefaultDescription
maskbooleanfalseMask input like password. Default is false.
patternstring'[0-9]'Regex pattern for allowed characters. Default is '[0-9]'.
placeholderstring''Placeholder character for empty slots.
autocompletestring'one-time-code'Autocomplete hint. Default is 'one-time-code'.
valuestringThe complete code value.
size'xs', 'sm' , 'lg'The size of the slots. Default is 'sm'.
labelstringThe label of the component.
descriptionstringThe description of the component.
tooltipstringThe tooltip of the component.
feedbackstringThe feedback message.
feedbackType'negative', 'positive' , 'warning'The feedback type.
status'success', 'error'The status of the component.
disabledbooleanDisable all slots. Default is false.
readonlybooleanRead-only state. Default is false.
requiredbooleanRequired for form validation. Default is false.
namestringForm element name.
Slots
NameDescription
defaultSlot for code-puncher-group, code-puncher-slot, and code-puncher-separator elements.
Events
Event NameDescriptionType
dds-inputFires on each digit input.{value: string, index: number }
dds-changeFires when value changes.{value: string }
dds-completeFires when all slots are filled.{value: string }
dds-focusFires when component gains focus.void
dds-blurFires when component loses focus.void
CSS Parts
Part NameDescription
baseThe main container.
slotsThe slots container.
labelThe label element.
descriptionThe description element.
feedbackThe feedback element.
CSS Custom Properties

No CSS custom properties available.