Browse documentation

Components Cards & framing

PanelCard

Build a focused metric or content panel using named slots, a standard or bucket surface, and a clear dominant title or value.

Client directive required No provider required

Examples

Link to this example4 presentations

The standard neutral seed preserves its eyebrow, title, value, unit and supporting copy. A visible caption defines the fictional annual hours saved.

368 × 420 px · 100%
Automation
Delivery velocity
2.4M/yr
Automation savings vs last quarter.
Illustrative annual hours saved, compared with last quarter’s rate. Fictional data.

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.

Choosing a presentation

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.

  • Default · metric retains the standard seed’s eyebrow, title, 2.4M /yr value and supporting copy. The added caption defines illustrative annual hours saved and makes the fictional comparison explicit.
  • Bucket · accent retains the tapered seed’s index 02, title and 2.3× value. Use brief content that stays away from its clipped edges.
  • Title, media & footer · dark adds a title-only neutral panel. The decorative CrosshairMark is one media item; a separate footer supplies the next planning step.
  • Progress slot · positive adds an illustrative 92-of-100 checklist, including both component imports and an accessible meter wrapper.

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.

Slots & text limits

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.

  • Choose eyebrow or index, never both. An eyebrow or unit accepts at most one explicit line. An index accepts a non-empty string or finite number, with no enforced line count.
  • A title accepts at most 2 explicit lines; supportingCopy accepts at most 3 explicit lines. These strings must be non-empty. The check counts newline-separated lines, not how text wraps.
  • Rendered titles are also clamped to two wrapped lines, and supporting copy to three. Essential units, timeframe or qualifications belong in readable surrounding text if they might be clipped. Eyebrows, values and units have no visual line clamp.
  • media, footer and progress each accept exactly one React content item when non-null. Group multiple elements in one wrapper. A fragment or wrapper counts as one item, but does not guarantee its contents will fit.
  • footer and progress are mutually exclusive bottom regions. Omit the unused prop: supplying null still participates in this relationship check. The progress slot accepts content, not a numeric progress value.
  • The declared children type is ReactNode, but the implementation rejects any supplied value except null or undefined, including false and empty fragments. Use the named slots.

Invalid fieldMode, tone or surface also throws. These relationships are runtime constraints; a successful TypeScript check alone cannot establish a valid panel.

Geometry & appearance

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.

Props

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.

Types and required flags extracted from the installed @coreux/ui declarations.
Prop / typeDefaultDescription
eyebrowstringundefinedOptional non-empty string, at most one explicit line. Mutually exclusive with index. Rendered uppercase.
indexstring | numberundefinedOptional non-empty string or finite number. Mutually exclusive with eyebrow. No line-count limit is enforced; keep it short.
mediaReactNodeundefinedOne 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.
titlestringundefinedNon-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 | numberundefinedNon-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.
unitstringundefinedNon-empty string, at most one explicit line. Requires value. Shown beside it in 24 px body-family type.
supportingCopystringundefinedNon-empty string, at most three explicit lines; also visually clamped to three wrapped lines. Do not put essential context only in potentially clipped text.
footerReactNodeundefinedOne content item in the bottom region, mutually exclusive with progress. Omit the unused prop: even null counts as supplied for the exclusivity check.
progressReactNodeundefinedOne 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.
revealProgressnumber1Finite 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.
valueProgressnumber1Finite 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.
childrenReactNodeundefinedDeclared ReactNode, but the implementation rejects every non-null, non-undefined value, including false or an empty fragment. Use named slots; omit children.

Accessibility & layout

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.

Consumer setup

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.

Source & revision

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)