Detent web components
By Shane Logsdon

Forms & inputs

LockInput

Implemented

Focus state that "locks" into place

detent-lock-input

Port status
Catalog status
implemented
Origin
upstream
Phase
3
Wave
phase-3-forms
Group
Forms & inputs

4.4 KB gzip for the class module

Variants

Recorded states

  • focus-visible recorded state; no setter
  • disabled recorded state; no setter
  • error recorded state; no setter
  • dark theme recorded state; no setter

Usage

Import

import '/components/lock-input/define.js';

// or register it yourself
import { DetentLockInput } from '/components/lock-input/lock-input.js';

Attributes

  • default-value
  • description
  • disabled
  • error
  • label
  • name
  • placeholder
  • required
  • type
  • value

Properties

  • value
  • defaultValue
  • label
  • description
  • error
  • placeholder
  • type
  • disabled
  • required
  • name

Slots

  • left-icon
  • right-icon

Events

  • detent-change — { value: string }

Example

Runnable example: site/examples/lock-input.ts. The snippet below is generated from the catalogued attributes.

<detent-lock-input
  default-value
  description
  disabled
  error
  label
  name
  placeholder
  required
  type
  value
></detent-lock-input>

Source

The pinned upstream source for this row:

  • src/components/ui/LockInput.tsx sha256 e22f9b189e22…

Native files

The native module and its artifacts:

  • src/components/lock-input/lock-input.ts
  • src/components/lock-input/styles.css
  • src/components/lock-input/define.ts
  • docs/components/lock-input.md
  • site/examples/lock-input.ts
  • tests/browser/lock-input.spec.ts
  • evidence/components/lock-input.md

API

Boolean attributes follow HTML presence semantics: present means true, absent means false, and disabled="false" still means disabled.

Attributes

Attributes
AttributePropertyTypeDefaultNotes
default-value———Recorded in the catalog as an attribute.
descriptiondescriptionstringundefinedKebab-case attribute; camelCase property.
disableddisabledbooleanfalsePresence semantics: present means true, absent means false.
errorerrorstringundefinedKebab-case attribute; camelCase property.
labellabelstringundefinedKebab-case attribute; camelCase property.
name———Recorded in the catalog as an attribute.
placeholder———Recorded in the catalog as an attribute.
required———Recorded in the catalog as an attribute.
type———Recorded in the catalog as an attribute.
value———Recorded in the catalog as an attribute.

Properties

Properties
PropertyTypeDefaultNotes
value——Recorded in the catalog without a top-level type; pinned from source when the row is ported.
defaultValue——Recorded in the catalog without a top-level type; pinned from source when the row is ported.
labelstringundefinedProperty-only: assign from script; not accepted as an attribute.
descriptionstringundefinedProperty-only: assign from script; not accepted as an attribute.
errorstringundefinedProperty-only: assign from script; not accepted as an attribute.
placeholder——Recorded in the catalog without a top-level type; pinned from source when the row is ported.
type——Recorded in the catalog without a top-level type; pinned from source when the row is ported.
disabledbooleanfalseProperty-only: assign from script; not accepted as an attribute.
required——Recorded in the catalog without a top-level type; pinned from source when the row is ported.
name——Recorded in the catalog without a top-level type; pinned from source when the row is ported.

Events

Events
EventUpstream propPayload typeNotes
detent-changeonChange(value: string) => voidComposed, bubbles; fires only for a user action.

Slots

Slots
SlotNotes
left-iconConsumer content; rendered through a slot, never re-created.
right-iconConsumer content; rendered through a slot, never re-created.

CSS customisation

  • React `children`/`ReactNode` props become DOM slots; caller content stays light DOM.
  • Framer Motion springs/AnimatePresence ported to CSS transitions, WAAPI or the shared rAF spring helper.
  • React state/hooks replaced by element-owned state with pre-upgrade property preservation.
  • The attribute label and string description/error render as text; icon nodes become slots.
  • Native additions: name, value, default-value, type, placeholder, required, setFormValue/setValidity, checkValidity/reportValidity, reset/restore, fieldset detection.
  • `detent-change` is a native addition: the row records no event, but the pinned source forwards onChange from InputHTMLAttributes.
  • The description hides while an error is shown (upstream `description && !error`) and aria-describedby follows the visible node.
  • Disabled mutates only the frame (upstream opacity-30 faded the label).
  • The lock ring is CSS instead of springSnappy (PC-10.4), removed under reduced motion with the final state kept.
  • Danger colours are color-mix values, not rose-500/50 on a dark-only surface.

What it does

A password field with a lock affordance and a reveal toggle, plus inline validation messaging.

Upstream behaviour
  • Focus ring scales in from 0.94 to 1.0 with a snappy spring, producing a physical "lock" feel
  • Inset border ring fades in alongside the outer focus halo for a layered lock effect
  • Icon and label slots adjust contrast on focus to draw the eye inward
  • Error state replaces accent with restrained rose and animates message in
  • Light/dark theme aware via CSS variables — same code, both themes
Differences from upstream
  • React `children`/`ReactNode` props become DOM slots; caller content stays light DOM.
  • Framer Motion springs/AnimatePresence ported to CSS transitions, WAAPI or the shared rAF spring helper.
  • React state/hooks replaced by element-owned state with pre-upgrade property preservation.
  • The attribute label and string description/error render as text; icon nodes become slots.
  • Native additions: name, value, default-value, type, placeholder, required, setFormValue/setValidity, checkValidity/reportValidity, reset/restore, fieldset detection.
  • `detent-change` is a native addition: the row records no event, but the pinned source forwards onChange from InputHTMLAttributes.
  • The description hides while an error is shown (upstream `description && !error`) and aria-describedby follows the visible node.
  • Disabled mutates only the frame (upstream opacity-30 faded the label).
  • The lock ring is CSS instead of springSnappy (PC-10.4), removed under reduced motion with the final state kept.
  • Danger colours are color-mix values, not rose-500/50 on a dark-only surface.
Previous: Loader Next: Login

Docs

Components

Project