Skip to content

RFC: Headless Components (@fluentui/react-headless-components)#35984

Open
dmytrokirpa wants to merge 4 commits intomicrosoft:masterfrom
dmytrokirpa:dmytrokirpa/rfc-headless-components
Open

RFC: Headless Components (@fluentui/react-headless-components)#35984
dmytrokirpa wants to merge 4 commits intomicrosoft:masterfrom
dmytrokirpa:dmytrokirpa/rfc-headless-components

Conversation

@dmytrokirpa
Copy link
Copy Markdown
Contributor

Summary

Proposes @fluentui/react-headless — a package of unstyled components built from base state hooks and render functions, with stable data-* attributes as the CSS-targeting contract for component state.

This is the next layer above the Base State Hooks RFC.

What's in this RFC

  • Package design@fluentui/react-headless as a single import surface re-exporting base hooks from individual packages
  • Composition model — each headless component is hook + render, data attributes authored in the base hook
  • State styling contract — stable data-* attribute schema on root slots, emitted by both headless and styled variants
  • Compound components — headless wrappers over existing base-context patterns (Menu, Dialog, Popover)
  • Rollout plan — phased: Button/Checkbox/Switch/Radio → Menu/Dialog/Popover → remaining v9 components

Open questions

See the review notes for identified gaps (FluentProvider dependency, _unstable naming, attribute collision semantics, etc.) that need resolution before this RFC is finalized.

Related

🤖 Generated with Claude Code

Proposes `@fluentui/react-headless` — unstyled components built from
base state hooks and render functions, with stable `data-*` attributes
as the CSS-targeting contract for component state.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions bot added the Type: RFC Request for Feedback label Apr 13, 2026
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 13, 2026

📊 Bundle size report

✅ No changes found

@github-actions
Copy link
Copy Markdown

Pull request demo site: URL

@dmytrokirpa dmytrokirpa self-assigned this Apr 13, 2026
@dmytrokirpa dmytrokirpa changed the title RFC: Headless Components (@fluentui/react-headless) RFC: Headless Components (@fluentui/react-headless-components) Apr 13, 2026
@dmytrokirpa dmytrokirpa force-pushed the dmytrokirpa/rfc-headless-components branch from 7d11b15 to 4e58ed7 Compare April 13, 2026 14:40
Headless components include:

- behavior and ARIA from base hooks
- existing slot API
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should highlight info about default slots ( no icons etc )

Ship headless components from `@fluentui/react-headless-components`.

```tsx
import { Button, Checkbox } from '@fluentui/react-headless-components';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should highlight the export maps api only

```

This abstraction preserves the existing base architecture but removes repetitive wiring from app
code. Note: headless components wrap existing hooks — they introduce no new behavior or
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets improve the structure

Suggested change
code. Note: headless components wrap existing hooks — they introduce no new behavior or
code.
> **💁‍♂️ Note:** headless components wrap existing hooks — they introduce no new behavior or


### State To `data-*` Mapping (Primary Contract)

Headless state hooks map internal state to stable `data-*` attributes. Components then render
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might be good to note that this pattern is also used for icons headless

- no design-state attributes (no appearance/size/shape)
- removal/rename is breaking (major)
- adding a new attribute is non-breaking for CSS selectors; it may affect snapshot tests, which is acceptable
- data attributes must be documented on the components documentation page (Storybook docsite)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would be actually good to have these as part of State type, then this will be part of .d.ts -> easy agent metadata extraction / SB table enablement

Comment on lines +35 to +36
Use headless when teams need Fluent behavior with non-Fluent visuals.
Use styled components when teams want Fluent visuals with branding tweaks.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this probably doesn't have to be part of this RFC, as the goal is clearly set above

dmytrokirpa and others added 2 commits April 14, 2026 16:06
- Clarify slot API: root slot only by default; optional slots (icon,
  avatar, indicator) require explicit props
- Remove redundant use-case guidance (already covered by Goal section)
- Add note that only the export-map root is a supported import surface
- Reformat composition-model note as a blockquote
- Note that icon-state data attributes follow the same data-* pattern
- Require data attributes to be typed on the State type for .d.ts /
  Storybook props-table / agent metadata extraction

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@dmytrokirpa dmytrokirpa marked this pull request as ready for review April 15, 2026 10:50
@dmytrokirpa dmytrokirpa requested review from a team as code owners April 15, 2026 10:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Type: RFC Request for Feedback

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants