# Tag

Use `ui-tag` for short labels that add context without taking much space: status chips, filter tokens, categories, owner metadata, or removable selections. Tags can be purely informational, selectable like filter chips, or dismissible like lightweight tokens.

## Import
```ts
import { TagComponent } from 'ui';
```

## Basic metadata tags
```ts
import { Component } from '@angular/core';
import { TagComponent } from 'ui';

@Component({
  selector: 'app-tag-basic-demo',
  standalone: true,
  imports: [TagComponent],
  template: `
    <div style="display:flex;flex-direction:column;gap:1rem;width:100%;max-width:42rem">
      <div
        style="display:flex;flex-wrap:wrap;gap:0.75rem;align-items:flex-start;padding:1rem;border:1px solid var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background-rest)"
      >
        <ui-tag text="Design system" appearance="filled" variant="secondary" />
        <ui-tag text="Internal" appearance="tint" variant="info" />
        <ui-tag text="Needs review" appearance="outline" variant="warning" />
        <ui-tag text="Approved" appearance="subtle" variant="success" />
      </div>

      <div
        style="display:flex;flex-wrap:wrap;gap:0.75rem;align-items:flex-start;padding:1rem;border:1px solid var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background-rest)"
      >
        <ui-tag
          text="Campaign launch"
          secondaryText="Q3"
          icon="rocket"
          appearance="filled"
          variant="primary"
        />
        <ui-tag
          text="Owner"
          secondaryText="Ava Lopez"
          icon="person"
          appearance="tint"
          variant="secondary"
        />
      </div>
    </div>
  `,
})
export class TagBasicDemoComponent {}
```

## Appearance and variant
```ts
import { Component } from '@angular/core';
import { TagComponent } from 'ui';

@Component({
  selector: 'app-tag-appearance-variant-demo',
  standalone: true,
  imports: [TagComponent],
  template: `
    <div style="display:flex;flex-direction:column;gap:1rem;width:100%;max-width:44rem">
      <div
        style="display:flex;flex-direction:column;gap:0.75rem;padding:1rem;border:1px solid var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background-rest)"
      >
        <div style="font-size:0.9375rem;font-weight:600">Subtle metadata tags</div>
        <div style="display:flex;flex-wrap:wrap;gap:0.75rem">
          <ui-tag text="Billing" appearance="subtle" variant="secondary" />
          <ui-tag text="Compliance" appearance="subtle" variant="info" />
          <ui-tag text="High priority" appearance="subtle" variant="danger" />
        </div>
      </div>

      <div
        style="display:flex;flex-direction:column;gap:0.75rem;padding:1rem;border:1px solid var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background-rest)"
      >
        <div style="font-size:0.9375rem;font-weight:600">Higher-emphasis state tags</div>
        <div style="display:flex;flex-wrap:wrap;gap:0.75rem">
          <ui-tag text="Published" appearance="filled" variant="success" />
          <ui-tag text="At risk" appearance="tint" variant="warning" />
          <ui-tag text="Blocked" appearance="outline" variant="danger" />
          <ui-tag text="New" appearance="filled" variant="primary" />
        </div>
      </div>
    </div>
  `,
})
export class TagAppearanceVariantDemoComponent {}
```

## Size and shape
```ts
import { Component } from '@angular/core';
import { TagComponent } from 'ui';

@Component({
  selector: 'app-tag-size-shape-demo',
  standalone: true,
  imports: [TagComponent],
  template: `
    <div style="display:flex;flex-direction:column;gap:1rem;width:100%;max-width:42rem">
      <div
        style="display:flex;flex-wrap:wrap;gap:0.75rem;align-items:center;padding:1rem;border:1px solid var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background-rest)"
      >
        <ui-tag text="Small" size="small" appearance="tint" variant="primary" />
        <ui-tag text="Medium" size="medium" appearance="tint" variant="primary" />
        <ui-tag text="Large" size="large" appearance="tint" variant="primary" />
      </div>

      <div
        style="display:flex;flex-wrap:wrap;gap:0.75rem;align-items:center;padding:1rem;border:1px solid var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background-rest)"
      >
        <ui-tag text="Rounded" shape="rounded" appearance="outline" variant="secondary" />
        <ui-tag text="Circular" shape="circular" appearance="outline" variant="secondary" />
        <ui-tag text="Square" shape="square" appearance="outline" variant="secondary" />
      </div>
    </div>
  `,
})
export class TagSizeShapeDemoComponent {}
```

## Selectable filter chips
```ts
import { Component } from '@angular/core';
import { TagComponent } from 'ui';

@Component({
  selector: 'app-tag-selectable-filters-demo',
  standalone: true,
  imports: [TagComponent],
  template: `
    <div style="display:flex;flex-direction:column;gap:1rem;width:100%;max-width:44rem">
      <div
        style="display:flex;flex-wrap:wrap;gap:0.75rem;align-items:flex-start;padding:1rem;border:1px solid var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background-rest)"
      >
        <ui-tag
          text="Assigned to me"
          appearance="tint"
          variant="primary"
          [selectable]="true"
          [(selected)]="assignedToMe"
        />
        <ui-tag
          text="Open"
          appearance="tint"
          variant="success"
          [selectable]="true"
          [(selected)]="openOnly"
        />
        <ui-tag
          text="Blocked"
          appearance="tint"
          variant="danger"
          [selectable]="true"
          [(selected)]="blockedOnly"
        />
        <ui-tag
          text="Needs review"
          appearance="tint"
          variant="warning"
          [selectable]="true"
          [(selected)]="needsReview"
        />
      </div>

      <div
        style="padding:0.875rem 1rem;border:1px dashed var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background2-rest)"
      >
        <p
          style="margin:0 0 0.5rem;font-size:0.75rem;font-weight:600;letter-spacing:0.06em;text-transform:uppercase;color:var(--color-neutral-foreground2-rest)"
        >
          Active filters
        </p>
        <div style="font-size:0.875rem;line-height:1.5;color:var(--color-neutral-foreground-rest)">
          {{ activeFilters }}
        </div>
      </div>
    </div>
  `,
})
export class TagSelectableFiltersDemoComponent {
  protected assignedToMe = true;
  protected openOnly = false;
  protected blockedOnly = false;
  protected needsReview = true;

  protected get activeFilters(): string {
    const filters = [
      this.assignedToMe ? 'Assigned to me' : null,
      this.openOnly ? 'Open' : null,
      this.blockedOnly ? 'Blocked' : null,
      this.needsReview ? 'Needs review' : null,
    ].filter((value): value is string => !!value);

    return filters.length ? filters.join(', ') : 'No filters selected.';
  }
}
```

## Dismissible tokens
```ts
import { Component } from '@angular/core';
import { TagComponent } from 'ui';

type Token = {
  id: string;
  text: string;
  variant: 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info';
};

@Component({
  selector: 'app-tag-dismissible-demo',
  standalone: true,
  imports: [TagComponent],
  template: `
    <div style="display:flex;flex-direction:column;gap:1rem;width:100%;max-width:44rem">
      <div
        style="display:flex;flex-wrap:wrap;gap:0.75rem;align-items:flex-start;padding:1rem;border:1px solid var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background-rest)"
      >
        @for (token of tokens; track token.id) {
          <ui-tag
            [text]="token.text"
            [variant]="token.variant"
            appearance="filled"
            [dismissible]="true"
            (dismiss)="removeToken(token.id)"
          />
        }
      </div>

      <div
        style="padding:0.875rem 1rem;border:1px dashed var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background2-rest)"
      >
        <p
          style="margin:0 0 0.5rem;font-size:0.75rem;font-weight:600;letter-spacing:0.06em;text-transform:uppercase;color:var(--color-neutral-foreground2-rest)"
        >
          Remaining tokens
        </p>
        <div style="font-size:0.875rem;line-height:1.5;color:var(--color-neutral-foreground-rest)">
          {{ tokens.length ? tokenLabels : 'All tokens removed.' }}
        </div>
      </div>
    </div>
  `,
})
export class TagDismissibleDemoComponent {
  protected tokens: Token[] = [
    { id: 'design', text: 'Design', variant: 'primary' },
    { id: 'frontend', text: 'Frontend', variant: 'info' },
    { id: 'urgent', text: 'Urgent', variant: 'danger' },
    { id: 'approved', text: 'Approved', variant: 'success' },
  ];

  protected get tokenLabels(): string {
    return this.tokens.map(token => token.text).join(', ');
  }

  protected removeToken(id: string): void {
    this.tokens = this.tokens.filter(token => token.id !== id);
  }
}
```

## Metadata panel composition
```ts
import { Component } from '@angular/core';
import { TagComponent } from 'ui';

@Component({
  selector: 'app-tag-workspace-panel-demo',
  standalone: true,
  imports: [TagComponent],
  template: `
    <div
      style="display:flex;flex-direction:column;gap:1rem;width:100%;max-width:44rem;padding:1rem;border:1px solid var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background-rest)"
    >
      <div style="display:flex;flex-direction:column;gap:0.375rem">
        <div style="font-size:1rem;font-weight:600">Project metadata card</div>
        <div
          style="font-size:0.875rem;color:var(--color-neutral-foreground2-rest);line-height:1.45"
        >
          Tags often work best as compact metadata inside a richer surface, not as isolated
          decorative chips.
        </div>
      </div>

      <div style="display:flex;flex-wrap:wrap;gap:0.75rem;align-items:flex-start">
        <ui-tag
          text="Enterprise"
          appearance="filled"
          variant="secondary"
          icon="building_bank_toolbox"
        />
        <ui-tag text="Launch ready" appearance="filled" variant="success" icon="checkmark" />
        <ui-tag text="Security review" appearance="tint" variant="warning" icon="shield" />
        <ui-tag
          text="Tracked"
          secondaryText="JIRA-214"
          appearance="outline"
          variant="info"
          icon="ticket_diagonal"
        />
      </div>

      <div
        style="padding:0.875rem 1rem;border:1px dashed var(--color-neutral-stroke-rest);border-radius:0.875rem;background:var(--color-neutral-background-rest)"
      >
        <div style="font-size:0.9375rem;font-weight:600">Next milestone</div>
        <div
          style="margin-top:0.375rem;font-size:0.875rem;line-height:1.5;color:var(--color-neutral-foreground2-rest)"
        >
          Finalize the review package and confirm launch blockers before the Friday release window.
        </div>
      </div>
    </div>
  `,
})
export class TagWorkspacePanelDemoComponent {}
```

## Accessibility

### Informational vs interactive
Plain informational tags are not focusable by default. When `selectable` is enabled, the tag becomes keyboard-focusable and exposes button-like interaction with `aria-selected`.

### Keyboard
| Key | Action |
| --- | --- |
| Tab | Moves focus to selectable or dismissible tags only. |
| Enter / Space | Toggles a selectable tag. |
| Enter / Space on dismiss button | Removes the tag when dismissible. |

### Dismiss semantics
Dismissible tags render a dedicated button with an accessible label like `Remove Design`. The dismiss button is hidden when the tag is disabled, so users do not encounter an unavailable removal control.
