Automation
Delivery velocity
2.4M/yr
Automation savings vs last quarter.
Components Cards & framing
Build a focused metric or content panel using named slots, a standard or bucket surface, and a clear dominant title or value.
The standard neutral seed preserves its eyebrow, title, value, unit and supporting copy. A visible caption defines the fictional annual hours saved.
Preview setting only: fitting scales the whole composition. Actual size preserves the copied dimensions and allows horizontal scrolling. The panel itself stays 320 px wide.
Preview only: surrounding canvas and spacing. All metrics are illustrative.
'use client';
import { PanelCard } from '@coreux/ui';
export default function Default() {
return (
<figure style={{ margin: 0, width: 368, boxSizing: 'border-box', background: '#F4F1E9', color: '#0B1221', padding: 24 }}>
<PanelCard
eyebrow="Automation"
title="Delivery velocity"
value="2.4M"
unit="/yr"
supportingCopy="Automation savings vs last quarter."
/>
<figcaption style={{ marginTop: 12, fontSize: 13, lineHeight: 1.5 }}>Illustrative annual hours saved, compared with last quarter’s rate. Fictional data.</figcaption>
</figure>
);
}
Use PanelCard when a metric or short idea needs its own surface, supporting content, and optional bottom region. For an unframed number and caption, use StatBlock. A ProgressMeter can occupy the progress slot when there is a known total.
Both panel seeds retain their component props and ivory 24 px surroundings. Complete examples add visible context beneath the card; all numbers and plans are illustrative. A panel is a presentation surface, not a clickable card or editable dashboard.
Although every prop is optional in the declaration, runtime requires a title or value. Both are allowed; when both are present the value is dominant. A string value must be non-empty; numeric values must be finite. Values render literally, with no formatting or character limit. A unit requires a value.
Invalid fieldMode, tone or surface also throws. These relationships are runtime constraints; a successful TypeScript check alone cannot establish a valid panel.
The article is fixed at 320 px wide and at least 292 px tall, with a 2 px colored outer inset. Its inner region has a 288 px minimum height and grows with content. Standard panels use 24 px inner padding, a 16 px outer radius and a 4 px left accent rail. Bucket panels use 32 px top/side and 24 px bottom padding, an 8 px outer radius, a top rail and a tapered polygon clip. Neither surface provides width, height, style or className props.
The media region is 64 px wide and at least 64 px tall. Constrain media yourself. The bottom region has 24 px top padding and an automatic top margin, which pushes it down when space remains. It can also make the panel taller. Overflow is hidden; bucket clipping narrows both sides toward the bottom. Test your content rather than treating the minimum height as a fixed canvas.
fieldMode selects light or dark. tone accepts neutral, accent, muted, positive, warning and error. Accent uses a cobalt surface with ivory text; muted uses pale steel on light or slate on dark. Semantic tones retain the field surface and text, adding green, saffron or coral borders and rails. State the status in text as well. These are video-family appearance props, distinct from marketing components’ ink/ivory tones.
Supporting copy uses 0.82 opacity. On a muted dark panel this reduces its small-text contrast to about 4.12:1, below 4.5:1. The dark example uses neutral instead so its supporting text stays readable; check contrast when choosing a different tone or supplying slot content.
revealProgress and valueProgress default to 1: fully visible, settled output. Both require finite numbers and clamp to 0–1. Reveal changes overall opacity, scale from 0.98 to 1 and vertical offset from 12 to 0 px. Value progress changes dominant content opacity and offset from 8 to 0 px; it never counts up the number. There is no internal clock or automatic transition. Consumers who animate these inputs must manage timing and reduced-motion preferences.
Types and optional flags come from the installed declarations. Authored defaults are checked against the implementation. The runtime slot relationships above apply even when the type table marks a prop optional.
| Prop / type | Default | Description |
|---|---|---|
eyebrowstring | undefined | Optional non-empty string, at most one explicit line. Mutually exclusive with index. Rendered uppercase. |
indexstring | number | undefined | Optional non-empty string or finite number. Mutually exclusive with eyebrow. No line-count limit is enforced; keep it short. |
mediaReactNode | undefined | One content item in a 64 px wide region with at least 64 px height. A single wrapper can hold a composition; multiple direct children throw. Size and label the supplied content yourself. |
titlestring | undefined | Non-empty string, at most two explicit lines; also visually clamped to two wrapped lines. A title or value is required at runtime; both are allowed. |
valuestring | number | undefined | Non-empty string or finite number, rendered literally at 58 px. Required when title is absent. No numeric formatting, counting animation, length limit or visual line clamp. |
unitstring | undefined | Non-empty string, at most one explicit line. Requires value. Shown beside it in 24 px body-family type. |
supportingCopystring | undefined | Non-empty string, at most three explicit lines; also visually clamped to three wrapped lines. Do not put essential context only in potentially clipped text. |
footerReactNode | undefined | One content item in the bottom region, mutually exclusive with progress. Omit the unused prop: even null counts as supplied for the exclusivity check. |
progressReactNode | undefined | One content item in the bottom region, mutually exclusive with footer. It is a ReactNode slot, not a number; import and supply a ProgressMeter with its semantic wrapper when needed. |
surface"standard" | "bucket" | "standard" | standard has a 16 px radius and left accent rail. bucket has an 8 px radius, tapered polygon clip, top accent rail and larger top/side padding. |
fieldMode"light" | "dark" | "light" | light or dark selects the palette family. Unlike a canvas setting, this changes the actual panel colors. Provide a matching outer background. |
tone"neutral" | "accent" | "muted" | "positive" | "warning" | "error" | "neutral" | neutral, accent, muted, positive, warning or error. Panel surface, text, border and accent come from toneTokens[fieldMode][tone]. Semantic tones use colored borders/rails, not a fully colored surface. |
revealProgressnumber | 1 | Finite number clamped to 0–1. Controls overall opacity, scale from 0.98 to 1, and vertical offset from 12 to 0 px. Defaults to fully revealed; no internal timer. |
valueProgressnumber | 1 | Finite number clamped to 0–1. Controls dominant content opacity and vertical offset from 8 to 0 px: value when present, otherwise title. Does not interpolate the displayed number. |
childrenReactNode | undefined | Declared ReactNode, but the implementation rejects every non-null, non-undefined value, including false or an empty fragment. Use named slots; omit children. |
The component renders an article, but its title is a div rather than a heading. Add an appropriate heading and visible context in your composition when the panel needs an outline entry. The accent rail is decorative and hidden from assistive technology. Label meaningful media; hide purely decorative media as the dark example does. The component does not add keyboard behavior, labels for supplied slots, or live updates.
The progress example hides the library’s unnamed progressbar visual and supplies a named outer progressbar with matching value and units. Its visible caption explains the number. See the ProgressMeter accessibility guidance before composing your own slot.
The copied wrappers are 368 px wide to preserve the 320 px panel plus 24 px padding on each side. At narrow widths, provide a contained scrolling area or another deliberate composition. Fit to canvas only scales this documentation preview; it does not make PanelCard responsive or alter copied source. Actual size preserves geometry in a focusable scrolling region.
Browsing, previews, and copying are public. Installing the private @coreux/ui package requires repository read access and permission to use the bundled CoreUX brand fonts.
Follow the one-time installation guide for the pinned Git dependency, Tailwind v4 stylesheet setup, fonts, and troubleshooting. Keep the 'use client' directive in each example; no provider is required.
The quick start walks through a copied StatBlock in a minimal app.
This reference targets @coreux/ui version 0.1.0 at 06f42fd. Types come from its installed declarations; explanations and defaults are checked against this implementation.
Revision and upgrade notes · Contribution and coverage guide
View PanelCard source (repository access required)