Skip to content

Call parts: ControlButton, ParticipantTile, FloatingDock, IncomingCallCard, BottomSheet, Slider export - #147

Merged
prakashUXtech merged 10 commits into
mainfrom
feat/call-parts
Sep 30, 2026
Merged

prakashUXtech merged 10 commits into
mainfrom
feat/call-parts

Conversation

@prakashUXtech

Copy link
Copy Markdown
Contributor

Adds the parts paw-enterprise needs to build its three call layouts (Glass, Focus, Classic). Every part is a new ./ui-only export, so the spec registry and the manifest don't change (still 189 widgets). No media and no LiveKit in ripple: the tile takes the host's <video> through a snippet.

Export (@ripple-ui/svelte/ui) What it does Props
ControlButton one call control, native <button>, forwards every attribute variant pill / bar / classic, tone default / danger / accent, size default / compact, pressed (aria-pressed), wide (hang-up), label (text beside the icon, bar only, hidden under 640px), icon snippet, count / mention / badgeTestId
ControlBar the row the buttons sit in, role=group label, variant pill / bar / classic, size default / compact
CountBadge count pill: N, 99+ over 99, @ for a mention, nothing at 0 count, mention, max, any span attribute (keeps host test ids)
ParticipantTile one person: video slot, ripple Avatar fallback, name pill, mic-off, speaking state name, src, speaking, muted, skin glass / focus / classic, size lg / md / sm / orb; snippets video, avatar, badge, menu
FloatingDock draggable container: pointer capture, ignores drags that start on controls, snaps to the nearer side, clamps on drop and on window resize label, corner, bounds window / parent, gap, onPositionChange
IncomingCallCard incoming / joinable / rejoin card with a pulsing halo (Tailwind's animate-ping, motion-safe) title, subtitle, name, src, role (alert by default), halo; snippets avatar, primary, secondary
BottomSheet non-modal sheet with peek / half / full stops. Drag the handle past 48px to move a stop, under 6px counts as a tap. Enter/Space toggle, arrow keys step. Content stays mounted stop (bindable, mirrored to data-state), onStopChange, label, handleLabel(stop), handleTestId
Slider the existing shadcn slider, now exported as a namespace (Slider.Root) bits-ui props

The primitives Button (@ripple-ui/svelte/primitives) also gets a success variant for Accept and Join.

Colours are ripple tokens only. Accent text on glass reads --ripple-accent-on-glass if the host defines it and falls back to --ripple-accent. Sizes live in scoped CSS, so a Tailwind w-* class won't resize a ControlButton. Use wide for that.

Tests

widgets/call/call.test.ts has 26 behaviour tests, committed red first. The ./ui contract test now mounts every new export standalone and lists Slider as a namespace. The full svelte suite passes (1471 tests). bun run check: 0 errors, 0 warnings. bun run lint: clean apart from the usual test-file assertion warnings. Root bun run build passes and the manifest is unchanged. /showcase/call shows every part in all three layouts. I clicked through it in a browser: layout switch, speaker ring per skin, bar labels, wide hang-up, sheet stops, halo animation.

Not verified

  • The dock drag was only tested in jsdom with stubbed rects. Nobody has dragged it by hand yet.
  • The 640px label hide and the glass blur in paw-enterprise's light theme under its glass pin haven't been checked. That happens when PE consumes these parts.
  • One Qr security test failed once in a full run and passed on rerun, and it passes alone on both this branch and main. I think it's a flake and not caused by this PR.

@prakashUXtech
prakashUXtech merged commit 4aa1290 into main Sep 30, 2026
1 check passed
@prakashUXtech
prakashUXtech deleted the feat/call-parts branch September 30, 2026 15:49
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