Skip to main content

Presentation Patterns

@thyris/ui-patterns combines primitives into repeatable interface structures. Patterns remain controlled, prop-driven presentation. The application adapts API data, owns permissions, performs side effects, and passes event handlers.

Keep @thyris/ui and @thyris/ui-patterns on the same release version.

Page and Navigation Patterns​

PatternUse It ForImportant Inputs
PageHeaderConsistent title, description, icon, actions, and breadcrumb framing.title, description, icon, action, breadcrumbs.
SectionNavigationControlled navigation between related sections.Items, active item, selection or rendering callback.
SidebarServiceSearchSearch and grouped service navigation inside the shared sidebar.Groups, query, active item, empty text, render or navigation hooks.
import {PageHeader} from "@thyris/ui-patterns"
import {Button} from "@thyris/ui"
import {Boxes} from "lucide-react"

export function CatalogHeader() {
return (
<PageHeader
title="Catalog"
description="Manage products available to customer and agent journeys."
icon={<Boxes aria-hidden="true" />}
breadcrumbs={[
{label: "Store", href: "/store"},
{label: "Catalog"},
]}
action={<Button type="button">Add product</Button>}
/>
)
}

The application owns actual route transitions and permission-filtered navigation items.

Collection and Table Patterns​

PatternUse It ForImportant Inputs
SearchFilterToolbarSearch, filters, and collection actions above a list or table.Controlled value/change handler, placeholder, icon, filters, actions.
BulkActionToolbarSelection count and actions that affect selected rows.Selection state, labels, actions, clear handler.
TablePaginationPage navigation and optional page-size selection.Page, page count, row count, page size, callbacks, labels.
useTablePaginationClient-side pagination of an already available collection.Items, controlled initial or current page configuration.
OperationLogTableShellStandard filters, states, table, and pagination for logs.Toolbar, table content, loading/empty state, pagination.
DomainTableShellStandard page-level framing around domain tables.Header context, toolbar, table, state, pagination.
CollectionTableShellGeneral semantic alias of DomainTableShell.Same as DomainTableShell.
CatalogProductTableShellCatalog-specific semantic alias.Same as DomainTableShell.
ProcurementTableShellProcurement-specific semantic alias.Same as DomainTableShell.

Apply filters before pagination. Distinguish initial empty, filtered empty, loading, and error states. Pattern callbacks should call application-owned query or mutation logic.

Feedback and Utility Patterns​

PatternUse It For
FeedbackAlertSuccess, error, or informational feedback with consistent tone.
StatusBadgeTextual status with default, success, warning, muted, or destructive tone.
formatStatusLabelConvert stable lowercase or underscore values into readable labels.
EmptyStateExplain why no content is shown and provide a relevant next action.
CopyableValue, CopyId, HeaderIdChipDisplay and copy identifiers without rebuilding clipboard feedback.
MetricCardPresent one operational metric, supporting detail, and optional trend or icon.
import {EmptyState, StatusBadge} from "@thyris/ui-patterns"

export function ProviderState({count}: {count: number}) {
if (count === 0) {
return (
<EmptyState
title="No providers configured"
description="Add a provider before enabling enrichment jobs."
/>
)
}

return <StatusBadge value="active" tone="success" />
}

The application decides what a status means. The pattern only presents the value.

Selection and Form Patterns​

PatternUse It For
SelectionListPanelA labeled, searchable, keyboard-operable list of selectable items.
ProviderSelectorGrouped provider choice using presentation-ready provider options.
WizardDialogShellDialog framing, steps, body, and navigation actions for a controlled wizard.
AppDialogProvider, useAppDialogApplication-level alert, confirmation, and prompt dialog orchestration.

WizardDialogShell does not own validation, credentials, persistence, or route changes. Validate each step and perform side effects in application handlers.

Domain Presentation Patterns​

Domain wording is allowed in these presentation models, but backend behavior is not.

PatternUse It For
EnrichmentProviderTableProvider rows, status, usage, selection, and row or bulk controls.
EnrichmentUsageChartPresentationA prepared enrichment usage time series.
EnrichmentUsageLogEnrichment request history with filters and pagination.
EnrichmentUsageMetricGroupQuota, usage, and progress metric cards.
MarketplaceRecentRunsA concise table of recent marketplace executions.
ProviderWizardPresentationVisual steps and controlled fields for provider configuration.

Adapt raw responses before passing them to these patterns:

const rows = apiProviders.map((provider) => ({
id: provider.id,
name: provider.displayName,
description: provider.description,
textModel: provider.textModel,
imageModel: provider.imageModel,
inputPricePerMillion: provider.inputPrice.toString(),
outputPricePerMillion: provider.outputPrice.toString(),
imagePrice: provider.imagePrice.toString(),
currency: provider.currency,
isDefault: provider.id === defaultProviderId,
}))

return (
<EnrichmentProviderTable
title="Providers"
description="Models and pricing available to enrichment jobs."
providers={rows}
onEdit={(provider) => openEditDialog(provider.id)}
onMakeDefault={(provider) => setDefaultMutation.mutate(provider.id)}
/>
)

The exact presentation interface is exported by the installed package and should be checked by TypeScript. Do not pass raw API models simply because some field names currently overlap.

Pattern Ownership Checklist​

A shared pattern may:

  • Render presentation-ready models.
  • Hold local visual state that does not represent business truth.
  • Invoke callbacks supplied by the consumer.
  • Compose primitives and semantic tokens.
  • Define safe responsive and accessible behavior.

A shared pattern must not:

  • Fetch from a product API.
  • Import a product router or route table.
  • Read application authentication or permissions.
  • Store or transmit credentials.
  • Perform mutations or decide business state transitions.
  • Import database or backend-only types.