Skip to content

feat(ui): primitives for the stage-workspace port - #58

Closed
TheGreatAxios wants to merge 5 commits into
mainfrom
cl-8775-scribe-react-ui
Closed

TheGreatAxios wants to merge 5 commits into
mainfrom
cl-8775-scribe-react-ui

Conversation

@TheGreatAxios

Copy link
Copy Markdown
Contributor

Summary

  • SegmentedControl — generic joined-segment control (role=group + aria-pressed) for theme/protocol/density pickers
  • Tabs — icon/marker descriptor slots, and a scrollable variant whose tablist scrolls horizontally with scroll-driven edge fades
  • NotificationsBell — marker="dot" variant for queues where the count is noise but "something is waiting" is not
  • HorizontalStepper — variant="segments", a hairline whisper track for dense chrome where the step name is carried by the surface beneath

All additive: no existing component's default look or API changes, so current consumers are unaffected.

Test plan

  • bun run typecheck
  • bun run lint
  • bun test — 6 new tests; 3 pre-existing Toaster failures unchanged on clean HEAD
  • bun run build — including the contrast gate

A small set of mutually exclusive choices as joined segments — theme,
protocol, density. role=group with aria-pressed toggles rather than a
radiogroup because the choice takes effect immediately. Stateless: the
host owns the value since it usually outlives the component.
Artifact-style strips outgrow their pane; wrapping pushes content down.
The scrollable tablist fades whichever edge still hides tabs, driven by
scroll position and a ResizeObserver on the pane itself. icon carries
the thing's kind, marker a trailing state (live dot, dirty flag).
…ntalStepper

A queue that is either empty or not makes the count noise; marker=dot
keeps 'something is waiting' without it. The segments stepper is the
whisper track — hairline segments, current stretched in accent — for
dense chrome where the step name is carried by the surface beneath.
@TheGreatAxios
TheGreatAxios force-pushed the cl-8775-scribe-react-ui branch from 459b9d0 to 86b172b Compare September 22, 2026 05:24
onSendHold fires on a >=450ms press instead of sending — the heavier
alternative (send back, send-and-…) that shares the button because it is
a send, not a separate action. The click ending a hold is swallowed so
it never sends on release, and a leaked hold cannot eat a later send.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant