Skip to main content
cngx-src documentation

CngxTagGroup

ComponentPrimaryOnPushNo encapsulationv0.1.0WCAG AA

projects/common/display/tag-group/tag-group.component.ts

Import#

import { CngxTagGroup } from '@cngx/common/display'

Description#

Layout-only container for a row of CngxTag siblings.

Why this exists. Pairs with CngxTag to satisfy the long tail of "render N taxonomy badges in a row, optionally as a semantic list" needs. The component owns only the flex-wrap layout (gap / align), the role="list" + aria-label ARIA opt-in, and the <ng-template>-driven header / accessory slot zones. The cascade that flips each child's role="listitem" lives on the CngxTag side (tag.directive.ts reads CNGX_TAG_GROUP.semanticList() through a computed); this component just provides the implementer of that token (Pillar 1 - derivation rather than imperative sync; Pillar 2 - ARIA in the reactive graph).

Responsibilities (intentionally narrow).

  • Apply gap / align host-class modifiers + thematic CSS custom properties.
  • Bind role="list" reactively from [semanticList].
  • Bind aria-label reactively from [label].
  • Provide CNGX_TAG_GROUP so descendant CngxTag directives can read semanticList() without injecting this concrete class (atomic-decompose rule 4).
  • Project consumer-supplied *cngxTagGroupHeader / *cngxTagGroupAccessory templates above / below the tag row, exposing the live group state plus count of projected CngxTag children via the slot context.

Non-responsibilities.

  • No role="listitem" cascade implementation here - that lives in CngxTag so the cascade survives any future non-component implementer of CngxTagGroupHost (test doubles, programmatic groups).
  • No hostDirectives - decorative atoms have no shared cross-cutting behaviour to compose. Per atomic-decompose rule 1 the absence is the right call until a future shared concern lands.
  • Configuration cascade (provideTagConfig) - deferred (see display-accepted-debt.md §1).

https://cngxjs.github.io/cngx/examples/#/common/display/tag/app-wide-defaults-via-providetagconfig https://cngxjs.github.io/cngx/examples/#/common/display/tag/color-palette https://cngxjs.github.io/cngx/examples/#/common/display/tag/composition-with-cngxicon https://cngxjs.github.io/cngx/examples/#/common/display/tag/density https://cngxjs.github.io/cngx/examples/#/common/display/tag-group/semantic-list https://cngxjs.github.io/cngx/examples/#/common/display/tag-group/with-header-accessory https://cngxjs.github.io/cngx/examples/#/common/display/tag-group/alignment https://cngxjs.github.io/cngx/examples/#/common/display/tag-group/gap-variants https://cngxjs.github.io/cngx/examples/#/common/display/tag/link-mode https://cngxjs.github.io/cngx/examples/#/common/display/tag/slot-overrides-custom-label https://cngxjs.github.io/cngx/examples/#/common/display/tag/slot-overrides-prefix-label-suffix https://cngxjs.github.io/cngx/examples/#/common/display/tag/truncate-maxwidth https://cngxjs.github.io/cngx/examples/#/common/display/tag/variant-matrix

Metadata#

Host#

Providers#

CNGX_TAG_GROUP
useExisting CngxTagGroup

Relationships

Index#

Inputs#

input()

Cross-axis distribution. start (default) | center | end | between.

default this.cfg.groupDefaults?.align ?? 'start'
input()

Spacing between projected tags. sm (default) | xs | md.

default this.cfg.groupDefaults?.gap ?? 'sm'
label#string | undefined
input()

Optional label rendered as aria-label on the host. When the group also opts into [semanticList]="true", AT reads "Tags, list, N items"; without semanticList, the label sits on a decorative grouping (no role).

Instance Properties#

accessorySlot#unknown
contentChild()ProtectedReadonly

Per-instance accessory-slot directive - projected below the row.

contentChild(CngxTagGroupAccessory)
accessoryTpl#unknown
ProtectedReadonly

Resolved accessory template. Same 2-stage cascade as headerTpl.

injectResolvedTagTemplate(this.accessorySlot, 'accessory')
headerSlot#unknown
contentChild()ProtectedReadonly

Per-instance header-slot directive - projected as <ng-template cngxTagGroupHeader>...</ng-template>. Resolved through injectResolvedTagTemplate so consumers can project a header without wrapping the group component.

contentChild(CngxTagGroupHeader)
headerTpl#unknown
ProtectedReadonly

Resolved header template. Phase 2 cascade: instance slot → null (no DOM rendered above the row when not projected). Phase 4 commit 5 inserts CNGX_TAG_CONFIG.templates.header as a middle tier without touching this call site.

injectResolvedTagTemplate(this.headerSlot, 'header')
semanticList#Signal
Readonly

Public host-contract field. InputSignal<boolean> already structurally extends Signal<boolean>, so the assignment narrows the public type without a runtime conversion. Read by CngxTag.roleAttr through CNGX_TAG_GROUP to derive role="listitem" reactively.

this.semanticListInput

HostBindings#

BindingExpression
[class.cngx-tag-group--gap-xs]gap() === 'xs'
[class.cngx-tag-group--gap-md]gap() === 'md'
[class.cngx-tag-group--align-start]align() === 'start'
[class.cngx-tag-group--align-center]align() === 'center'
[class.cngx-tag-group--align-end]align() === 'end'
[class.cngx-tag-group--align-between]align() === 'between'
[attr.role]semanticList() ? 'list' : null
[attr.aria-label]label() ?? null

Shared structural skeleton for the tag family. Two scopes live here because both atoms share structural defaults and link this file first in their styleUrls:

  • .cngx-tag - inline-flex pill (gap, padding, font-size, density modifiers, label ellipsis)
  • .cngx-tag-group - vertical three-zone stack (header / row / accessory) with gap + alignment modifiers

Thematic skin (color cascade, radius, font-weight) is in the per-atom files (../tag.css, ../tag-group.component.css). Layout-only file - no @property registrations here; the structural tokens are registered in those neighbours and this file just consumes them.

Density modifiers (CngxTag)

  • --sm - padding + font-size compressed
  • (no modifier - default md)
  • --lg - padding + font-size lifted
  • --xl - padding + font-size lifted further
  • --truncate - single-line label with ellipsis on __label

Gap modifiers (CngxTagGroup)

Applied to > .cngx-tag-group__row:

  • --gap-xs - tight row gap
  • (no modifier - default sm)
  • --gap-md - relaxed row gap

Alignment modifiers (CngxTagGroup)

  • --align-start - default justify-content: flex-start
  • --align-center
  • --align-end
  • --align-between

Slots

  • .cngx-tag__label - shrinkable text container, truncates under --truncate
  • .cngx-tag-group__row - the inline-flex row inside the stack

Inheritance

  • --cngx-tag-gap -> --cngx-space-xs
  • --cngx-tag-font-size -> --cngx-font-size-sm
  • --cngx-tag-group-stack-gap -> --cngx-space-sm
  • --cngx-tag-group-gap -> --cngx-space-sm
  • --cngx-tag-group-gap-xs -> --cngx-space-xs
  • density / alignment tokens fall straight back to literal defaults registered in the per-atom files

Token surface for CngxTagGroup. The host carries .cngx-tag-group and stacks a header / row / accessory column; the structural rules (column stack, row flex-wrap, gap and alignment modifiers) live in ../tag/shared/tag-base.css and are linked first by the component's styleUrls array. This file registers only the layout-related @property tokens so a future thematic skin (a backplate color for a Material wrapper, say) can land here without changing the style-link surface.

Density modifiers

Consumed by the gap rules in tag-base.css:

  • --cngx-tag-group-gap-xs - tight row spacing
  • --cngx-tag-group-gap-md - relaxed row spacing
  • (no modifier - default --cngx-tag-group-gap)

Inheritance

  • --cngx-tag-group-stack-gap - leaf token, outer column gap
  • --cngx-tag-group-gap - leaf token, row gap (tag-base.css falls it back to --cngx-space-sm at the consumption site)
  • --cngx-tag-group-gap-xs / -md - leaf density tokens

Index#

Layout

--cngx-tag-group-stack-gap#<length>
Default value 8px

Vertical gap between the three group zones (header / row / accessory). Drives the outer column stack.

--cngx-tag-group-gap#<length>
Default value 8px

Horizontal gap between tags in the row when no density modifier is applied. Falls back to --cngx-space-sm.

Variant / Density

--cngx-tag-group-gap-xs#<length>
Default value 4px

Horizontal gap for the .cngx-tag-group--gap-xs density modifier.

--cngx-tag-group-gap-md#<length>
Default value 12px

Horizontal gap for the .cngx-tag-group--gap-md density modifier.