Usage
Input Group composes exactly one Input or Textarea with reusable Nord content. The nested control remains the only editable, form-associated element and retains its Shadow DOM, value, events, methods, validation, and reset behavior. The Light DOM group and add-ons provide only the shared presentation.
Import both modules to register the group and add-on elements:
import "@nordhealth/components/lib/InputGroup"
import "@nordhealth/components/lib/InputGroupAddon"
Composition
Input Group Addon positions contextual content around the shared control surface.
Give a standalone group a label, or place it inside a Field. Add-ons can contain text, icons, buttons, keyboard hints, spinners, or a dropdown without replacing those components’ semantics.
Supported controls: compose exactly one direct Nord Input or Textarea. Native inputs and arbitrary custom or third-party controls are unsupported because they cannot consume the Field, validation, focus, and presentation contexts; those compositions use the diagnostic fallback.
The Input Group is presentational, while the nested Input, Textarea, or surrounding Field owns the form semantics. Use the group label API for a standalone compound field, or let Field own label, hint, error, required, and invalid presentation when the group is composed inside one.
Examples
Label ownership
Choose one source for field copy: use Input Group’s label and hint API when it stands alone, or Field when the composition needs shared form layout and description.
Hint placement
Use hint-below when a standalone group’s hint should follow the control instead of appearing beside its label. Field compositions continue to follow Field’s own description layout.
Add-on alignments
The position property uses logical directions and does not depend on source order. The default is inline-start. Keep interactive children in the DOM order users should encounter with a keyboard or screen reader.
The group shell owns the one shared background and outline. Add-ons and the nested Input or Textarea stay transparent and borderless inside it, with no internal divider seams.
At medium size, inline add-ons keep their token-based outer inset and remove only the padding beside the control. The grouped control supplies one small --n-space-xs seam gap. A standalone decorative Icon receives a subtle token-derived optical adjustment automatically. An exact direct Button or Dropdown matching the group size supplies its own control padding; intentionally smaller nested controls keep the normal add-on inset. Private token roles scale that geometry, add-on typography, child gap, padding, and target height with group size; block add-ons align to the native text inset.
inline-start
Use inline-start for prefixes or leading context.
inline-end
Use inline-end for suffixes, units, or trailing context.
block-start
Block-start add-ons span the shared surface above the editable control.
block-end
Block-end add-ons span the shared surface below the control and grow with multiline content.
Icon
Use a decorative icon to reinforce the expected content or status. Icon-only actions still need their own accessible name.
Text
Short text add-ons work well for currency, units, URL fragments, or account suffixes. Put longer guidance in a hint or Field Description instead.
Button
Buttons and links remain independent actions. Clicking them does not focus or activate the text control. Pair an unfamiliar icon-only action with an accessible label and Tooltip.
Kbd
Keyboard hints retain their kbd semantics and can sit beside other add-on content.
Dropdown
A Dropdown trigger keeps its own focus, menu interaction, and disabled state. The group does not synthesize clicks or disable add-on actions implicitly.
Spinner
Use a labeled Spinner for meaningful asynchronous state such as saving or loading. Readonly can prevent editing while the operation completes without removing the current value from form submission.
Textarea
Textarea retains its multiline and auto-growth behavior. Block add-ons remain above or below the control while the shared border grows with its content.
Size
Set size to s, m (default), or l. Input Group owns the effective presentation of its direct Input or Textarea and add-ons so their font size, line height, spacing, and height stay aligned. An explicit child size remains unchanged but group size takes presentation precedence while composed; the child’s own size resumes if it moves outside the group. The default token geometry follows the corresponding Nord text-control sizes, and --n-input-group-target-size can raise the shared minimum where a larger product-specific touch target is required.
Custom Input
Custom Input styling uses Nord Input properties and Input Group’s public CSS custom properties. Third-party text controls are intentionally unsupported: accepting only Nord Input or Textarea preserves form association, password-manager handling, native events, validation, and the one-surface presentation contract.
Available presentation variables are --n-input-group-inline-size, --n-input-group-background, --n-input-group-background-inactive, --n-input-group-border-color, --n-input-group-border-radius, and --n-input-group-target-size. Target size defaults to the effective s, m, or l Nord control geometry and can be increased for larger compound controls.
RTL
Logical inline positions mirror with the surrounding writing direction. DOM and keyboard order stay unchanged.
Validation and Field composition
For standalone use, provide label and optionally hint, error, required, or invalid on the group. Inside nord-field, Field owns the label, helper/error content, and invalid presentation; avoid providing both sets of field copy. Disabled state OR-merges Field, group, and direct-control state. Setting required on either the group or direct control marks the Field Label required, while readonly state comes from either the group or direct control.
Disabled and readonly
Group disabled and readonly state flows to the editable control and combines with the direct control’s own state; Field disabled state also participates in the disabled OR-merge. Disabled values are omitted from FormData; readonly values remain submitted. Add-on actions follow only their own explicit disabled state, so disable them separately when the action should also be unavailable.
Accessibility
- Clicking noninteractive icon, text, or empty add-on space focuses the text control without changing its value.
- Buttons, links, menu triggers, and other interactive descendants retain their own pointer and keyboard behavior.
- The shared boundary reflects hover, keyboard focus-visible, invalid, disabled, and readonly state without adding a second inner border.
- Every group needs an accessible label. A standalone group can use
labelor the label slot; a group inside Field uses Field Label. - Hint and error content is associated with the inner Shadow DOM control, and invalid state is exposed through native and ARIA state.
- Logical properties, Nord semantic tokens, forced-colors handling, reduced motion, compact widths, and multiline growth support themes, RTL, zoom, and high contrast.
API reference
InputGroup
Input Group composes exactly one Nord Input or Textarea with reusable add-ons while leaving the editable control, form state, and all consumer nodes owned by the consumer.
<nord-input-group></nord-input-group>Props
| Property | Attribute | Description | Type | Default |
|---|---|---|---|---|
size | size | Controls the effective size of the grouped Input or Textarea and add-ons. | 's' | 'm' | 'l' | 'm' |
label | label | Plain-text label used when the group is not inside a Nord Field. | string | '' |
hint | hint | Optional standalone hint text. | string | undefined | — |
hintBelow | hint-below | Places the standalone hint below the group surface. | boolean | false |
error | error | Optional standalone error text. Supplying it makes the group invalid. | string | undefined | — |
required | required | Makes the grouped text control required. | boolean | false |
hideLabel | hide-label | Visually hides the standalone label while preserving its accessible name. | boolean | false |
hideRequired | hide-required | Hides the visual required indicator without changing native required state. | boolean | false |
invalid | invalid | Applies invalid state when the group is standalone. | boolean | false |
disabled | disabled | Disables the grouped text control without implicitly disabling add-on actions. | boolean | false |
readonly | readonly | Makes the grouped text control readonly. | boolean | false |
Slots
| Slot name | Description |
|---|---|
Default slot | A single nord-input or nord-textarea plus Input Group Addons. |
label | Optional rich label content for a standalone group. |
hint | Optional rich hint content for a standalone group. |
error | Optional rich validation message for a standalone group. |
CSS Properties
CSS Custom Properties provide more fine grain control over component presentation. We advise utilizing existing properties on the component before using these.
| Property | Description | Default |
|---|---|---|
--n-input-group-inline-size | Controls the group's inline size. | 100% |
--n-input-group-background | Controls the shared control surface. | var(--n-color-surface) |
--n-input-group-background-inactive | Controls the disabled and readonly surface. | var(--n-color-active) |
--n-input-group-border-color | Controls the shared border colour. | var(--n-color-border-strong) |
--n-input-group-border-radius | Controls the shared corner radius. | var(--n-border-radius-s) |
--n-input-group-target-size | Overrides the size-derived compound control minimum block size. | — |
State attributes
These data-* attributes are set by the component to reflect its current state. Use them as styling hooks — they are read-only and should not be set manually.
| Attribute | Description |
|---|---|
data-invalid | Present while the effective Field/group state is invalid. |
data-disabled | Present while the effective Field/group state is disabled. |
data-readonly | Present while the group or control is readonly. |
data-focused | Present while the control or an add-on action has focus. |
data-focus-visible | Present while the text control has keyboard-visible focus. |
data-composition-invalid | Present unless exactly one supported text control is composed. |
Parts
This component is made up of the following parts.
Input Group Addon
Positions reusable Nord content around the text control in an Input Group. Its children retain their native semantics and interaction behavior.
<nord-input-group-addon></nord-input-group-addon>Props
| Property | Attribute | Description | Type | Default |
|---|---|---|---|---|
position | position | Logical position around the grouped text control. | InputGroupAddonPosition | 'inline-start' |
Slots
| Slot name | Description |
|---|---|
Default slot | Text, icons, keyboard hints, spinners, buttons, dropdowns, or other reusable content. |
Dependencies
This component is internally dependent on the following components:
Design guidelinesFor designers
Usage
Input Group presents exactly one Input or Textarea and one or more add-ons as a single field surface. The original control remains the sole editable, form-associated element; the group does not clone, move, or replace consumer content.
Supported controls: the editable child must be exactly one direct nord-input or nord-textarea. Native inputs and arbitrary custom/third-party controls are unsupported because they cannot consume the group’s Field, validation, focus, and presentation contexts; unsupported compositions render the diagnostic fallback.
Do
- Use add-ons for short context such as units, URL prefixes, icons, keyboard hints, loading state, or a closely related action.
- Provide exactly one direct
nord-inputornord-textareachild and give the group a label, or compose it inside a Field. - Use logical
inline-start,inline-end,block-start, andblock-endpositions so the layout adapts to right-to-left languages. - Keep interactive add-ons explicitly enabled or disabled according to their own action state.
Don’t
- Don’t put multiple editable controls in one group; use a Field Group for multiple fields.
- Don’t use an add-on for lengthy help or validation copy; use a hint, Field Description, or Field Error.
- Don’t visually reorder interactive add-ons with custom CSS, because keyboard order follows source order.
- Don’t substitute a third-party input element. Input Group supports Nord Input and Textarea so it can preserve their established form, validation, and accessibility behavior.
Add-on positions
nord-input-group-addon defaults to position="inline-start". Inline positions sit before or after the text control in the current writing direction. Block positions span the group above or below the control. Position is independent of source order, but focus and assistive-technology order still follow the DOM, so place interactive content in the order users should encounter it.
The group shell supplies the one shared background and outline. Add-ons and the nested text control are transparent within that surface and do not draw internal divider borders.
At the default medium size, inline add-ons keep the normal --n-space-s outer inset but remove padding at the control seam; the grouped control contributes one --n-space-xs gap on that side. A direct, standalone Icon gets a small token-derived optical adjustment automatically. An exact direct Button or Dropdown whose own size matches the group supplies its own control padding, so the add-on removes the duplicate wrapper padding; intentionally smaller nested controls retain the normal inset. Private Nord-token roles scale add-on typography, child gap, padding, seam gap, and target height with group size, while block add-ons share the native control's effective text inset.
Clicking noninteractive add-on content focuses the text control. Buttons, links, dropdown triggers, and other interactive descendants keep their own pointer and keyboard behavior; Input Group neither synthesizes a control click nor disables those actions implicitly.
Label ownership
Input Group supports two label owners. Choose one pattern for each group; do not provide field copy in both places.
Standalone Input Group
Use the group’s label when Input Group stands on its own. Put hint, error, required, invalid, disabled, and readonly on the group when they describe the combined control. Input Group renders that field UI once and supplies its accessible name and description to the nested Shadow DOM control.
Hint text appears above the shared surface by default. Add hint-below when the helper copy should follow the control. If an error is also present, the error appears first and the hint follows it, matching Input and Textarea.
<nord-input-group label="Website" hint="Enter the public address." hint-below required>
<nord-input placeholder="example.com"></nord-input>
<nord-input-group-addon position="inline-start">https://</nord-input-group-addon>
</nord-input-group>
Input Group inside Field
Use Field when the surrounding form should own the label, description, error, disabled state, or invalid state. Do not also set label, hint, error, or invalid on Input Group. Field is the sole visible and accessible field owner; the group continues to own the combined surface.
Put required on the direct Input or Textarea so Field Label can reflect it. A control may still own control-specific properties such as name, value, autocomplete, readonly, and native validation constraints.
<nord-field invalid>
<nord-field-label for="website">Website</nord-field-label>
<nord-input-group>
<nord-input id="website" placeholder="example.com" required></nord-input>
<nord-input-group-addon position="inline-start">https://</nord-input-group-addon>
</nord-input-group>
<nord-field-description>Enter the public address.</nord-field-description>
<nord-field-error>This address is unavailable.</nord-field-error>
</nord-field>
The nested Input or Textarea’s built-in label, hint, and error UI is suppressed while Field or standalone Input Group owns that field context. Keep this copy on the selected owner so users receive one label and one description.
Field state
Disabled state is an OR-merge of Field, Input Group, and the direct Input or Textarea: any one can disable the editable control. A required group or direct control publishes required state to the Field Label. Readonly state likewise comes from either the group or direct control. The nested Input or Textarea keeps its value, name, autocomplete, validation, native input and change events, focus methods, and form participation. Form reset restores its initial value, disabled controls are omitted from FormData, and readonly values remain submitted.
Size
Set group size to s, m (default), or l. The group owns the effective presentation of its direct Input or Textarea and add-ons so typography, line height, spacing, and block size stay aligned. A child’s own public size value is not mutated: group size takes presentation precedence only while the child is composed, and the child’s explicit size resumes if it moves outside.
Custom presentation
Use the group’s public CSS custom properties to adapt a supported Nord control rather than replacing it:
--n-input-group-inline-size--n-input-group-background--n-input-group-background-inactive--n-input-group-border-color--n-input-group-border-radius--n-input-group-target-size(overrides the effective size’s token-derived target height)
The Custom Input example customizes the supported Nord Input with its public properties and these variables; it does not accept a different control implementation. The exact-one-Nord-control boundary is intentional: it avoids forking form association, password-manager behavior, native events, and validation semantics.
Accessibility
- Every group needs an accessible label. Use the group’s
label/label slot when standalone, or a connected Field Label inside Field. - Decorative icons should have no label. Give icon-only add-on buttons their own accessible label and associate a Tooltip when the action benefits from visible explanation.
- Keep spinners labeled when they communicate meaningful asynchronous state.
- Required, invalid, disabled, and readonly visuals mirror the effective native and ARIA state of the nested control.
- Focus-visible styling follows keyboard focus on the text control, while
:focus-withinkeeps the shared surface coherent as focus moves to add-on actions. - Logical layout, token-based colors, forced-colors support, reduced motion, multiline growth, and compact-width constraints are built into the group shell.
Rendering boundary
Input Group and Input Group Addon are scoped Light DOM shells. Input and Textarea retain their existing Shadow DOM. Only component-owned label, hint, error, and shell nodes receive the private scope stamp; consumer controls, add-on children, state, listeners, text, and DOM identity remain untouched.