GitHub

Component catalog

Every esa-* lego the package ships, in one scannable index — the fastest way to answer "does a component for this already exist?" before you build one. Each row links to its full doc page; the Layout & Sections group is where the section-level legos (esa-app-shell, esa-page-header, esa-stat) live.

Core

ComponentKindWhat it isProps
Button esa-button .astro Variant model aligned to Beacon's UiButton (two independent axes + toggle): - variant: primary | secondary | danger | success | warning | info | ai | ghost - appearance: fill | outline | dashed | sof… variant? appearance? active? size? disabled? loading? icon? iconRight? iconOnly? label? current? type? tag? href? target? rel? class? color?
Button Group esa-button-group web component groups slotted <esa-button> elements with connected borders. Faithful port of the Angular esa-button-group: selectionMode 'none' (visual grouping) or 'single' (radio-like segmented control). interactive (Lit)
Button Toggle esa-button-toggle web component Group label and segment text are both UI text (medium). The SELECTED segment steps up to semibold, which is what the -strong weight axis is for — it is not a size change, so the rung stays the same. interactive (Lit)
Icon esa-icon .astro hub-edit-approved: Andy approved (2026-06-15) — the Lucide glyph lookup moved to the shared ./icon-registry module so the SAME map feeds both this server component and the client-side esa-sidebar-nav… name size? label? paths?

Layout & Sections

ComponentKindWhat it isProps
App Shell esa-app-shell .astro CANONICAL application shell . The house chrome: NEUTRAL off-white surfaces layered by value (canvas < bar < rail), a sidebar toggle in the TOP-LEFT corner, the logo at the TOP OF THE SIDENAV, a compa… title? active? items? userMenu? userName? searchIndex? searchPlaceholder? mark? brandHref? accent? collapsed? id?
Page Header esa-page-header .astro The standard prototype page header: optional breadcrumbs OR an eyebrow (with an optional leading icon), a title (heading-lg by default, or the oversized display via prominence="display"), and a right… title meta? eyebrow? icon? prominence? as?
Stat esa-stat .astro A big display value, a readable label, and an optional supporting datum. Replaces the bespoke .stat / .stat__value / .stat__label / .stat__sub cluster every prototype re-implements. value label sub? accent?
Container esa-container .astro Centered, max-width layout wrapper with a symmetric side gutter. The single place the kit owns "constrain page content to a readable width." (Promoted from cb-fish's cbf-container; esa-app-bar alread… maxWidth?

Forms

ComponentKindWhat it isProps
Text Field esa-text-field web component The two composites a control needs at each step of the size ramp. A control renders TWO text treatments at one size: the label is UI text (label-*, medium) and the value the user typed is prose (body… interactive (Lit)
Textarea esa-textarea web component The label and value composites at each step of the control ramp. See the FORMS header in component-tokens.css for why the letters do not line up. interactive (Lit)
Select esa-select web component Label / trigger text is UI text (label-*, medium); typed values, options and chips are prose (body-*, regular). See the FORMS header in component-tokens.css. interactive (Lit)
Combobox esa-combobox web component Label / trigger text is UI text (label-*, medium); typed values, options and chips are prose (body-*, regular). See the FORMS header in component-tokens.css. interactive (Lit)
Input Tag esa-input-tag web component Label / trigger text is UI text (label-*, medium); typed values, options and chips are prose (body-*, regular). See the FORMS header in component-tokens.css. interactive (Lit)
Checkbox esa-checkbox web component A choice label is the option's own text, not the group's heading — prose weight, so it reads body-* rather than label-*. See the FORMS header in component-tokens.css for the step→rung mapping. interactive (Lit)
Checkbox Group esa-checkbox-group web component The group heading is UI text (label-*, medium); each option's own text is prose (body-*, regular). See the FORMS header in component-tokens.css for the mapping. interactive (Lit)
Radio Group esa-radio-group web component The group heading is UI text (label-*, medium); each option's own text is prose (body-*, regular). See the FORMS header in component-tokens.css for the mapping. interactive (Lit)
Switch Toggle esa-switch-toggle web component Why a Web Component (not .astro): this needs real behavior — toggle, keyboard, form participation. As a custom element it works in ANY stack (Astro, React, Angular, plain HTML), which is the portable… interactive (Lit)
Form Field esa-form-field .astro Faithful translation of the Angular esa-form-field: label row + control slot + hint/error text. Error text replaces help text when present. label? size? helpText? errorText? required? disabled?
Field Error esa-field-error .astro Beacon's ui-field-error binds to an Angular AbstractControl and renders its validation errors when the control is invalid + touched/dirty. That control plumbing is framework-specific, so this is the… message? icon? id?
Error Summary esa-error-summary web component id of the field to send the user to — the HOST element (<esa-text-field id="email">), not anything inside its shadow root. IDREFs do not cross a shadow boundary in any engine, so the summary cannot p… interactive (Lit)
Date Picker esa-date-picker web component Label is UI text (medium); the typed date is prose (regular). See the FORMS header in component-tokens.css for the step→rung mapping. interactive (Lit)
Color Picker esa-color-picker web component The label is UI text. The hex field is the one value slot in the kit set in the MONO face — a hex code is tabular, so it reads code-* rather than body-*. interactive (Lit)
Range Slider esa-range-slider web component Both slots are UI text at medium: the field label, and the numeric readout — a readout is chrome, not something the user typed, so it stays label-*. interactive (Lit)
File Upload esa-file-upload web component Faithful translation of the Angular esa-file-upload: - signal inputs → Lit reactive properties - filesSelected output → bubbling/composed 'change' CustomEvent (detail.files) - host dragging/disabled… interactive (Lit)
File List esa-file-list web component File name shown in the row. interactive (Lit)

Display

ComponentKindWhat it isProps
Avatar esa-avatar .astro Faithful translation of the Angular esa-avatar: image → initials → icon fallback, deterministic hue from the name hash, circle/square shapes and size variants. Angular host classes → class list; @if/… name? src? icon? size? shape? initials?
Badge esa-badge .astro Faithful translation of the Angular esa-badge: same variants, sizes, dot mode, same private --_* tokens reading public semantic tokens with literal fallbacks. Angular host classes → class list here;… value? variant? size? dot? label?
Card esa-card .astro Faithful translation of the Angular esa-card: variant / headerVariant / padding host classes, header (icon + title + subtitle), body and optional footer. Angular TemplateRef inputs (header/actions/fo… title? meta? subtitle? icon? variant? headerVariant? padding?
Chip Group esa-chip-group web component Chip text is UI text at the SEMIBOLD tier. It rendered font-weight: 600 as a raw literal — 600 is not a token weight in this system (semibold is 550), so adopting the composite is a small deliberate… interactive (Lit)
Alert Box esa-alert-box .astro Faithful translation of the Angular esa-alert-box: info/success/warning/danger variants with auto-mapped Lucide icons, optional title, slotted message, and an optional dismiss button. Angular host cl… variant? title? dismissable? live?
Danger Zone esa-danger-zone .astro Faithful translation of Beacon's ui-danger-zone: a bordered section that corrals destructive action(s) behind clear danger-colored chrome so a misclick isn't a zero-effort accident. Angular heading/d… heading? description?
Pill esa-pill .astro Faithful translation of the Angular esa-pill: required label, color variants, size variants, optional leading Lucide icon, and an optional remove button. Angular host classes → class list; @if → cond… label variant? removable? size? category? shape?
Pillbox esa-pillbox .astro Faithful translation of the Angular esa-pillbox: a flex-wrap container that lays out pills with a configurable gap. Angular host class bindings on gap() become a class string here; <ng-content> becom… gap?
Progress Bar esa-progress-bar .astro Faithful translation of the Angular esa-progress-bar: determinate/indeterminate modes, size and color variants, optional label + percentage value, and the clamped 0–100 fill. Angular host classes/ari… value? mode? size? variant? label? showValue?
Loading Spinner esa-loading-spinner .astro Faithful translation of the Angular esa-loading-spinner: xs/sm/md/lg sizes and an optional custom color (CSS value, defaults to --color-background-brand). Angular host classes + [style.--_spinner-col… size? color? label? decorative?
Loading Overlay esa-loading-overlay .astro Faithful translation of the Angular esa-loading-overlay: covers its positioned parent with a spinner (lg) and an optional message when active; transparent switches the opaque backdrop to a semi-trans… active? message? transparent?
Empty State esa-empty-state .astro Faithful translation of the Angular esa-empty-state: optional icon, required title, optional description, slotted actions, and xs/sm/md/lg size variants. Angular host classes → class list; @if → cond… title description? size?
Back To Top esa-back-to-top web component Why a Web Component (not .astro): it owns runtime behavior — a passive scroll listener that shows/hides the button past a threshold, and click-to-scroll-to-top. As a custom element it works in any st… interactive (Lit)
Collapsible esa-collapsible .astro A single disclosure section: an icon + title summary over a slotted body, built on the native <details>/<summary> element (free a11y, keyboard, and open/close state — no JS). The standard disclosure… title icon? iconPaths? open? flush?
Keycap esa-kbd .astro A keycap for rendering keyboard hints (/, Tab, Esc, ↑ ↓ ↵). Slot the key label. —

Overlays

ComponentKindWhat it isProps
Dialog esa-dialog web component modal dialog [wc]. Built on the NATIVE <dialog> element, opened with showModal(). interactive (Lit)
Confirm Dialog esa-confirm-dialog web component confirmation modal [wc]. Faithful translation of the Angular esa-confirm-dialog. interactive (Lit)
Side Dialog esa-side-dialog web component a slide-in drawer / side sheet (Ecology's first). Aligned to Beacon's ui-side-dialog. interactive (Lit)
Popover esa-popover web component click/hover anchored popover [wc]. Faithful translation of the Angular esaPopover directive + popover content component (which used @angular/cdk/overlay). interactive (Lit)
Tooltip esa-tooltip web component hover/focus tooltip [wc]. Faithful translation of the Angular esaTooltip directive + tooltip panel (which used @angular/cdk/overlay). interactive (Lit)
Dropdown Menu esa-dropdown-menu web component click-toggled menu [wc]. Faithful translation of the Angular esa-dropdown-menu (which used @angular/cdk/overlay CdkConnectedOverlay). interactive (Lit)
Command Palette esa-command-palette web component The command's name, as it reads in the list. e.g. interactive (Lit)
Snackbar esa-snackbar-container web component Milliseconds before the toast dismisses itself. **0 (the default) means it stays until dismissed.** This default changed on 2026-08-16, from 5000. interactive (Lit)
Snackbar Item esa-snackbar-item web component a single toast [wc]. Faithful translation of the Angular esa-snackbar-item. interactive (Lit)
Search Panel esa-search-panel web component Faithful translation of the Angular esa-search-panel (overlays entry point): - Angular signal inputs (placeholder/results/loading/position) → Lit properties - two-way open model → reflected open attr… interactive (Lit)
ComponentKindWhat it isProps
App Bar esa-app-bar .astro The full-bleed horizontal chrome shell shared by top nav bars, sub-bars, and footers. It sets a COLOR CONTEXT (background + currentColor) from ecology semantic tokens via tone, then exposes three slo… tone? contained? maxWidth? as? ariaLabel? class?
Nav Dropdown esa-nav-dropdown .astro A chrome-button trigger paired with a floating panel, using a native <details>/<summary> disclosure — zero runtime JS, same pattern as esa-header-nav. The trigger reuses esa-button (variant="chrome"… label icon? size? align?
Header Nav esa-header-nav .astro A data-driven convenience SET, now composed from the chrome bricks rather than re-implementing them: esa-app-bar → the bar shell + start/main/end slots + tone esa-icon-link → plain nav links esa-nav-… items? user? navLabel?
Sidebar Nav esa-sidebar-nav web component Why a Web Component (not .astro): the sidebar carries real runtime state — a collapse toggle (icon-rail vs. full width) and per-parent accordion expand. interactive (Lit)
Breadcrumbs esa-breadcrumbs .astro Faithful translation of the Angular esa-breadcrumbs: same item shape, size variants, separator icon, and "last item = current page" semantics. Angular host classes → class list; Angular @for/@if → JS… items size?
Pagination esa-pagination web component Why a Web Component (not .astro): page navigation is pure runtime state — current page, prev/next/first/last, page-size selection, and the derived "1 – 25 of 100" range label. Not a form control (no… interactive (Lit)
Tab Layout esa-tab-layout web component The two composites a tab renders at each step of the size ramp. A tab label is regular until it is the selected one, and then it is UI text carrying state — so the active row swaps family rather than… interactive (Lit)

Filters

ComponentKindWhat it isProps
Filter Container esa-filter-container .astro Faithful translation of the Angular esa-filter-container: a wrapping flex row that lays out filter dropdowns, pills, and the clear button with consistent wrap + gap. In Angular this also provided the… gap? rowGap?
Filter Dropdown esa-filter-dropdown web component The three composites this control renders at each step of the size ramp. The trigger is UI text (label-*, medium) and gains weight — not size — once a filter is applied, so selection reads as emphasi… interactive (Lit)
Filter Pills esa-filter-pills .astro Faithful translation of the Angular esa-filter-pills: rounded chips showing "<label>: <displayValue>" with an x remove button. In Angular the chips came from the injected EsaFilterService. filters?
Filter Clear Button esa-filter-clear-button .astro Faithful translation of the Angular esa-filter-clear-button: same ghost/link styling, optional leading icon (Lucide filter-x), and "Clear all" default label. In Angular, visibility was driven by the… label? showIcon? hidden?

Data & Editors

ComponentKindWhat it isProps
Chart esa-chart web component an accessibility-corrected wrapper over AG Charts Community. WHY A WRAPPER. interactive (Lit)
Data Grid esa-grid reference esa-grid is a thin Ecology skin over AG Grid (ag-grid-angular / ag-grid-community). wraps AG Grid —
Map esa-map reference esa-map renders an interactive slippy map with markers, or a themed placeholder when the mapping library is absent. wraps Leaflet —
Rich Text Editor esa-rich-text-editor reference esa-rich-text-editor is a WYSIWYG field: a formatting toolbar above an editable content area, wired as a form control. wraps TinyMCE —

Deprecated

Still shipped, still working — each is a shim that forwards to its replacement and warns at build time, so a spoke that upgrades does not break. They are listed here rather than in the group they used to sit in so nobody picks one by browsing. Migrate a spoke with /update-tokens.

ComponentKindWhat it isProps
Icon Button esa-icon-button .astro use esa-button variant="chrome" iconOnly DEPRECATED (2026-08-14). Now a shim over esa-button. icon label href? size? type?

A composition you keep rebuilding that isn't a single lego? It may belong in the Pattern Library — or be a /request-lego. The on-disk catalog is always the source of truth: ls node_modules/@esa/ecology/src/components/ from any spoke.