proposals/LabeledDivider/decisions.md87 lines · View on GitHub
Decisions: LabeledDivider
Name and scope
Decision:LabeledDivider, net-new (PDS v2 has no divider).
Why: use-case neutral. It covers event logs, runtime/edge logs, threads and agent state markers. StreamDivider, TimelineDivider and EventDivider each fit only some of those.
Port impact: none. If a plain Divider is added later, this can stay as the labeled form.
Time selector is MenuButton, not a new menu
Decision: passing menuItems (plus id) renders the label as a MenuButton (secondary, same size as the divider, agentic border when the tone is not neutral) between the lines. The consumer owns the options and callbacks.
Why: reuse before building. The chevron means a time selector only (designer's answer), so no disclosure mode.
Port impact: depends on the local MenuButton proposal.
Jump to a specific date uses the PDS Datepicker in a Modal
Decision: the optional datePicker prop adds a separator and a last menu item that opens the PDS Modal with a single-date PDS Datepicker. Picking a date calls datePicker.onChange(date) and closes the modal. All text (menu item, modal title, field label) comes from the prop.
Why: designer asked to use the PDS date picker. Datepicker has no inline or controlled-open mode (it is an input with its own dropdown), so it needs a container; the Modal gives one that works with the menu item. The date is picked in two steps (click the field, then a day).
Port impact: uses Modal and Datepicker from the package. A controlled-open or inline Datepicker would make it one step.
Icons are props: prefix and suffix
Decision:prefixIcon and suffixIcon, using the local Icon wrapper. The Default story shows both.
Why: the reference shows an icon on each side of "Text"; designer asked for both. Named by position, not iconName, since there are two.
Port impact: none beyond the Icon wrapper.
Sizes
Decision:size: xs / s (default), named after the type tokens like ThinkingState. Sets the text size, icon size and label padding; the selector's MenuButton gets the same size.
Why: designer asked for XS, S and M, then dropped M as too large.
Port impact: none. Check that the MenuButton height at each size matches the static pill.
Tones
Decision:neutral (default), agentic (AI gradient border, same pattern as agentic Button) and agentic-filled (discovery status fill and border). The designer removed accent and wants both agentic stylings side by side on the Agentic story to choose between; one will be dropped. Lines are the separator color for neutral, the discovery border for agentic-filled and the AI gradient for agentic (each line has the full gradient, not one gradient spanning both).
Why: matches the screenshot; designer confirmed darker lines.
Port impact: none.
Gradient bolt (superseded: the icon is now black, see the last section)
Decision: on the agentic tone, a zappy icon is painted with the AI gradient, using the Spinner's bolt technique (gradient background masked to the bolt shape). Other icons, and agentic-filled, are unchanged.
Why: designer asked for the bolt to match the gradient border and lines.
Port impact: the mask duplicates the Spinner bolt path; the port can share it if the Icon gets a gradient option.
Shimmer on the agentic tone
Decision: the PDS shimmer band (--pds-gradient-ai-shimmer) is an extra background layer on the agentic label border, both lines and the gradient bolt, animated with the package's pds-ai-shimmer-sweep keyframes and --pds-animation-duration-ai-shimmer. Off for reduced motion. The label text does not shimmer, and the time selector's trigger border does not either (it is the agentic Button border).
Why: designer asked. Layers were used instead of the pds-ai-active-shimmer utility, which needs a pseudo-element (an svg icon has none) and would sweep over the text.
Port impact: relies on the package keyframes being loaded.
Accessibility
Decision: the static form is role='separator' with aria-label from label; the visible pill and lines are aria-hidden. The selector form is not a separator, since it is interactive.
Why: a separator is the right landmark for a break in a stream, and the label carries the meaning.
Port impact: none.
Semantic type classes instead of font primitives (2026-10-19)
Decision: The root takes pds-copy-s or pds-copy-xs by size; --labeled-divider-font-size is gone.
Why: The designer asked for semantic tokens over primitives where they exist; the semantic layer for type is the pds-copy-* classes. The classes are !important, so they only go on elements whose own font properties nothing else overrides. A child that sets its own weight (the medium labels in Chain of Thought) still wins, because the !important only beats rules on the same element, not inheritance. Computed sizes match before the change (summary 14px, rows 12px at s; divider 14px / 12px).
Port impact: none beyond the class on the root.
Open questions
Is a modal the right container, or should the calendar open in a popover anchored to the divider (designer)? A time of day (showTime) can be turned on.
Which agentic styling stays: gradient border or discovery fill (designer)? The selector uses the gradient for both.
Is a vertical orientation needed for left-to-right timelines (designer)?
Should the lead icon show on the selector in the neutral tone? It is supported; confirm it looks right.
An action slot to swap the label for any control (2026-10-21)
Decision: a new optional action (ReactNode) replaces the label with any control, centered on the line, for example a "Show more" Button that unfolds more content under the divider. The divider only places it: the screen owns the control, aria-expanded / aria-controls and the content it reveals (the With Action story shows it). When action is set, label, menuItems, prefixIcon and suffixIcon are ignored (label stays required for the other modes), and the root is a plain group, not a separator, since it holds a control. tone still colors the lines either side.
Why: the designer wants the divider's button to be swappable or configurable, such as a "show more" button.
Port impact: adds the action prop and .pds-labeled-divider__action.
Open: should the divider own the unfolding (an isExpandable mode with children revealed under it), or stay a slot? It is a slot for now.
The agentic icon is black, not the gradient (2026-10-21)
Decision: on the agentic tone the zappy icon is the label's plain foreground color (--pds-color-foreground-default), not painted with the AI gradient. The gradient bolt (the mask, the --labeled-divider-bolt-mask variable and the __icon--gradient class) was removed, and the bolt no longer shimmers. The label border and the lines keep the gradient and the shimmer.
Why: the designer's call, after comparing the gradient variant next to the purple.
Port impact: the Divider no longer duplicates the Spinner's bolt mask; one raw value (the mask's fill='black') is gone.
The purple agentic-filled tone is removed (2026-10-21)
Decision: after comparing the gradient agentic tone next to the purple agentic-filled one, the designer kept the gradient and removed the purple. LabeledDividerTone is now neutral or agentic; the discovery-colored CSS block, the story with both stylings and the purple row in the all-variants story are gone. This closes the earlier open question about which agentic styling stays. The earlier notes in this file about agentic-filled are history.
Port impact: one tone fewer; no use of the discovery status tokens in the divider.