feat: Next.js (React Server Components) support#469
Open
jaieds wants to merge 6 commits into
Open
Conversation
Mark component entries with "use client" so the directive survives the build into each dist chunk, and expose compound sub-components as named exports so they work in React Server Components without dot access (which does not cross the client boundary). - Add 'use client' to all 43 component entry files (previously only on the barrel, where Rollup flattened it away so no directive reached dist/) - Remove the now-dead 'use client' from src/components/index.ts - Expose named subpart exports (dot-matching aliases) for all 17 compound components (Select, Accordion, Sidebar, RadioButton, Dialog, Drawer, Table, DropdownMenu, SearchBox, Breadcrumb, Pagination, Tabs, Menu, Topbar, HamburgerMenu, Container, ProgressSteps) - Add 'use client' to Drawer sub-part files so the bundler cannot hoist past the client boundary - Guard render-path window access in Sidebar and getOperatingSystem() for SSR safety
Add a "Next.js Usage" MDX doc page for every component (41), nested under each component below its Docs page. Each documents Server Component usage; compound components show the named subpart-export pattern (required in RSC) plus a dot-notation note, backed by a hidden example story that powers an isolated Canvas live preview. - 41 *.nextjs.mdx doc pages (one per component) - 17 *.nextjs.stories.tsx hidden example stories (tags: !dev, !autodocs) - .storybook/main.ts: allow MDX to build under the library vite config (strip lib/externals/output, drop lib-only plugins vite:dts + preserve-directives, normalize the addon-docs mdx-react-shim file:// import); order *.stories before *.mdx so Docs sorts above Next.js Usage
Fix the live previews and make the Next.js docs approachable for all levels. Previews: match each compound example to its main story's layout/sizing; drop docs.story.height (it clipped shadows/dropdowns); wrap Dialog/Drawer Title + CloseButton in flex justify-between so the X sits top-right. Clarity: add a plain-language TL;DR callout to every page; add an 'Event handlers & state' section (the client-component gotcha) to simple + non-stateful-compound pages; add a shared 'Guides / Using force-ui with Next.js' overview (Server vs Client components, install, CSS import, named-export rule with the real errors).
| @@ -1,3 +1,4 @@ | |||
| 'use client'; | |||
There was a problem hiding this comment.
What: The addition of the 'use client' directive is correct, but ensure consistent application across all components that directly interact with client-side functionalities.
Why: The 'use client' directive is necessary for Next.js Server Components to correctly interpret component behavior. This helps to prevent potential rendering issues when components need to access client-specific behavior, such as DOM manipulation or state management.
How: Double-check that this directive is present for all components intended to be rendered as client components. Review all component files to ensure consistency and functionality.
The Select Next.js example story rendered the combobox button with no accessible name, failing the test-runner's axe button-name rule. Add a label (matching the main Select story) so the button has discernible text.
ButtonGroup's default export is a compound object ({ Group, Button }) used via dot notation, which the earlier compound rollout missed (its scan only matched Object.assign and X.Sub = patterns). Dot access fails in Server Components, so expose ButtonGroupContainer (.Group) and ButtonGroupButton (.Button) as named exports, and add its Next.js Usage doc + hidden example story. Completes coverage: every public component now has a Next.js Usage page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Related issue: brainstormforce/surerank#1860
Summary
Adds Next.js (React Server Components) compatibility to force-ui. Components can now be imported and rendered directly inside Server Components in the App Router, and compound components expose named subpart exports so they work across the server/client boundary. Fully backward compatible (existing dot-notation usage in client components is unchanged).
What changed
Core (RSC support)
'use client'directive added to every component entry file so it survives the build into eachdistchunk (previously only on the barrel, where Rollup flattened it away and no directive reacheddist/).SelectButton,DialogPanel,TabsTab,ContainerItem). Dot access (Select.Button) can't cross the RSC boundary; named exports are individual client references.'use client'(they live in separate modules the bundler would otherwise hoist past the client boundary).Sidebarinitial collapsed state andgetOperatingSystem()no longer touchwindowduring render.Storybook docs
<Canvas>preview..storybook/main.tsadjusted so MDX builds under the library Vite config.Changelog
1.8.0entry added.package.jsonversion intentionally left unbumped (to be cut separately).Verification
npm run build(tsc + vite) andbuild-storybookboth pass.dist/components/*/*.{es,cjs}.jsentry chunk leads with"use client".Notes