-
Notifications
You must be signed in to change notification settings - Fork 2.9k
feat(react-base-components): add a new package to export Fluent UI base state hooks and render functions #35931
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
dmytrokirpa
wants to merge
14
commits into
microsoft:master
Choose a base branch
from
dmytrokirpa:feat/export-base-hooks-from-suite
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
bfa4a03
feat(react-base-components): introduce new package for creating base …
dmytrokirpa d8a971e
base components stories and update types for components
dmytrokirpa 7913660
add missing packages to package.json
dmytrokirpa a49da44
fixup
dmytrokirpa 03bd4d0
fixup
dmytrokirpa e3b3b68
change
dmytrokirpa 8ced617
add base components to public-docsite-v9
dmytrokirpa e9b6f9f
update docs
dmytrokirpa ff41b04
Merge branch 'master' into feat/export-base-hooks-from-suite
dmytrokirpa a80aec7
update
dmytrokirpa 0e73c15
switch to css
dmytrokirpa 02d014f
add more components
dmytrokirpa a196fe8
change
dmytrokirpa 124cb9d
update api snapshot
dmytrokirpa File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
7 changes: 7 additions & 0 deletions
7
change/@fluentui-react-base-components-e353fbc0-1423-4a34-ba93-1d47bf2afae3.json
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| { | ||
| "type": "minor", | ||
| "comment": "feat: introduce new package for creating base components", | ||
| "packageName": "@fluentui/react-base-components", | ||
| "email": "dmytrokirpa@microsoft.com", | ||
| "dependentChangeType": "patch" | ||
| } |
7 changes: 7 additions & 0 deletions
7
change/@fluentui-react-breadcrumb-59f990c7-d36b-4b22-b659-4152e463b83e.json
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| { | ||
| "type": "patch", | ||
| "comment": "fix: update types for render function", | ||
| "packageName": "@fluentui/react-breadcrumb", | ||
| "email": "dmytrokirpa@microsoft.com", | ||
| "dependentChangeType": "patch" | ||
| } |
7 changes: 7 additions & 0 deletions
7
change/@fluentui-react-button-6561155a-5cdf-4b9a-ae91-69fa32f9650d.json
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| { | ||
| "type": "patch", | ||
| "comment": "fix: update types for render function", | ||
| "packageName": "@fluentui/react-button", | ||
| "email": "dmytrokirpa@microsoft.com", | ||
| "dependentChangeType": "patch" | ||
| } |
7 changes: 7 additions & 0 deletions
7
change/@fluentui-react-field-90597e60-8f13-4477-b049-1f63aaf11da4.json
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| { | ||
| "type": "patch", | ||
| "comment": "fix: add missing base hook export", | ||
| "packageName": "@fluentui/react-field", | ||
| "email": "dmytrokirpa@microsoft.com", | ||
| "dependentChangeType": "patch" | ||
| } |
7 changes: 7 additions & 0 deletions
7
change/@fluentui-react-rating-49b1cc95-f0a0-4864-bf2f-e7087f636601.json
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| { | ||
| "type": "patch", | ||
| "comment": "fix: add mising base hook export", | ||
| "packageName": "@fluentui/react-rating", | ||
| "email": "dmytrokirpa@microsoft.com", | ||
| "dependentChangeType": "patch" | ||
| } |
7 changes: 7 additions & 0 deletions
7
change/@fluentui-react-skeleton-8eae8004-fa9d-4754-bc51-fd06d5eb2c06.json
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| { | ||
| "type": "patch", | ||
| "comment": "fix: update types for render function", | ||
| "packageName": "@fluentui/react-skeleton", | ||
| "email": "dmytrokirpa@microsoft.com", | ||
| "dependentChangeType": "patch" | ||
| } |
7 changes: 7 additions & 0 deletions
7
change/@fluentui-react-textarea-13fe61b7-e8e0-479f-87f7-566a49be4b26.json
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| { | ||
| "type": "patch", | ||
| "comment": "fix: update types for render function", | ||
| "packageName": "@fluentui/react-textarea", | ||
| "email": "dmytrokirpa@microsoft.com", | ||
| "dependentChangeType": "patch" | ||
| } |
4 changes: 4 additions & 0 deletions
4
packages/react-components/react-base-components/library/.babelrc.json
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| { | ||
| "extends": "../../../../.babelrc-v9.json", | ||
| "plugins": ["annotate-pure-calls", "@babel/transform-react-pure-annotations"] | ||
| } |
30 changes: 30 additions & 0 deletions
30
packages/react-components/react-base-components/library/.swcrc
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| { | ||
| "$schema": "https://json.schemastore.org/swcrc", | ||
| "exclude": [ | ||
| "/testing", | ||
| "/**/*.cy.ts", | ||
| "/**/*.cy.tsx", | ||
| "/**/*.spec.ts", | ||
| "/**/*.spec.tsx", | ||
| "/**/*.test.ts", | ||
| "/**/*.test.tsx" | ||
| ], | ||
| "jsc": { | ||
| "parser": { | ||
| "syntax": "typescript", | ||
| "tsx": true, | ||
| "decorators": false, | ||
| "dynamicImport": false | ||
| }, | ||
| "externalHelpers": true, | ||
| "transform": { | ||
| "react": { | ||
| "runtime": "classic", | ||
| "useSpread": true | ||
| } | ||
| }, | ||
| "target": "es2019" | ||
| }, | ||
| "minify": false, | ||
| "sourceMaps": true | ||
| } |
15 changes: 15 additions & 0 deletions
15
packages/react-components/react-base-components/library/LICENSE
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| @fluentui/react-base-components | ||
|
|
||
| Copyright (c) Microsoft Corporation | ||
|
|
||
| All rights reserved. | ||
|
|
||
| MIT License | ||
|
|
||
| Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
|
|
||
| The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | ||
|
|
||
| THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
|
|
||
| Note: Usage of the fonts and icons referenced in Fluent UI React is subject to the terms listed at https://aka.ms/fluentui-assets-license |
154 changes: 154 additions & 0 deletions
154
packages/react-components/react-base-components/library/README.md
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,154 @@ | ||
| # @fluentui/react-base-components | ||
|
|
||
| **Base component hooks and utilities for [Fluent UI React](https://react.fluentui.dev/)** | ||
|
|
||
| `@fluentui/react-base-components` exposes the base layer of Fluent UI v9 components: pure component logic, accessibility patterns, and semantic slot structure — without any styling opinions. | ||
|
|
||
| It is intended for teams building **custom design systems** that significantly diverge from Fluent 2. For most teams, the default styled components in `@fluentui/react-components` remain the recommended path. | ||
|
|
||
| ## What this package provides | ||
|
|
||
| - Component behavior, structure, and ARIA patterns | ||
| - Keyboard handling | ||
| - Semantic slot structure | ||
| - Base hooks and render functions for each component | ||
| - Re-exports of foundational utilities from `@fluentui/react-utilities` and `@fluentui/react-shared-contexts` | ||
|
|
||
| ## What this package does NOT provide | ||
|
|
||
| - Design props (`appearance`, `size`, `shape`, etc.) | ||
| - Style logic (Griffel, design tokens) | ||
| - Motion logic (animations, transitions) | ||
| - Default slot implementations (icons, components) | ||
|
|
||
| > **Accessibility note:** Base hooks provide ARIA attributes and semantic structure, but not visual accessibility (e.g., focus indicators, sufficient contrast). Consumers are responsible for implementing these in their custom styles. | ||
|
|
||
| ## Installation | ||
|
|
||
| ```sh | ||
| npm install @fluentui/react-base-components | ||
| ``` | ||
|
|
||
| ## Usage | ||
|
|
||
| ```tsx | ||
| import * as React from 'react'; | ||
| import { useButton, renderButton } from '@fluentui/react-base-components'; | ||
| import type { ButtonProps, ButtonState } from '@fluentui/react-base-components'; | ||
|
|
||
| type CustomButtonProps = ButtonProps & { | ||
| variant?: 'primary' | 'secondary' | 'tertiary'; | ||
| tone?: 'neutral' | 'success' | 'warning' | 'danger'; | ||
| }; | ||
|
|
||
| export const CustomButton = React.forwardRef<HTMLButtonElement, CustomButtonProps>( | ||
| ({ variant = 'primary', tone = 'neutral', ...props }, ref) => { | ||
| const state = useButton(props, ref); | ||
|
|
||
| state.root.className = ['custom-btn', `custom-btn--${variant}`, `custom-btn--${tone}`, state.root.className] | ||
| .filter(Boolean) | ||
| .join(' '); | ||
|
|
||
| if (state.icon) { | ||
| state.icon.className = ['custom-btn__icon', state.icon.className].filter(Boolean).join(' '); | ||
| } | ||
|
|
||
| return renderButton(state as ButtonState); | ||
| }, | ||
| ); | ||
| ``` | ||
|
|
||
| ## API | ||
|
|
||
| ### Naming conventions | ||
|
|
||
| | Artifact | Pattern | Example | | ||
| | ---------- | ------------------------ | -------------- | | ||
| | Hook | `use${ComponentName}` | `useButton` | | ||
| | Props type | `${ComponentName}Props` | `ButtonProps` | | ||
| | State type | `${ComponentName}State` | `ButtonState` | | ||
| | Render fn | `render${ComponentName}` | `renderButton` | | ||
|
|
||
| Hooks are stable aliases of the internal `use${ComponentName}Base_unstable` hooks from individual component packages. Types use `Base` internally but are exported without the suffix (e.g., `ButtonProps`, `ButtonState`). | ||
|
|
||
| ### `composeComponent` | ||
|
|
||
| A utility to compose a complete component from a base hook and render function: | ||
|
|
||
| ```ts | ||
| import { composeComponent } from '@fluentui/react-base-components'; | ||
| ``` | ||
|
|
||
| ### Component base hooks and render functions | ||
|
|
||
| | Component | Hooks | Context values hook | Render functions | | ||
| | ---------- | ----------------------------------------------------------------------------------- | -------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | | ||
| | Accordion | `useAccordion`, `useAccordionItem`, `useAccordionHeader`, `useAccordionPanel` | `useAccordionContextValues`, `useAccordionHeaderContextValues` | `renderAccordion`, `renderAccordionItem`, `renderAccordionHeader`, `renderAccordionPanel` | | ||
| | Badge | `useBadge`, `usePresenceBadge`, `useCounterBadge` | — | `renderBadge` | | ||
| | Breadcrumb | `useBreadcrumb`, `useBreadcrumbDivider`, `useBreadcrumbItem`, `useBreadcrumbButton` | `useBreadcrumbContextValues` | `renderBreadcrumb`, `renderBreadcrumbDivider`, `renderBreadcrumbItem`, `renderBreadcrumbButton` | | ||
| | Button | `useButton`, `useToggleButton` | — | `renderButton`, `renderToggleButton` | | ||
| | Card | `useCard`, `useCardFooter`, `useCardHeader`, `useCardPreview` | `useCardContextValues` | `renderCard`, `renderCardFooter`, `renderCardHeader`, `renderCardPreview` | | ||
| | Divider | `useDivider` | — | `renderDivider` | | ||
| | Image | `useImage` | — | `renderImage` | | ||
| | Input | `useInput` | — | `renderInput` | | ||
| | Link | `useLink` | — | `renderLink` | | ||
| | Persona | `usePersona` | — | `renderPersona` | | ||
| | Radio | `useRadioGroup`, `useRadio` | `useRadioGroupContextValues` | `renderRadioGroup`, `renderRadio` | | ||
| | Rating | `useRating`, `useRatingDisplay`, `useRatingItem` | `useRatingContextValues`, `useRatingDisplayContextValues` | `renderRating`, `renderRatingDisplay`, `renderRatingItem` | | ||
| | SearchBox | `useSearchBox` | — | `renderSearchBox` | | ||
| | Skeleton | `useSkeleton`, `useSkeletonItem` | `useSkeletonContextValues` | `renderSkeleton`, `renderSkeletonItem` | | ||
| | Slider | `useSlider` | — | `renderSlider` | | ||
| | SpinButton | `useSpinButton` | — | `renderSpinButton` | | ||
| | Spinner | `useSpinner` | — | `renderSpinner` | | ||
| | Switch | `useSwitch` | — | `renderSwitch` | | ||
| | Textarea | `useTextarea` | — | `renderTextarea` | | ||
|
|
||
| ### Re-exported utilities | ||
|
|
||
| #### From `@fluentui/react-shared-contexts` | ||
|
|
||
| | Export | Description | | ||
| | ------------------------- | ---------------------------------------- | | ||
| | `AnnounceProvider` | Provider for screen reader announcements | | ||
| | `PortalMountNodeProvider` | Provider for portal mount node | | ||
| | `useAnnounce` | Hook to trigger announcements | | ||
| | `useFluent` | Hook to access Fluent context | | ||
| | `usePortalMountNode` | Hook to access portal mount node | | ||
| | `useThemeClassName` | Hook to access theme class name | | ||
| | `useTooltipVisibility` | Hook to access tooltip visibility state | | ||
|
|
||
| #### From `@fluentui/react-utilities` | ||
|
|
||
| `getIntrinsicElementProps`, `getPartitionedNativeProps`, `getSlotClassNameProp_unstable`, `slot`, `assertSlots`, `IdPrefixProvider`, `resetIdsForTests`, `SSRProvider`, `useAnimationFrame`, `useId`, `useIsomorphicLayoutEffect`, `useEventCallback`, `mergeCallbacks`, `useIsSSR`, `useMergedRefs`, `useApplyScrollbarWidth`, `useScrollbarWidth`, `useSelection`, `useTimeout`, `isHTMLElement` | ||
|
|
||
| Also exports deprecated (but available) APIs: `getNativeElementProps`, `getSlots`, `resolveShorthand`. | ||
|
|
||
| ## Composition layers | ||
|
|
||
| ``` | ||
| use{Component}Base_unstable ← this package (base hook — logic + accessibility) | ||
| ↓ | ||
| use{Component}_unstable (adds design props) | ||
| ↓ | ||
| {Component} (adds Griffel styles + tokens) | ||
| ``` | ||
|
|
||
| This package exposes the **first layer** only. Styled components in `@fluentui/react-components` compose on top of it. | ||
|
|
||
| ## Migration | ||
|
|
||
| This is a new package; there is no migration from v8 or v0. For teams currently using full Fluent UI components that want to adopt base hooks: | ||
|
|
||
| 1. Replace `useButton_unstable(props, ref)` with `useButton(props, ref)` from this package | ||
| 2. Remove design props (`appearance`, `size`, `shape`) from your props type — use `ButtonProps` (the base variant) instead | ||
| 3. Apply your own class names or styles to the returned state slots before passing to the render function | ||
|
|
||
| ## Accessibility | ||
|
|
||
| Base hooks provide the semantic foundation for accessibility. Consumers must ensure their custom styles maintain: | ||
|
|
||
| - **Visible focus indicators** — base hooks do not apply focus ring styles | ||
| - **Sufficient color contrast** — base hooks do not apply colors or tokens | ||
| - **Appropriate visual feedback** for all interactive states (hover, active, disabled) | ||
|
|
||
| Each component follows its corresponding [WAI-ARIA authoring practice](https://www.w3.org/WAI/ARIA/apg/). Keyboard navigation, focus management, and state announcements are identical to the styled counterparts in `@fluentui/react-components`. |
7 changes: 7 additions & 0 deletions
7
...ges/react-components/react-base-components/library/bundle-size/ReactComponents.fixture.js
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| import * as rbc from '@fluentui/react-base-components'; | ||
|
|
||
| console.log(rbc); | ||
|
|
||
| export default { | ||
| name: 'react-base-components: entire library', | ||
| }; |
5 changes: 5 additions & 0 deletions
5
packages/react-components/react-base-components/library/config/api-extractor.json
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| { | ||
| "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", | ||
| "extends": "@fluentui/scripts-api-extractor/api-extractor.common.v-next.json", | ||
| "mainEntryPointFilePath": "<projectRoot>/../../../../../../dist/out-tsc/types/packages/react-components/<unscopedPackageName>/library/src/index.d.ts" | ||
| } |
3 changes: 3 additions & 0 deletions
3
packages/react-components/react-base-components/library/config/tests.js
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| /** Jest test setup file. */ | ||
|
|
||
| require('@testing-library/jest-dom'); |
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🕵🏾♀️ visual changes to review in the Visual Change Report
vr-tests-react-components/Avatar Converged 1 screenshots
vr-tests-react-components/CalendarCompat 4 screenshots
vr-tests-react-components/Charts-DonutChart 1 screenshots
vr-tests-react-components/Menu Converged - submenuIndicator slotted content 2 screenshots
vr-tests-react-components/Positioning 2 screenshots
vr-tests-react-components/ProgressBar converged 3 screenshots
vr-tests-react-components/TagPicker 1 screenshots
vr-tests/Callout 1 screenshots
vr-tests/Keytip 2 screenshots
vr-tests/react-charting-LineChart 4 screenshots
vr-tests/react-charting-MultiStackBarChart 2 screenshots
vr-tests/react-charting-VerticalBarChart 1 screenshots
There were 4 duplicate changes discarded. Check the build logs for more information.