Skip to content

ConfigurationCard

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

ConfigurationCard

ConfigurationCard is a generic presentational card built on Carbon Tile. It renders a heading, optional body content, and an optional action button. The component has no router coupling — all navigation and external actions are delegated to the parent via the onButtonClick callback prop.

Rationale

Use ConfigurationCard when a configuration or settings page needs a consistent card layout that surfaces a title, a short description (or custom content), and an optional action. Centralising this pattern in one component prevents each configuration page from re-implementing Carbon Tile layout and button wiring.

Source References

  • Source: frontend/src/components/core/ConfigurationCard/index.tsx
  • Tests: frontend/src/components/core/ConfigurationCard/index.unit.test.tsx
  • Barrel: frontend/src/components/core/index.ts
  • Issue: #906 — ConfigurationCard component

Props

Name Type Required Default Description
title string Yes — Card heading.
description string | ReactNode No — Card body text or rich content. Rendered inside a <p> tag when provided. Ignored when children is also provided.
children ReactNode No — Custom children rendered inside the tile. Takes priority over description when both are provided.
buttonLabel string No — Button label text. Button is not rendered when this prop is absent.
onButtonClick () => void No — Callback fired when the button is clicked. Button is not rendered when this prop is absent.
kind ButtonProps['kind'] No 'tertiary' Carbon Button kind passed directly to the underlying Button.
disabled boolean No false When true, the action button is rendered in a disabled state.

Behavior

  • Renders a Carbon Tile containing an <h4> heading.
  • Content priority: when both children and description are provided, children is rendered and description is ignored.
  • Button rendering: the button is rendered only when both buttonLabel and onButtonClick are provided. Providing one without the other suppresses the button entirely.
  • The kind prop defaults to 'tertiary' and is forwarded directly to Carbon Button.
  • The component is purely presentational; it owns no internal state and performs no navigation.

Examples

Happy path: standard configuration card with navigation callback

import { ConfigurationCard } from '@/components/core';

<ConfigurationCard
  title="District average waste volumes"
  description="View or manage district volume tables for each district."
  buttonLabel="View or update tables →"
  onButtonClick={() => navigate({ to: '/configuration/district-volume-tables' })}
/>

Edge case: custom children, primary button, and disabled state

When richer body content is needed, pass children instead of description. The button can be disabled independently while still rendering — useful for permission-gated actions.

import { ConfigurationCard } from '@/components/core';
import { InlineNotification } from '@carbon/react';

<ConfigurationCard
  title="Annual submission targets"
  buttonLabel="Edit targets"
  onButtonClick={handleEdit}
  kind="primary"
  disabled={!canEdit}
>
  <InlineNotification
    kind="info"
    subtitle="Targets are locked until the fiscal period opens."
    hideCloseButton
  />
</ConfigurationCard>

Edge case: title-only card (no body, no button)

The component renders gracefully with only the required title prop.

<ConfigurationCard title="Feature under construction" />

Testing Notes

Current unit coverage (9/9 passing) verifies:

  • Title rendering
  • description rendering as a string
  • children takes priority over description when both are provided
  • Button renders when both buttonLabel and onButtonClick are provided
  • onButtonClick is called once on button click
  • Button is suppressed when onButtonClick is undefined
  • Button is suppressed when buttonLabel is undefined
  • kind prop is forwarded and reflected via CSS class
  • disabled prop disables the button element

Known Constraints

  • The button is suppressed when either buttonLabel or onButtonClick is omitted. Providing only one of the two is a valid no-button state, not an error.
  • description accepts ReactNode but wraps it in a <p> tag. Passing block-level elements (e.g. <div>) will produce invalid HTML. Prefer children for structured content.
  • The component has no internal loading state. Callers are responsible for rendering a skeleton or disabled variant while async data loads.

Change Impact

  • codes/frontend/Components.md — catalog entry points to this page.
  • architecture/frontend/Frontend Architecture Overview.md — may reference the configuration page pattern.

See Also

Waste Plus Wiki

Home

Architecture

Codes

Decisions

Knowledge Base

Development

Changes

Clone this wiki locally