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:
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:
Importing
Importing React
Tree-Shakeable Imports
For optimal bundle sizes, use the tree-shakeable import syntax:
Attributes
| Property | Type | Default | Description |
|---|
mask | boolean | false | Mask input like password. Default is false. |
pattern | string | '[0-9]' | Regex pattern for allowed characters. Default is '[0-9]'. |
placeholder | string | '' | Placeholder character for empty slots. |
autocomplete | string | 'one-time-code' | Autocomplete hint. Default is 'one-time-code'. |
value | string | | The complete code value. |
size | 'xs', 'sm' , 'lg' | | The size of the slots. Default is 'sm'. |
label | string | | The label of the component. |
description | string | | The description of the component. |
tooltip | string | | The tooltip of the component. |
feedback | string | | The feedback message. |
feedbackType | 'negative', 'positive' , 'warning' | | The feedback type. |
status | 'success', 'error' | | The status of the component. |
disabled | boolean | | Disable all slots. Default is false. |
readonly | boolean | | Read-only state. Default is false. |
required | boolean | | Required for form validation. Default is false. |
name | string | | Form element name. |
Slots
| Name | Description |
|---|
default | Slot for code-puncher-group, code-puncher-slot, and code-puncher-separator elements. |
Events
| Event Name | Description | Type |
|---|
dds-input | Fires on each digit input. | {value: string, index: number } |
dds-change | Fires when value changes. | {value: string } |
dds-complete | Fires when all slots are filled. | {value: string } |
dds-focus | Fires when component gains focus. | void |
dds-blur | Fires when component loses focus. | void |
CSS Parts
| Part Name | Description |
|---|
base | The main container. |
slots | The slots container. |
label | The label element. |
description | The description element. |
feedback | The feedback element. |
How to Use CSS Parts
You can style CSS parts using the ::part() pseudo-element selector:
Example usage:
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
| Property | Type | Default | Description |
|---|
mask | boolean | false | Mask input like password. Default is false. |
pattern | string | '[0-9]' | Regex pattern for allowed characters. Default is '[0-9]'. |
placeholder | string | '' | Placeholder character for empty slots. |
autocomplete | string | 'one-time-code' | Autocomplete hint. Default is 'one-time-code'. |
value | string | | The complete code value. |
size | 'xs', 'sm' , 'lg' | | The size of the slots. Default is 'sm'. |
label | string | | The label of the component. |
description | string | | The description of the component. |
tooltip | string | | The tooltip of the component. |
feedback | string | | The feedback message. |
feedbackType | 'negative', 'positive' , 'warning' | | The feedback type. |
status | 'success', 'error' | | The status of the component. |
disabled | boolean | | Disable all slots. Default is false. |
readonly | boolean | | Read-only state. Default is false. |
required | boolean | | Required for form validation. Default is false. |
name | string | | Form element name. |
Slots
| Name | Description |
|---|
default | Slot for code-puncher-group, code-puncher-slot, and code-puncher-separator elements. |
Events
| Event Name | Description | Type |
|---|
dds-input | Fires on each digit input. | {value: string, index: number } |
dds-change | Fires when value changes. | {value: string } |
dds-complete | Fires when all slots are filled. | {value: string } |
dds-focus | Fires when component gains focus. | void |
dds-blur | Fires when component loses focus. | void |
CSS Parts
| Part Name | Description |
|---|
base | The main container. |
slots | The slots container. |
label | The label element. |
description | The description element. |
feedback | The feedback element. |
CSS Custom Properties
No CSS custom properties available.