# Table Cell

Level: molecule.

## Purpose and use

Render one typed table value or row affordance. Use inside a table row; this cell
sets role=cell and does not provide headers, sticky positioning or row ownership.

## Anatomy, behavior, and accessibility

- Text/number/link share label, optional description, icons and left/right slots.
  Link renders a native anchor; only its text is the link target. None keeps the
  empty cell boundary. Ordinary text can render an optional status Badge below
  its title. Slot projects `[wblTableCellSlot]` content.
- The right icon sits at the cell's end by default (`rightIconPlacement`
  `end`, the library Text cell). `inline` places it right after the title, on
  its first line, 4px (`--space-100`) away — the contact cell of the
  outer-customer applications table (Figma `20295:62639`, A-010). The icon is
  decorative in both placements.
- The description uses `text-icon/primary-gray` (`#5f5f6d`), matching the
  library Text cell `18296:100243` (A-010; it was `text-icon/secondary`).
- The ordinary title (including text, number, and link values) and optional
  description are internally marked for `component.line-clamp-popup`. On
  pointer hover, that Table surface opens only for the individual title or
  description whose rendered box is clipped; it exposes that item's complete
  text and does not change the Table Cell public API.
- Checkbox wraps the small primitive, forwards checked/intermediate/disable and
  emits changes from its padded target. Chevron exposes a named native expand
  button and emits the inverse opened value; the parent owns nested content.
- Badge uses projected badge/dropdown content or a fixed success Badge fallback.
  Overflow tooltip depends on measured truncation; optional hint uses hintLabel.
- Configured actions provide up to three direct buttons. With more than three,
  two remain direct and the rest enter a More dropdown. Disabled actions do not
  emit. Icon-only actions require an icon and retain label-based accessible names
  and tooltips. `tooltipText` supplies richer tooltip copy while `label` remains
  the accessible name and fallback tooltip. Without actions data, three legacy
  action slots/defaults apply.
- `WblTableCellAction.overflow` explicitly assigns an action to the More
  dropdown regardless of the total action count. An explicitly overflowed
  action never renders as a direct button. When a dropdown is needed, at most
  two non-overflow actions remain direct and every other action enters the
  dropdown in its original input order. Omitting `overflow` preserves the
  automatic grouping: up to three direct actions, then two direct and the
  remainder in the dropdown.
- fixed controls boundary treatment, not position. The current names are inverted:
  fixed='right' applies the left separator class; fixed='left' the right one.
  Numeric type affects alignment;
  it does not format numbers. Supply real href values and business-specific labels.

## Open Questions

`disable` only guards checkbox behavior; it does not disable links or chevron.
Default badge/action copy is fixture content. Projected custom controls own their
semantics; tooltip and overflow-menu keyboard behavior need the relevant child
contracts rather than assumptions from cell type.

Figma exposes `lFixed`/`rFixed` visual states, but the current local API maps
`fixed='left'` to `wbl-table-cell--fixed-right` and `fixed='right'` to
`wbl-table-cell--fixed-left`. The evidence does not establish whether their
semantic directions match, so this remains an Angular reconciliation question.

## Figma reconciliation

Direct read-only evidence came from [the Table Cell section](https://www.figma.com/design/EO9tuCsqwuHL8cZ4Eb2psR/?node-id=18719-17951).
The inspected root `18719:17951` is a Figma `SECTION`, not a published parent
component set. It contains separate published cell targets, while the local
runtime intentionally exposes one `wbl-table-cell` API with a `type` union.
This is a translation boundary, not evidence for a one-to-one parent Figma
component or a second Angular API.

| Verified Figma target                                                 | Local `type` | Reconciled boundary                                                               |
| --------------------------------------------------------------------- | ------------ | --------------------------------------------------------------------------------- |
| Text `18296:100243`                                                   | `text`       | Plain text; optional description, icons, slots, and fixed treatment.              |
| Link `18296:101879` (`18296:100255` Accent; `18296:100263` Secondary) | `link`       | Native link content with the two verified visual treatments.                      |
| Number `18296:100271`                                                 | `number`     | Quantitative content; locally right aligned.                                      |
| Actions `18296:100281`                                                | `actions`    | Nested action controls; the concrete commands remain table/screen-owned.          |
| Badge `18296:100293`                                                  | `badge`      | Retains a nested Badge `S`; the hint is optional.                                 |
| Slot `18296:100301`                                                   | `slot`       | Consumer-projected custom content when no narrower type fits.                     |
| Checkbox `18296:100305`                                               | `checkbox`   | Retains a nested Checkbox `S`; the enclosing table owns row selection.            |
| Chevron `18297:102095` (`18296:100309` closed; `18296:100313` open)   | `chevron`    | The `opened` state is the row-expansion affordance; expanded content is external. |
| None `18297:103831`                                                   | `none`       | Intentionally empty structural cell, not a missing-value convention.              |

The reference family uses a `48px` minimum cell height, `16px` block and
`12px` inline padding, `8px` content gap, `13/16` primary text, `11/14`
primary-gray description, and a secondary-stroke separator for fixed cells. These
are visual evidence only; the runtime must consume owned semantic tokens.

### Figma ownership decision

Do not create `table-cell.figma.md` and keep this inventory entry's
`figmaSidecar` as `null`: the verified root is a section and has no parent
component key to satisfy a `figma-assembly.v2` contract. The separately owned
`Table Cell/*` atom sidecars retain the verified component keys, dependencies,
and assembly predicates for their published Figma targets.

### M-002 screen evidence

The read-only screen evidence in Figma file `uGBDiLA947AJwkuvpohikQ`, node
`16970:22753`, shows a `40px` action cell with one `more-vert` trigger. The
screen requires the commands «Редактировать» and «Удалить» inside that dropdown.
This confirms the need for explicit overflow placement even when there are only
two actions. The cell width, command copy, command results, and delete/remove
semantics remain screen-owned and do not become Table Cell defaults.
The current Transport Requests composition uses a 68px action column in every
tab so its optional direct Comment button and More trigger fit together.

### M-002 tab-specific row actions

Transport Requests owns the concrete action arrays for these read-only
Figma states:

- [«Новые», `17034:21028`](https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17034-21028);
- [«В работе», `17065:58399`](https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17065-58399);
- [«Ожидают оплаты», `17065:77752`](https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17065-77752).

Transport Requests sends its text menu commands with `overflow: true`.
«Предварительные» supplies Edit and Delete; «Архивные» is read-only and supplies
View details. New, In progress and Awaiting payment commands vary by role and
status and may also supply one direct icon-only Comment action for a row with a
comment; their exact current matrix remains screen-owned in
[`transport-requests.md`](../../screens/transport-requests.md).

Table Cell retains its existing direct/overflow rendering and emits the supplied
action object. It forwards `separatorBefore` from an overflow action to the
corresponding Dropdown item; the field has no effect on direct action buttons.
Labels, order, availability and command results remain screen-owned defaults.

## Local component contract

This is the active owned contract for `component.table-cell`. The API below
is verified against the current local implementation, focused test and story.
The Source commit `0112cba0779a2d2a4b6c7a17243201694344d70a` remains
migration provenance, not the runtime owner.

M-002 adds the optional `WblTableCellAction.overflow` and `tooltipText` fields and
the ordinary-text status inputs below. They are implemented in the local
component and covered by focused tests and Storybook controls.

### Classes and selectors

- `WblTableCellAction1Directive` — `[wblTableCellAction1]` (src/app/design-system/patterns/table-cell/table-cell.component.ts).
- `WblTableCellAction2Directive` — `[wblTableCellAction2]` (src/app/design-system/patterns/table-cell/table-cell.component.ts).
- `WblTableCellAction3Directive` — `[wblTableCellAction3]` (src/app/design-system/patterns/table-cell/table-cell.component.ts).
- `WblTableCellComponent` — `wbl-table-cell` (src/app/design-system/patterns/table-cell/table-cell.component.ts).

### Inputs

- `WblTableCellComponent.type = input<WblTableCellType>('text')`
- `WblTableCellComponent.fixed = input<WblTableCellFixed>('none')`
- `WblTableCellComponent.link = input<WblTableCellLink>('accent')`
- `WblTableCellComponent.alignment = input<WblTableCellAlignment>('left')`
- `WblTableCellComponent.href = input('#')`
- `WblTableCellComponent.leftSlot = input(false)`
- `WblTableCellComponent.leftIcon = input(false)`
- `WblTableCellComponent.leftIconName = input<WblIconName>('sparkle')`
- `WblTableCellComponent.text = input('Text')`
- `WblTableCellComponent.description = input(false)`
- `WblTableCellComponent.descriptionText = input('Description')`
- `WblTableCellComponent.rightIcon = input(false)`
- `WblTableCellComponent.rightIconName = input<WblIconName>('sparkle')`
- `WblTableCellComponent.rightIconPlacement = input<WblTableCellRightIconPlacement>('end')`
- `WblTableCellComponent.rightSlot = input(false)`
- `WblTableCellComponent.hint = input(false)`
- `WblTableCellComponent.hintLabel = input('Информация')`
- `WblTableCellComponent.badgeText = input('')`
- `WblTableCellComponent.badgeAppearance = input<WblBadgeAppearance>('success')`
- `WblTableCellComponent.checked = input(false)`
- `WblTableCellComponent.intermediate = input(false)`
- `WblTableCellComponent.disable = input(false)`
- `WblTableCellComponent.checkboxLabel = input('Выбрать строку')`
- `WblTableCellComponent.opened = input(false)`
- `WblTableCellComponent.expandLabel = input('Развернуть вложенные строки')`
- `WblTableCellComponent.collapseLabel = input('Свернуть вложенные строки')`
- `WblTableCellComponent.action1 = input(true)`
- `WblTableCellComponent.action1Variant = input<WblTableCellActionButtonVariant>('primary')`
- `WblTableCellComponent.action2 = input(true)`
- `WblTableCellComponent.action2Variant = input<WblTableCellActionButtonVariant>('secondary')`
- `WblTableCellComponent.action3 = input(true)`
- `WblTableCellComponent.action3Variant = input<WblTableCellActionButtonVariant>('flat-primary')`
- `WblTableCellComponent.actions = input<WblTableCellAction[]>([])`
- `WblTableCellComponent.moreActionLabel = input('Ещё действия')`

### Public types and allowed values

```ts
type WblTableCellType =
  | 'none'
  | 'text'
  | 'number'
  | 'link'
  | 'badge'
  | 'checkbox'
  | 'chevron'
  | 'slot'
  | 'actions';
type WblTableCellFixed = 'none' | 'left' | 'right';
type WblTableCellLink = 'accent' | 'secondary';
type WblTableCellAlignment = 'left' | 'right';
type WblTableCellRightIconPlacement = 'end' | 'inline';
type WblTableCellActionButtonVariant = WblButtonVariant | `flat-${WblButtonFlatVariant}`;
type WblTableCellAction = {
  id: string;
  label: string;
  variant?: WblTableCellActionButtonVariant;
  iconName?: WblIconName;
  showLabel?: boolean;
  /** Optional visible tooltip copy; label remains the accessible name. */
  tooltipText?: string;
  disabled?: boolean;
  /** Keep this action in the More dropdown. */
  overflow?: boolean;
  /** Show a dropdown separator immediately before this overflow action. */
  separatorBefore?: boolean;
};
type WblButtonVariant = 'primary' | 'secondary' | 'danger' | 'inverted';
type WblButtonFlatVariant = 'primary' | 'secondary' | 'warning' | 'success' | 'danger';
type WblBadgeAppearance =
  | 'default'
  | 'red'
  | 'orange'
  | 'green'
  | 'success'
  | 'warning'
  | 'error'
  | 'clear'
  | 'disabled'
  | 'info';
```

Icon-name inputs use `WblIconName` from the [shared icon contract](../atoms/icon.md);
choose a key present in the owned icon pack, not an arbitrary external icon name.

### Models

- None.

### Outputs

- `WblTableCellComponent.checkedChange = output<boolean>()`
- `WblTableCellComponent.openedChange = output<boolean>()`
- `WblTableCellComponent.actionSelect = output<WblTableCellAction>()`

### Slots and projection markers

- `WblTableCellComponent: <ng-content select="[wblTableCellBadge], wbl-badge, wbl-dropdown">`
- `WblTableCellComponent: <ng-content select="[wblTableCellSlot]">`
- `WblTableCellComponent: <ng-content select="[wblTableCellAction1]">`
- `WblTableCellComponent: <ng-content select="[wblTableCellAction2]">`
- `WblTableCellComponent: <ng-content select="[wblTableCellAction3]">`
- `WblTableCellComponent: <ng-content select="[wblTableCellLeftSlot]">`
- `WblTableCellComponent: <ng-content select="[wblTableCellRightSlot]">`
- The implementation applies `[wblLineClampContent]` to ordinary title/link and
  description nodes. It is an internal Line Clamp integration marker, not a
  Table Cell consumer projection marker.

### Local evidence

- Code: `src/app/design-system/patterns/table-cell/table-cell.component.ts`.
- Focused test: `src/app/design-system/patterns/table-cell/table-cell.component.spec.ts`.
- Public export: `export * from './patterns/table-cell/table-cell.component';` in `src/app/design-system/index.ts`.
- Storybook: `storybook/stories/table-cell.stories.ts` (`Design System/Patterns/wbl-table-cell`).

The M-002 implementation groups configured actions before rendering. Two actions
marked `overflow: true` produce one `more-vert` trigger and no direct action
buttons; selecting a dropdown item emits the original `WblTableCellAction`.
Existing focused coverage retains the automatic grouping for more than three
unmarked actions and disabled-item behavior. The updated Storybook action matrix
contains the explicit two-item overflow case used by Transport Requests.

`separatorBefore` is copied to the matching `WblDropdownItem` when an overflow
menu is built. Focused coverage verifies the forwarded separator, and the Table
Cell action story exposes the separated overflow group. Omitting the field keeps
the existing unseparated menu order.

When `badgeText` is non-empty on an ordinary text/number/link cell, Table Cell
renders a size-S Badge beneath the main text with `badgeAppearance`. Empty
`badgeText` renders no status badge. Transport Requests uses this API beneath ID
for non-preliminary tab statuses. Focused coverage and the Table Cell text
controls are current evidence.

A-010 adds `rightIconPlacement` (`end` default, `inline` after the title with a
4px gap) and switches the description colour to primary-gray. Focused coverage
checks both placements; the Table Cell story exposes the control and an
«Inline right icon» example.

M-002 verification includes focused Table Cell unit coverage together with the
application build, Storybook build, design-system check, and Memory check.

## M-002 action alignment and fixture content

Action cells align their action group to the inline end, use `--space-200` (8px)
inline padding and `--space-100` (4px) gap while retaining accessible names and
24px controls. One action remains at the right edge; two controls fit the 68px
cell as `24 + 4 + 24 + 16 = 68px`. Existing direct/overflow grouping remains
unchanged.

Transport Requests may supply Comment per row only in New, In progress and
Awaiting payment through the existing `WblTableCellAction` model:
`{ id: 'comment', label: 'Комментарий', variant: 'flat-primary',
iconName: 'message-lines', showLabel: false, tooltipText: <полный текст> }`. It
renders as a direct icon-only action; Tooltip shows `tooltipText` on hover/focus,
falls back to `label` when the field is absent, and keeps `label` as its
accessible name. It is not part of the More dropdown. Fixtures include different
long comments and rows without Comment. Its availability and result are
screen-owned. In every
extended tab, `Детали` uses primary
`Груз: {cargo} · Расстояние: {distance}` and description `Ставка: {rate}`; a
Commercial row appends ` · Грузовладелец: {cargoOwner}` to that description.
`Норматив` uses primary `Время: {duration}` and description
`Тип маршрута: {routeType}`. These labels use the existing
`text`/`description`/`descriptionText` composition and define no new Table Cell
input or output.

## A-011 styling hooks for Table cards

Table Cell reads three optional CSS custom properties from its container:
`--wbl-table-cell-padding-block`, `--wbl-table-cell-padding-inline`, and
`--wbl-table-cell-min-block-size`. When unset, every cell type keeps its current
padding and 48px minimum height. Table's adaptive card layout sets them to `0`
so a cell can sit inside a card field. The public Angular API is unchanged.

## Provenance

The archived source-document copy is historical evidence only. The active
resolver is local code/test/export and the exact Storybook story above, with
the direct Figma evidence recorded in this reconciliation.
