Angular Tabs, Pills & Accordion Component | ng-hub-ui-panels
Angular content-panels component that renders as tabs, pills or an accordion, with routing, reactive forms, keyboard navigation and CSS variables.
API reference
Here's the full contract for panels: everything you can bind, listen to, project and theme, gathered in one place. Wire up what you need and style what you want — it's standalone and signal-friendly.
Inputs
Dial panels in with 20 inputs. Bind them like any Angular @Input.
| Name | Type | Default | Description |
|---|---|---|---|
type | 'tabs' | 'pills' | 'accordion' | 'card' | 'tabs' | Visualization of the container: underlined tabs, rounded pills or stacked accordion panels. |
vertical | boolean | false | Stacks the header strip vertically beside the content (tabs / pills views). |
justified | boolean | false | Stretches the headers to share the available width equally. |
scrollable | boolean | false | Adds backward/forward scroll buttons when the header strip overflows. |
isKeysAllowed | boolean | true | Enables keyboard navigation (arrows / Home / End / Delete). |
multiple | boolean | false | Allows several panels to be active at once. In the accordion view they all expand; in the tabs/pills views every active header starts a visible panel block and the following inactive headers stay grouped above that block until the next active header starts a new one. The form value becomes an array. |
flush | boolean | false | Accordion view: edge-to-edge panels without outer borders or radius. |
bindValue | string | undefined | Dot-notation path applied to each panel's value to obtain the emitted form value (e.g. 'meta.key'). |
compareWith | (a: unknown, b: unknown) => boolean | (a, b) => a === b | Equality used to match form values against panel values. |
heading | string | undefined | hub-panel: plain-text header. Ignored when a hubPanelHeading template is provided. |
appearance | 'card' | 'alert' | 'card' | hub-panel: visual appearance of a standalone panel — 'card' (default) or a semantic 'alert' callout. Ignored in the tabs/pills/accordion strip views. |
variant | 'primary' | 'success' | 'danger' | 'warning' | 'info' | undefined | hub-panel: semantic colour of an alert ('primary' | 'success' | 'danger' | 'warning' | 'info'). Omit for a neutral alert. |
value | unknown | id | hub-panel: value contributed when the container is used as a form control. |
active | boolean (model) | false | hub-panel: two-way bound active/expanded state. |
disabled | boolean | false | hub-panel: prevents the panel from being activated. |
removable | boolean | false | hub-panel: shows a ✕ affordance and enables removal with the Delete key. |
routerLink | string | string[] | undefined | hub-panel: turns the panel into a routed panel backed by a <router-outlet>. |
queryParams | Params | undefined | hub-panel: query params appended when navigating to routerLink. |
pathMatch | 'route' | 'full' | 'route' | hub-panel: URL comparison used to mark a routed panel active. |
customClass | string | undefined | hub-panel: extra CSS classes applied to both the nav item and the pane. |
Outputs
React to what panels does — 4 events to hook your logic onto.
| Name | Type | Description |
|---|---|---|
panelChange | EventEmitter<PanelChangeEvent> | hub-panels: emitted when the user activates (opens) a different panel. Provides { current, prev }. |
selectPanel | EventEmitter<PanelComponent> | hub-panel: emitted when the panel becomes active. |
deselectPanel | EventEmitter<PanelComponent> | hub-panel: emitted when the panel stops being active. |
removed | EventEmitter<PanelComponent> | hub-panel: emitted when the panel is removed via the ✕ button or the Delete key. |
Templates
Make it yours — 3 template slots let you project custom markup.
| Name | Description | Example |
|---|---|---|
hubPanelHeading | Marks an <ng-template> inside a hub-panel as that panel’s custom header (strip link in tabs/pills, disclosure button in accordion), replacing the plain-text heading input. | <hub-panel>
<ng-template hubPanelHeading>
<i class="fa-solid fa-gear"></i> Settings <span class="badge text-bg-primary">3</span>
</ng-template>
Panel content
</hub-panel> |
hubPanelHeader / hubPanelFooter | Mark an element inside a hub-panel as the panel’s content header/footer band. Renders in every view (tabs, pills, accordion, card), distinct from hubPanelHeading. | <hub-panel>
<div hubPanelHeader>Card title</div>
Card content
<div hubPanelFooter>Actions</div>
</hub-panel> |
type="card" | The chromeless card visualization: no navigation strip, every panel always visible. A hub-panel can also be used standalone, outside any hub-panels, where it renders as a card. | <hub-panels type="card">
<hub-panel>…</hub-panel>
<hub-panel>…</hub-panel>
</hub-panels> |
CSS variables
Theme every pixel with 36 CSS variables. Override them at :root or scope them to a wrapper.
Layout & Borders
Overall structure of the container: strip direction, content padding and the shared border tokens.
| Variable | Default | Type | Description |
|---|---|---|---|
--hub-panels-flex-direction | row | string | Direction of the header strip relative to the content. rowrow-reverse |
--hub-panels-border-width | 1px | length | Border width used by the tabs strip and active tab. 02px |
--hub-panels-border-color | #dee2e6 | color | Border colour of the tabs strip and content. #ced4davar(--bs-border-color) |
--hub-panels-border-radius | 0.375rem | length | Corner radius of the tab headers and content. 00.5rem |
--hub-panels-content-bg | #fff | color | Background of the content area. transparent#f8f9fa |
--hub-panels-header-bg | var(--hub-panels-content-bg) | color | Background of the tabs/pills strip area behind inactive headers and spacer zones. #f8f9favar(--bs-tertiary-bg) |
--hub-panels-content-box-shadow | none | shadow | Box shadow applied to the content area wrapper. none0 0.5rem 1rem rgba(0,0,0,.08) |
--hub-panels-content-padding-x | 1rem | length | Horizontal padding of the content area. 0.75rem1.5rem |
--hub-panels-content-padding-y | 1rem | length | Vertical padding of the content area. 0.75rem1.5rem |
Tab Headers
Typography, spacing and colour states of the individual tab/pill headers.
| Variable | Default | Type | Description |
|---|---|---|---|
--hub-panels-tab-font-weight | 500 | number | Font weight of the header label. 400600 |
--hub-panels-tab-padding-x | 1rem | length | Horizontal padding inside a header. 0.75rem1.25rem |
--hub-panels-tab-padding-y | 0.5rem | length | Vertical padding inside a header. 0.375rem0.75rem |
--hub-panels-tab-color | #212529 | color | Text colour of an inactive header. #495057var(--bs-body-color) |
--hub-panels-tab-bg | transparent | color | Background of an inactive header; leave transparent to let --hub-panels-header-bg show through. transparent#f8f9fa |
--hub-panels-tab-color-active | #0d6efd | color | Text colour of the active header. var(--bs-primary)#0b5ed7 |
--hub-panels-tab-bg-active | #fff | color | Background of the active header; defaults to the content surface so the active tab fuses with the panel. var(--bs-primary)var(--hub-panels-content-bg) |
--hub-panels-tab-bg-hover | #f8f9fa | color | Background of a header on hover. #e9eceftransparent |
--hub-panels-tab-border-color-active | #0d6efd | color | Border colour of the active tab. var(--bs-primary)#0b5ed7 |
--hub-panels-tab-active-shadow | 0 -0.25rem 0.5rem rgba(0, 0, 0, 0.06) | shadow | Elevation shadow used by the active tab in the horizontal boxed tabs view. none0 -0.25rem 0.75rem rgba(0,0,0,.12) |
--hub-panels-tab-active-shadow-vertical | -0.25rem 0 0.5rem rgba(0, 0, 0, 0.06) | shadow | Elevation shadow used by the active tab in the vertical boxed tabs view. none-0.25rem 0 0.75rem rgba(0,0,0,.12) |
--hub-panels-tab-focus-ring-color | rgba(13, 110, 253, 0.25) | color | Focus ring colour for keyboard focus. rgba(13,110,253,.4) |
Pills
Tokens specific to the pills visualization.
| Variable | Default | Type | Description |
|---|---|---|---|
--hub-panels-pill-border-radius | 50rem | length | Corner radius of pill headers. 0.5rem999px |
--hub-panels-pill-bg-active | #0d6efd | color | Background of the active pill. var(--bs-primary)#198754 |
--hub-panels-pill-color-active | #fff | color | Text colour of the active pill. #fff#000 |
--hub-panels-pill-gap | 0.5rem | length | Gap between pill headers. 0.25rem0.75rem |
--hub-panels-pill-content-border-width | 0 | length | Border width of the pills content card; set it to the shared border width to restore a bordered pane. 01px |
--hub-panels-nav-content-gap | 1rem | length | Gap between the pills strip and the content card (inline gap when vertical). 0.75rem1.5rem |
Multiple Selection
Layout of the block-based multiple view when the tabs/pills styles allow several active headers at once.
| Variable | Default | Type | Description |
|---|---|---|---|
--hub-panels-pane-min-width | 16rem | length | Minimum width of each open pane before the content area scrolls horizontally. 12rem20rem |
--hub-panels-pane-min-height | 8rem | length | Minimum height of each open pane in the vertical layout. 6rem12rem |
--hub-panels-pane-gap | 0 | length | Gap between multiple panel blocks. 01rem |
Accordion View
Tokens for the accordion visualization. Each falls back to the matching --hub-accordion-* variable for theme compatibility.
| Variable | Default | Type | Description |
|---|---|---|---|
--hub-panels-accordion-active-color | #0c63e4 | color | Text colour of an expanded accordion header. var(--bs-primary) |
--hub-panels-accordion-active-bg | #e7f1ff | color | Background of an expanded accordion header. var(--bs-primary-bg-subtle) |
--hub-panels-accordion-btn-padding-x | 1.25rem | length | Horizontal padding of the disclosure button. 1rem1.5rem |
--hub-panels-accordion-btn-padding-y | 1rem | length | Vertical padding of the disclosure button. 0.75rem1.25rem |
--hub-panels-accordion-btn-icon-transform | rotate(-180deg) | string | Transform applied to the chevron when expanded. rotate(180deg)scaleY(-1) |
--hub-panels-accordion-collapse-transition-duration | 0.25s | transition | Duration of the expand/collapse animation. 0.2s0.35s |
Styling and theming
No styling examples are documented yet. This section will include customization recipes and theming examples.