CngxTagGroup
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-labelreactively from[label]. - Provide
CNGX_TAG_GROUPso descendantCngxTagdirectives can readsemanticList()without injecting this concrete class (atomic-decompose rule 4). - Project consumer-supplied
*cngxTagGroupHeader/*cngxTagGroupAccessorytemplates above / below the tag row, exposing the live group state pluscountof projectedCngxTagchildren via the slot context.
Non-responsibilities.
- No
role="listitem"cascade implementation here - that lives inCngxTagso the cascade survives any future non-component implementer ofCngxTagGroupHost(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 (seedisplay-accepted-debt.md §1).
Metadata#
Host#
Providers#
CNGX_TAG_GROUP- useExisting
CngxTagGroup
Relationships
Index#
Derived State
Inputs#
CngxTagGroupAlignCross-axis distribution. start (default) | center | end | between.
this.cfg.groupDefaults?.align ?? 'start'Spacing between projected tags. sm (default) | xs | md.
this.cfg.groupDefaults?.gap ?? 'sm'string | undefinedOptional 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#
unknownPer-instance accessory-slot directive - projected below the row.
contentChild(CngxTagGroupAccessory)unknownResolved accessory template. Same 2-stage cascade as headerTpl.
injectResolvedTagTemplate(this.accessorySlot, 'accessory')unknownPer-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)unknownResolved 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')SignalPublic 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.semanticListInputHostBindings#
| Binding | Expression |
|---|---|
[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- defaultjustify-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.cssfalls it back to--cngx-space-smat the consumption site)--cngx-tag-group-gap-xs/-md- leaf density tokens
Index#
Variant / Density
Layout
<length>8pxVertical gap between the three group zones (header / row / accessory). Drives the outer column stack.
<length>8pxHorizontal gap between tags in the row when no density modifier
is applied. Falls back to --cngx-space-sm.
Variant / Density
<length>4pxHorizontal gap for the .cngx-tag-group--gap-xs density modifier.
<length>12pxHorizontal gap for the .cngx-tag-group--gap-md density modifier.