Skip to content

feat(ui): export the primitives as @flowdrop/flowdrop/ui - #60

Closed
stmh wants to merge 3 commits into
mainfrom
feat/ui-export
Closed

stmh wants to merge 3 commits into
mainfrom
feat/ui-export

Conversation

@stmh

@stmh stmh commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

What

A new package entry, @flowdrop/flowdrop/ui (src/lib/ui/index.ts), re-exports the editor's design-system components:

  • Primitives: Button, Card, Checkbox, Chip, Combobox, Composer, EmptyState, Field, IconButton, Menu, Notice, PanelHeader, Segmented, Select, StatusPill, Switch, Tabs, Toolbar, ToolbarSeparator
  • Surfaces: SurfaceOverlay, TabbedSurface
  • Text controls: Input, Textarea
  • Skin: graphiteSkin and skinCss(skin, selector = ':root'), so a host can give its own pages the Graphite tokens: light on :root, dark under data-theme="dark". buildScopedSkinCss now calls the same builder.

The ./ui entry is added to package.json exports in the same shape as ./display. The README entry table lists it. The components' "Not exported from the package" doc lines now point at the entry.

Why

flowdrop-rs is rebuilding its admin UI on the editor's components and --fd-* tokens, so that the editor and the admin pages look like one app. The entry is documented as semver-stable, so a breaking prop change is a major release. Components that don't exist yet are staged in the host under the same primitive contract and upstreamed one at a time.

Tests

  • tests/unit/ui/uiEntry.test.ts imports the entry, checks that each name is a component, and checks that nothing else is exported, and that skinCss(graphiteSkin) targets :root. scopedSkinCss.test.ts covers skinCss with the default and a custom selector.
  • Unit: 3642 passed. svelte-check: 0 errors, 0 warnings. prepack (svelte-package, check-dts, publint): all good, and dist/ui/index.{js,d.ts} is emitted.

CHANGELOG: Unreleased / Added.

https://claude.ai/code/session_01XR2k7eeSeAKTuptqh4uyee

postcss-html 2.0.0 (via the stylelint toolchain) requires Node ^22.12 or
>=24, so pnpm install fails with ERR_PNPM_UNSUPPORTED_ENGINE on Node 20
and every lint, bundle and storybook job is red, on main and on every PR.
The Dockerfiles already build on node:22. The package's engines field
stays >=20: the requirement is a dev-toolchain one.

Claude-Session: https://claude.ai/code/session_01XR2k7eeSeAKTuptqh4uyee
@stmh

stmh commented Oct 23, 2026

Copy link
Copy Markdown
Collaborator Author

Rebased onto #61 (CI on Node 22), which fixes the ERR_PNPM_UNSUPPORTED_ENGINE failures this PR showed. The diff shrinks back to this PR's own commit once #61 merges.

https://claude.ai/code/session_01XR2k7eeSeAKTuptqh4uyee

stmh added 2 commits October 23, 2026 23:29
…schemas

- Storybook: ubuntu-latest is now 26.04, where Playwright cannot install
  Chromium. Pin ubuntu-24.04.
- oasdiff's install script now installs to /usr/local/bin itself; the
  following mv found nothing and failed the job.
- OpenAPI lint: nullable needs a sibling type (struct rule). The two
  allOf + nullable properties on PlaygroundChatBinding and
  WorkflowPlayground gain type: object.

Claude-Session: https://claude.ai/code/session_01XR2k7eeSeAKTuptqh4uyee
d34dman added a commit that referenced this pull request Oct 23, 2026
# Conflicts:
#	libs/flowdrop/CHANGELOG.md
@d34dman

d34dman commented Oct 23, 2026

Copy link
Copy Markdown
Collaborator

Released in @flowdrop/flowdrop 2.16.0 (tag 2.16.0), so I'm closing this PR. Your commit 5c37d95 landed on main before your rebase onto #61, which is why GitHub doesn't show it as merged. Thanks!

What shipped: @flowdrop/flowdrop/ui with every component from the PR:

  • Primitives: Button, Card, Checkbox, Chip, Combobox, Composer, EmptyState, Field, IconButton, Menu, Notice, PanelHeader, Segmented, Select, StatusPill, Switch, Tabs, Toolbar, ToolbarSeparator
  • Surfaces: SurfaceOverlay, TabbedSurface
  • Text controls: Input, Textarea
  • Skin: graphiteSkin and skinCss(skin, selector = ':root')

Different from the PR

  1. The entry is experimental in 2.x, not semver-stable. Names and props may still change in a minor release while the design system settles, and every change will be in the CHANGELOG. It becomes stable no later than 3.0. Pin a minor version (~2.16.0) in flowdrop-rs. The README's entry table marks it that way. @flowdrop/flowdrop/webmcp got the same label in this release.

  2. More exports: tabId and tabPanelId (the ids Tabs documents for its panels), and the prop types MenuItem, MenuEntry, MenuGroup, MenuSeparator, SegmentedOption, SelectOption, StatusPillStatus, SurfaceTab, TabItem and FlowDropSkin. uiEntry.test.ts imports each of them.

  3. skinCss selector: pass one compound selector such as :root, .app or .flowdrop-scope. It is doubled for specificity, so a selector list (a, b) or a descendant selector (.a .b) does not work. Dark mode is data-theme="dark" on the element the selector matches.

  4. Using the components on a host page: base.css (which loads tokens.css) styles only .flowdrop-root, .flowdrop-scope and .flowdrop-portal, so wrap host content in a .flowdrop-scope element and set data-theme on it:

    <div class="flowdrop-scope" data-theme="light">
      <Card><Button variant="primary">Save</Button></Card>
    </div>

    To keep the Graphite look inside the wrapper only, add skinCss(graphiteSkin, '.flowdrop-scope') as a stylesheet. The default :root restyles the whole page.

  5. Overlays keep the host's skin. A SurfaceOverlay is moved to <body>. Inside a .flowdrop-scope wrapper it now takes the flowdrop-scope class with it (so the wrapper's skin rules still apply) and follows the wrapper's data-theme, including later changes. Without data-theme on the wrapper it follows the editor's stored theme setting, which may not match your page, hence the advice in 4.

  6. Built-in strings (labels, placeholders) are English and follow setMessages from @flowdrop/flowdrop/core when it is called in an ancestor component.

The check:bundle gate now has a ui contract, so no heavy dependency (CodeMirror, xyflow, marked, DOMPurify, diff) can slip into the entry. CHANGELOG 2.16.0

@d34dman d34dman closed this Oct 23, 2026
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.

2 participants