CngxTag
cngx-tag
projects/common/display/tag/tag.directive.ts
Import#
import { CngxTag } from '@cngx/common/display'
Description#
Decorative tag / label / badge atom.
Why this exists.
CngxChip (@cngx/common/display) covers the removable pill
surface inside chip strips. CngxTag covers the long tail of
static labels: status indicators on a list row, taxonomy badges
on a card, role markers in an admin table, pre-filter chips in a
dashboard sidebar. Two narrow atoms with non-overlapping
concerns beat one chip-tag hybrid with mode flags
(Pillar 3 - Komposition statt Konfiguration).
Responsibilities (intentionally narrow).
- Apply variant / color / size / truncate / maxWidth host
classes + style bindings to any host element (
<span>,<a>,<button>,<div>). - When projected inside a
<cngx-tag-group [semanticList]="true">, reactively exposerole="listitem"so the parent'srole="list"semantics propagate without consumer wiring. The cascade readsCNGX_TAG_GROUP.semanticList()through a singlecomputed<'listitem' | null>()(Pillar 1 - derivation; Pillar 2 - ARIA in the reactive graph).
Non-responsibilities.
- Removable affordance - use
CngxChipinstead. - Clickable / interactive semantics - wrap with native
<button cngxTag>or<a cngxTag>for keyboard + focus + Enter/Space. - Configuration cascade - deferred (see
display-accepted-debt.md §1).
Metadata#
Host#
Relationships
Depends on1
Index#
Derived State
Inputs#
CngxTagColorSemantic colour. Predefined keys (neutral default, success,
warning, error, info) plus any consumer-defined string
which is emitted verbatim as a data-color attribute.
this.cfg.defaults?.color ?? 'neutral'string | nullOptional CSS max-width (e.g. '12rem', '200px'). Bound
inline so consumers don't need a CSS authoring step for ad-hoc
width caps. null clears the binding.
this.cfg.defaults?.maxWidth ?? nullCngxTagSizeDensity. md (default) | sm | lg | xl.
this.cfg.defaults?.size ?? 'md'When true, applies text-overflow: ellipsis + white-space: nowrap
to the inner .cngx-tag__label span. Pair with [maxWidth] for a
hard upper bound. Visual-only - the full text remains in the DOM
for AT.
Deliberately CSS-only - CngxTruncate (@cngx/common/layout) is the
right tool for multi-line clamp + expand/collapse state on long-form
text, but its reactive machinery (effect + ResizeObserver + isClamped
signal) is overkill for a chip-style single-line overflow.
this.cfg.defaults?.truncate ?? falseCngxTagVariantVisual variant. filled (default) | outline | subtle.
this.cfg.defaults?.variant ?? 'filled'Instance Properties#
unknownPer-instance label-slot directive - projected as
<ng-template cngxTagLabel>...</ng-template>. Resolved through
injectResolvedTagTemplate so consumers can override the
default <span class="cngx-tag__label"> wrapper without forking
the directive.
contentChild(CngxTagLabel)unknownResolved label template. Phase 1 cascade: instance slot → host
@else default (<span class="cngx-tag__label"><ng-content /></span>).
Phase 4 commit 5 inserts CNGX_TAG_CONFIG.templates.label as a
middle tier without touching this call site.
injectResolvedTagTemplate(this.labelSlot, 'label')unknownPer-instance prefix-slot directive - projected before the label.
contentChild(CngxTagPrefix)unknownResolved prefix template. Same 2-stage cascade as labelTpl.
injectResolvedTagTemplate(this.prefixSlot, 'prefix')unknownPer-instance suffix-slot directive - projected after the label.
contentChild(CngxTagSuffix)HostBindings#
| Binding | Expression |
|---|---|
[class.cngx-tag--filled] | variant() === 'filled' |
[class.cngx-tag--outline] | variant() === 'outline' |
[class.cngx-tag--subtle] | variant() === 'subtle' |
[class.cngx-tag--sm] | size() === 'sm' |
[class.cngx-tag--md] | size() === 'md' |
[class.cngx-tag--lg] | size() === 'lg' |
[class.cngx-tag--xl] | size() === 'xl' |
[class.cngx-tag--truncate] | truncate() |
[attr.data-color] | color() |
[style.max-width] | maxWidth() |
[attr.role] | roleAttr() |
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
Thematic skin of CngxTag - color cascade, radius, font-weight.
The host carries .cngx-tag; the structural rules (display, flex,
padding, density modifiers, label ellipsis) live in
./shared/tag-base.css and are linked first by the directive's
styleUrls. Per-color surfaces resolve through [data-color="..."]
attribute selectors, and predefined keys cascade through
--cngx-tag-{name}-* custom properties - arbitrary keys ride the
same selector pattern, so consumers can introduce new color names
without forking.
Style variants
Each variant pairs with a [data-color] attribute and rewires
the three tokens --cngx-tag-bg, --cngx-tag-color,
--cngx-tag-border on the host:
--filled- solid tinted background, optional border--outline- transparent fill, colored stroke--subtle- softer tint, transparent border
Color keys
[data-color="neutral"]- gray surface, no semantic claim[data-color="success"]- success-coded[data-color="warning"]- warning-coded[data-color="error"]- danger-coded (note: key name iserror, foundation token is--cngx-color-danger)[data-color="info"]- info-coded
Inheritance
--cngx-tag-radius->--cngx-radius-sm--cngx-tag-success-color->--cngx-color-success--cngx-tag-warning-color->--cngx-color-warning--cngx-tag-error-color->--cngx-color-danger--cngx-tag-info-color->--cngx-color-info- Filled / subtle backgrounds (
--cngx-tag-{key}-bg,--cngx-tag-{key}-subtle-bg) carry their own defaults; no foundation token exists for tinted surfaces
Dark mode
Two hooks flip every filled / subtle background from a high-L tinted surface to a low-L tinted surface, and the matching text colors flip from a dark hue to a light hue so they remain legible against the new background. Borders stay put (mid-tone reads on either surface):
prefers-color-scheme: dark[data-color-scheme="dark"]/.darkclass[data-color-scheme="light"]/.lightclass (explicit pin)
Index#
Variant / Density
Variant / Neutral
Variant / Success
Variant / Warning
Variant / Error
Layout
<length>4pxCorner radius. Defaults to --cngx-radius-sm so tags read as
gentle rectangles rather than pills.
<length>4pxGap between the tag's internal slots (prefix / label / suffix).
Typography
Surface
*transparentBackground. Defaults to transparent; variant + color combinations
pin a concrete value through the [data-color] cascade.
*1px solid transparentBorder shorthand. Variant + color combinations override per
[data-color].
Variant / Density
Variant / Neutral
<color>oklch(0.92 0.005 250)Filled background of the [data-color=neutral] variant.
<color>oklch(0.34 0.015 250)Text color of the [data-color=neutral] variant.
<color>oklch(0.68 0.01 250)Border color of the [data-color=neutral] variant.
<color>oklch(0.96 0.005 250)Subtle background of the [data-color=neutral] variant.
Variant / Success
<color>oklch(0.95 0.05 145)Filled background of the [data-color=success] variant.
See: [[--cngx-color-success]]
<color>oklch(0.4 0.1 160)Text color of the [data-color=success] variant.
<color>oklch(0.65 0.15 155)Border color of the [data-color=success] variant.
<color>oklch(0.97 0.025 145)Subtle background of the [data-color=success] variant.
Variant / Warning
<color>oklch(0.95 0.05 90)Filled background of the [data-color=warning] variant.
See: [[--cngx-color-warning]]
<color>oklch(0.45 0.12 60)Text color of the [data-color=warning] variant.
<color>oklch(0.72 0.18 70)Border color of the [data-color=warning] variant.
<color>oklch(0.98 0.02 90)Subtle background of the [data-color=warning] variant.
Variant / Error
<color>oklch(0.94 0.04 25)Filled background of the [data-color=error] variant.
See: [[--cngx-color-danger]]
<color>oklch(0.4 0.15 25)Text color of the [data-color=error] variant.
<color>oklch(0.65 0.22 25)Border color of the [data-color=error] variant.
<color>oklch(0.98 0.015 25)Subtle background of the [data-color=error] variant.
Variant / Info
<color>oklch(0.93 0.04 240)Filled background of the [data-color=info] variant.
See: [[--cngx-color-info]]
<color>oklch(0.4 0.15 250)Text color of the [data-color=info] variant.
<color>oklch(0.62 0.2 250)Border color of the [data-color=info] variant.
<color>oklch(0.97 0.025 240)Subtle background of the [data-color=info] variant.