Skip to content

ReadonlyInput

Paulo Gomes da Cruz Junior edited this page Jun 16, 2026 · 3 revisions

ReadonlyInput

Overview

ReadonlyInput is a small display component for labeled, read-only values. It uses semantic description-list markup, supports optional skeleton loading, optional tooltip help text, and a numeric display variant for values that should use the number-specific style.

It is useful anywhere the UI needs to present field-style data without allowing user editing, such as profile details, search result summaries, or detail panels.

Props

Name Type Required Description
label string ✅ The label displayed above the content
displayLabel boolean ❌ Whether to display the label. Defaults to true.
labelClassName string ❌ Additional CSS class name to be applied to the label. Defaults to ''.
children React.ReactNode ❌ The content to display. Falls back to -- when children is null or undefined
showSkeleton boolean ❌ If true, renders Carbon's TextInputSkeleton instead of the value content. Defaults to false.
id string ❌ HTML id attribute for the component's root element
tooltipText string ❌ Text shown in a Carbon DefinitionTooltip wrapped around the displayed content
isNumber boolean ❌ If true, applies number-specific styling (monospace font) to the content

Usage Examples

Basic Usage

import ReadonlyInput from "@/components/Form/ReadonlyInput";

<ReadonlyInput label="Email Address">user@example.com</ReadonlyInput>;

With Tooltip

<ReadonlyInput
  label="Employee ID"
  tooltipText="This is the unique identifier assigned by HR"
>
  EMP-12345
</ReadonlyInput>

With Number Styling

<ReadonlyInput label="Phone Number" isNumber={true}>
  (555) 123-4567
</ReadonlyInput>

With Skeleton Loading State

const [loading, setLoading] = React.useState(true);

<ReadonlyInput label="User Name" showSkeleton={loading}>
  John Doe
</ReadonlyInput>;

Complete Example

<ReadonlyInput
  id="user-details-name"
  label="Full Name"
  tooltipText="The user's legal full name"
  isNumber={false}
  showSkeleton={false}
>
  Jane Smith
</ReadonlyInput>

Behavior

Semantic structure

The component renders:

  • <dl> as the root container
  • <dt> for the label
  • <dd> for the displayed value

This keeps label-to-value relationships understandable to assistive technologies.

Skeleton mode

When showSkeleton is true, the component returns early and renders only a Carbon TextInputSkeleton. In that mode, it does not render the semantic description-list structure, tooltip wrapper, or value content.

Placeholder behavior

If children is null or undefined, the component falls back to the PLACE_HOLDER constant, which is currently --.

Because the implementation uses the nullish coalescing operator, other falsy values are handled differently:

  • empty string renders as the provided empty string value
  • numeric values render normally
  • boolean values are passed through React's normal rendering behavior

Tooltip behavior

When tooltipText is provided, the rendered value is wrapped in Carbon's DefinitionTooltip with openOnHover enabled.

  • string and number content are wrapped in a <span> before being passed to the tooltip
  • existing React elements are rendered directly inside the tooltip wrapper
  • no tooltip is rendered while showSkeleton is enabled

Label visibility

displayLabel defaults to true. When it is set to false, the visible label text is hidden, but the <dt> element still renders and keeps its aria-label, so the semantic label remains available to assistive technologies.

Title attribute

The <dd> element gets a native title attribute only when children is a string and skeleton mode is off. The placeholder fallback does not automatically become the title value.

Test IDs and Utilities

The component generates stable test ids from the label text using toKebabCase():

  • card-item-<label> for the root <dl>
  • card-item-content-<label> for the <dd>

toKebabCase() trims the text, removes empty whitespace segments, lowercases the result, and joins words with hyphens.

Utilities

toKebabCase(text: string): string

Converts a text string into kebab-case format (words separated by hyphens, all lowercase).

Parameters:

  • text - The input string to convert

Returns: The kebab-case version of the input string

Examples:

toKebabCase("Hello World"); // => 'hello-world'
toKebabCase("Employee ID"); // => 'employee-id'
toKebabCase("  First Name  "); // => 'first-name'
toKebabCase("This Is A Test"); // => 'this-is-a-test'

Features:

  • Trims leading and trailing whitespace
  • Filters out empty words
  • Converts to lowercase
  • Joins words with hyphens

Constants

PLACE_HOLDER

The default placeholder value displayed when no children are provided to the component.

Value: "--"

Usage:

import { PLACE_HOLDER } from "@/components/Form/ReadonlyInput/constants";

// The component automatically uses this when children is undefined

Styling

The component applies the following CSS classes:

  • .card-item - Applied to the root <dl> element
  • .card-item-label - Applied to the <dt> element
  • .card-item-content - Applied to the <dd> element (default)
  • .card-item-content-number - Applied to the <dd> element when isNumber={true}

For custom styling, refer to index.scss in the component directory.

Testing

The component includes unit tests covering:

  • Content rendering and placeholder behavior
  • Skeleton loading states
  • CSS class application
  • Tooltip functionality
  • Test ID generation
  • Label visibility and aria-label preservation
  • Edge cases such as empty strings, numbers, and booleans

Run tests with: npm run test:unit

Related Components

Waste Plus Wiki

Home

Architecture

Codes

Decisions

Knowledge Base

Development

Changes

Clone this wiki locally