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.

NameTypeDefaultDescription
type'tabs' | 'pills' | 'accordion' | 'card''tabs'Visualization of the container: underlined tabs, rounded pills or stacked accordion panels.
verticalbooleanfalseStacks the header strip vertically beside the content (tabs / pills views).
justifiedbooleanfalseStretches the headers to share the available width equally.
scrollablebooleanfalseAdds backward/forward scroll buttons when the header strip overflows.
isKeysAllowedbooleantrueEnables keyboard navigation (arrows / Home / End / Delete).
multiplebooleanfalseAllows 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.
flushbooleanfalseAccordion view: edge-to-edge panels without outer borders or radius.
bindValuestringundefinedDot-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 === bEquality used to match form values against panel values.
headingstringundefinedhub-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'undefinedhub-panel: semantic colour of an alert ('primary' | 'success' | 'danger' | 'warning' | 'info'). Omit for a neutral alert.
valueunknownidhub-panel: value contributed when the container is used as a form control.
activeboolean (model)falsehub-panel: two-way bound active/expanded state.
disabledbooleanfalsehub-panel: prevents the panel from being activated.
removablebooleanfalsehub-panel: shows a ✕ affordance and enables removal with the Delete key.
routerLinkstring | string[]undefinedhub-panel: turns the panel into a routed panel backed by a <router-outlet>.
queryParamsParamsundefinedhub-panel: query params appended when navigating to routerLink.
pathMatch'route' | 'full''route'hub-panel: URL comparison used to mark a routed panel active.
customClassstringundefinedhub-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.

NameTypeDescription
panelChangeEventEmitter<PanelChangeEvent>hub-panels: emitted when the user activates (opens) a different panel. Provides { current, prev }.
selectPanelEventEmitter<PanelComponent>hub-panel: emitted when the panel becomes active.
deselectPanelEventEmitter<PanelComponent>hub-panel: emitted when the panel stops being active.
removedEventEmitter<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.

NameDescriptionExample
hubPanelHeadingMarks 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 / hubPanelFooterMark 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.

VariableDefaultTypeDescription
--hub-panels-flex-directionrowstring Direction of the header strip relative to the content. rowrow-reverse
--hub-panels-border-width1pxlength Border width used by the tabs strip and active tab. 02px
--hub-panels-border-color#dee2e6color Border colour of the tabs strip and content. #ced4davar(--bs-border-color)
--hub-panels-border-radius0.375remlength Corner radius of the tab headers and content. 00.5rem
--hub-panels-content-bg#fffcolor Background of the content area. transparent#f8f9fa
--hub-panels-header-bgvar(--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-shadownoneshadow Box shadow applied to the content area wrapper. none0 0.5rem 1rem rgba(0,0,0,.08)
--hub-panels-content-padding-x1remlength Horizontal padding of the content area. 0.75rem1.5rem
--hub-panels-content-padding-y1remlength Vertical padding of the content area. 0.75rem1.5rem

Tab Headers

Typography, spacing and colour states of the individual tab/pill headers.

VariableDefaultTypeDescription
--hub-panels-tab-font-weight500number Font weight of the header label. 400600
--hub-panels-tab-padding-x1remlength Horizontal padding inside a header. 0.75rem1.25rem
--hub-panels-tab-padding-y0.5remlength Vertical padding inside a header. 0.375rem0.75rem
--hub-panels-tab-color#212529color Text colour of an inactive header. #495057var(--bs-body-color)
--hub-panels-tab-bgtransparentcolor Background of an inactive header; leave transparent to let --hub-panels-header-bg show through. transparent#f8f9fa
--hub-panels-tab-color-active#0d6efdcolor Text colour of the active header. var(--bs-primary)#0b5ed7
--hub-panels-tab-bg-active#fffcolor 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#f8f9facolor Background of a header on hover. #e9eceftransparent
--hub-panels-tab-border-color-active#0d6efdcolor Border colour of the active tab. var(--bs-primary)#0b5ed7
--hub-panels-tab-active-shadow0 -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-colorrgba(13, 110, 253, 0.25)color Focus ring colour for keyboard focus. rgba(13,110,253,.4)

Pills

Tokens specific to the pills visualization.

VariableDefaultTypeDescription
--hub-panels-pill-border-radius50remlength Corner radius of pill headers. 0.5rem999px
--hub-panels-pill-bg-active#0d6efdcolor Background of the active pill. var(--bs-primary)#198754
--hub-panels-pill-color-active#fffcolor Text colour of the active pill. #fff#000
--hub-panels-pill-gap0.5remlength Gap between pill headers. 0.25rem0.75rem
--hub-panels-pill-content-border-width0length Border width of the pills content card; set it to the shared border width to restore a bordered pane. 01px
--hub-panels-nav-content-gap1remlength 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.

VariableDefaultTypeDescription
--hub-panels-pane-min-width16remlength Minimum width of each open pane before the content area scrolls horizontally. 12rem20rem
--hub-panels-pane-min-height8remlength Minimum height of each open pane in the vertical layout. 6rem12rem
--hub-panels-pane-gap0length 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.

VariableDefaultTypeDescription
--hub-panels-accordion-active-color#0c63e4color Text colour of an expanded accordion header. var(--bs-primary)
--hub-panels-accordion-active-bg#e7f1ffcolor Background of an expanded accordion header. var(--bs-primary-bg-subtle)
--hub-panels-accordion-btn-padding-x1.25remlength Horizontal padding of the disclosure button. 1rem1.5rem
--hub-panels-accordion-btn-padding-y1remlength Vertical padding of the disclosure button. 0.75rem1.25rem
--hub-panels-accordion-btn-icon-transformrotate(-180deg)string Transform applied to the chevron when expanded. rotate(180deg)scaleY(-1)
--hub-panels-accordion-collapse-transition-duration0.25stransition 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.