Level: molecule.
Purpose and use
Label a table column, request a sort change, or expose the table's select-all checkbox. Use the checkbox variant only for row selection. Sorting and selected row state remain controlled by the enclosing table; this component does not reorder records or calculate aggregate selection. Use a regular heading for content outside a table.
Anatomy, behavior, and accessibility
- A
columnheadercontains either a text label with optional decorative info/sort icons, or the small Checkbox primitive. A sortable icon is wrapped by the shared Tooltip with text «Сортировать». There are no projected content slots. - A sortable text header uses a native button with a visible keyboard focus
outline.
aria-sortreflects the supplied direction. Activating the button requestsnone → ascending → descending → ascending; the parent must write the emitted direction back. No click returns tonone. - The checkbox receives checked, intermediate, disabled and accessible-label
values. Disabled checkbox changes are ignored.
checkboxLabelnames the checkbox;ariaLabel(falling back tolabel) names its header container. - Labels stay on one line with ellipsis. Hovering an overflowing label opens a tooltip with the full label; leaving closes it. Prefer short, distinct column names. The info icon is decorative and has no help interaction.
- Right alignment moves the sort icon before the label. Every header owns its
bottom separator.
sticky='left'adds the inline-end separator andsticky='right'adds the inline-start separator; positioning and sticky offsets belong to Table.
Open Questions
disabledcurrently affects the checkbox only; the sortable button remains active. A disabled sorting state needs a separate Angular change if required.- Overflow tooltips are mouse-triggered and are not linked with
aria-describedby; keyboard-triggered overflow help is not implemented.
Local component contract
This is the active owned contract for component.table-header. The API below
is verified against the current local implementation, focused test and story.
The Source commit remains migration provenance, not the runtime owner.
Classes and selectors
WblTableHeaderComponent—wbl-table-header(src/app/design-system/patterns/table-header/table-header.component.ts).
Inputs
WblTableHeaderComponent.alignment = input<WblTableHeaderAlignment>('left')WblTableHeaderComponent.variant = input<WblTableHeaderVariant>('text')WblTableHeaderComponent.label = input('Text')WblTableHeaderComponent.sticky = input<WblTableHeaderSticky>('none')WblTableHeaderComponent.infoIcon = input(false)WblTableHeaderComponent.sortable = input(false)WblTableHeaderComponent.sortDirection = input<WblTableHeaderSortDirection>('none')WblTableHeaderComponent.checked = input(false)WblTableHeaderComponent.intermediate = input(false)WblTableHeaderComponent.disabled = input(false)WblTableHeaderComponent.ariaLabel = input('')WblTableHeaderComponent.checkboxLabel = input('Выбрать все строки')
Public types and values
WblTableHeaderAlignment:'left' | 'right'.WblTableHeaderVariant:'text' | 'checkbox'.WblTableHeaderSticky:'none' | 'left' | 'right'.WblTableHeaderSortDirection:'none' | 'ascending' | 'descending'.
Models
- None.
Outputs
WblTableHeaderComponent.sortChange = output<WblTableHeaderSortDirection>()WblTableHeaderComponent.checkedChange = output<boolean>()
Slots and projection markers
- The exact template has no Angular content-projection slot.
Local evidence
- Code:
src/app/design-system/patterns/table-header/table-header.component.ts. - Focused test:
src/app/design-system/patterns/table-header/table-header.component.spec.ts. - Public export:
export * from './patterns/table-header/table-header.component';insrc/app/design-system/index.ts. - Storybook:
storybook/stories/table-header.stories.ts(Design System/Patterns/wbl-table-header).
Figma source and verified mapping
- Published component set: Table Header —
3395:383238, key825907d7b24368ae1024ab36f267b5bdf063f77a. - Verified in
D-021(GitLab Issue). - Reusable Figma construction is owned by
table-header.figma.md. Its stablecomponent.table-headeridentity and molecule taxonomy match this contract. - The owner key and exposed properties were rechecked read-only on 2026-09-05 during D-025.
The published set has 15 variants: text headers use every combination of
Alignment=Left|Right, State=Default|Hover, and Sticky=No|Left|Right;
selection headers use Alignment=Left, State=Checkbox, and each Sticky
side. Text cells are 256px wide, checkbox cells are 40px wide, and every
variant is 40px high.
Verified property mapping
- Figma
Alignmentmaps toalignment. - Figma
State=Checkboxmaps tovariant='checkbox'; text is the default local variant. FigmaState=Hoveris represented by runtime CSS hover, not a public Angular input. - Figma
Sortmaps tosortableandsortDirection. The local contract also emitssortChangefor accessible interactive sorting. - Figma
Sticky=No|Left|Rightmaps tosticky='none'|'left'|'right'for edge separators. The enclosing Table owns sticky positioning, offsets and boundary selection. Its column-levelfixedColumnremains a composition setting; the standalone Header no longer exposes the formerfixedColumnseparator flag.
Figma uses 12px horizontal padding and a 4px content gap, level-2 surface
#F6F6F9, secondary separator #E0E0EB, and primary-gray text/icon
#5F5F6D. Its source typography is Google Sans Regular 11px/14px; runtime
uses the owned caption role with matching metrics because Google Sans is not a
runtime font asset.
Resolved implementation gap
The original D-025 review observed that the standalone header lacked the
published bottom separator while Table supplied it. The current main
implementation resolves this: table-header.component.scss owns the bottom
border and both sticky-side borders, and table.component.scss no longer adds
the duplicate header border. The earlier proposal to move that separator is
therefore resolved, not pending Angular work. This source review does not claim
an additional visual screenshot verification.
Documentation migration
D-025 preserves the molecule sibling and inventory link as the canonical assembly owner. The verified property mapping above reflects the current API. Historical run paths and digests were not rewritten.
Provenance
Historical Source commit: 0112cba0779a2d2a4b6c7a17243201694344d70a.
Current ownership remains the local contract above.
The archived source-document copy is historical evidence only. The active resolver is local code/test/export and the exact Storybook story above.
M-002 refinement
Every sortable text header exposes the shared Tooltip with the fixed Russian
copy «Сортировать» on pointer hover and keyboard focus of the sort button. The
tooltip is supplemental to the column label and aria-sort; it does not replace
the button's accessible name or change the sort cycle. This current behavior is
aligned with Table UI Kit node
9036:58781.
M-002 Transport Requests sorting
The four non-preliminary Transport Requests tabs expose sorting on ID,
creation date and vehicle-submission date. Table Header continues to own the
interactive column button, aria-sort, Tooltip and direction cycle; Table and
the screen own numeric/date comparison and ordered rows. Creation date starts
descending. No new Header input or output was added for this screen refinement.
M-002 sort icon motion
The sort control always reserves its layout space. In the unsorted idle state it
is visually hidden at opacity: 0 and scale(0.9); header hover or a sorted
state reveals it at opacity: 1 and scale(1) over --duration-fast with
--ease-standard. The arrow-up icon rotates 180 degrees for descending order
with the same duration and easing. These decorative transitions do not delay
sortChange, aria-sort, focus or the controlled direction update and are
disabled by prefers-reduced-motion: reduce. No public Header API is added.