feat(react-headless-components-preview): add TeachingPopover #36205
feat(react-headless-components-preview): add TeachingPopover #36205mainframev wants to merge 4 commits into
Conversation
📊 Bundle size report✅ No changes found |
|
Pull request demo site: URL |
| @@ -0,0 +1,7 @@ | |||
| { | |||
There was a problem hiding this comment.
🕵🏾♀️ visual changes to review in the Visual Change Report
vr-tests-react-components/CalendarCompat 4 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| vr-tests-react-components/CalendarCompat.multiDayView.default.chromium_1.png | 487 | Changed |
| vr-tests-react-components/CalendarCompat.multiDayView.default.chromium.png | 486 | Changed |
| vr-tests-react-components/CalendarCompat.multiDayView - High Contrast.default.chromium.png | 1213 | Changed |
| vr-tests-react-components/CalendarCompat.multiDayView - Dark Mode.default.chromium.png | 1099 | Changed |
vr-tests-react-components/Menu Converged - submenuIndicator slotted content 2 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| vr-tests-react-components/Menu Converged - submenuIndicator slotted content.default - RTL.submenus open.chromium.png | 404 | Changed |
| vr-tests-react-components/Menu Converged - submenuIndicator slotted content.default.submenus open.chromium.png | 413 | Changed |
vr-tests-react-components/Positioning 2 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| vr-tests-react-components/Positioning.Positioning end.chromium.png | 744 | Changed |
| vr-tests-react-components/Positioning.Positioning end.updated 2 times.chromium.png | 613 | Changed |
vr-tests-react-components/ProgressBar converged 2 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| vr-tests-react-components/ProgressBar converged.Indeterminate + thickness - Dark Mode.default.chromium.png | 51 | Changed |
| vr-tests-react-components/ProgressBar converged.Indeterminate + thickness - High Contrast.default.chromium.png | 52 | Changed |
vr-tests-react-components/TagPicker 3 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| vr-tests-react-components/TagPicker.disabled.chromium.png | 677 | Changed |
| vr-tests-react-components/TagPicker.disabled - Dark Mode.disabled input hover.chromium.png | 658 | Changed |
| vr-tests-react-components/TagPicker.disabled - High Contrast.disabled input hover.chromium.png | 1319 | Changed |
There were 4 duplicate changes discarded. Check the build logs for more information.
086563e to
67884ed
Compare
| @@ -0,0 +1,37 @@ | |||
| import type { PopoverContextValue as V9PopoverContextValue } from '@fluentui/react-popover'; | |||
There was a problem hiding this comment.
nit, but lets use Base or Fluent prefix/suffix instead of v9
| state: TeachingPopoverState, | ||
| contextValues: TeachingPopoverContextValues, | ||
| ): React.ReactElement => ( | ||
| <PopoverProvider value={contextValues.popover}> |
There was a problem hiding this comment.
that's unfortunate that headless popover doesn't re-use v9's context provider, that would simplify cases like this
| * Cast around the v9 contextValues helper, which is typed against the | ||
| * styled state but only reads carousel fields that exist on the base state. | ||
| */ | ||
| export const useTeachingPopoverCarouselContextValues = ( |
There was a problem hiding this comment.
You can type-cast without creating a wrapper:
| export const useTeachingPopoverCarouselContextValues = ( | |
| export const useTeachingPopoverCarouselContextValues = useTeachingPopoverCarouselContextValues_unstable as (state: TeachingPopoverCarouselState) => TeachingPopoverCarouselContextValues |
| export const renderTeachingPopoverCarouselFooterButton = ( | ||
| state: TeachingPopoverCarouselFooterButtonState, | ||
| ): JSXElement => | ||
| renderTeachingPopoverCarouselFooterButton_unstable( |
There was a problem hiding this comment.
the same as above, lets type-cast without wrapping a hook
| import type { TeachingPopoverCarouselNavButtonState } from './TeachingPopoverCarouselNavButton.types'; | ||
|
|
||
| export const renderTeachingPopoverCarouselNavButton = (state: TeachingPopoverCarouselNavButtonState): JSXElement => | ||
| renderTeachingPopoverCarouselNavButton_unstable( |
There was a problem hiding this comment.
and here, lets type-cast without creating a wrapper
| @@ -0,0 +1,3 @@ | |||
| The headless `TeachingPopover` is built on top of the headless `Popover`. It adds a structured header / title / body / footer composition and an optional paged carousel — without styling. Bring your own CSS. | |||
|
|
|||
| `TeachingPopover` re-uses the v9 `react-teaching-popover` base hooks for its sub-components (`Header`, `Title`, `Footer`, `Carousel*`) and bridges the v9 `PopoverContext` internally so dismiss buttons, finish handlers, and the carousel state machine all work transparently. | |||
There was a problem hiding this comment.
v9 might not be clear to everyone, we should probably use @fluentui/react-teaching-popover
| TeachingPopoverTrigger, | ||
| } from '@fluentui/react-headless-components-preview/teaching-popover'; | ||
|
|
||
| import styles from './teaching-popover.module.css'; |
There was a problem hiding this comment.
can we re-use popover styles
import styles from './teaching-popover.module.css';
import popoverStyles from '../Popover/popover.module.css';
Adds a new headless
TeachingPopoverexposed at the@fluentui/react-headless-components-preview/teaching-popoversubpathHow it composes
useTeachingPopoverbuilds on the headlessusePopoverand defaultswithArrow: trueto match the v9 component.*Base_unstablehooks introduced in feat(react-teaching-popover): add base hooks and export them #36200(
useTeachingPopoverHeaderBase_unstable,useTeachingPopoverTitleBase_unstable,useTeachingPopoverFooterBase_unstable,useTeachingPopoverCarouselBase_unstable,etc.), keeping all behavior (dismiss handlers, finish handlers, carousel state
machine) while dropping the styled
appearance, default icons, and primary /secondary Button slots.
renderTeachingPopoverbridges the headlessPopoverProviderand the v9PopoverProviderso v9 base sub‑hooks can read context transparently.TeachingPopoverFooterships a local render that emits only<state.root />(no primary / secondary Button slots — consumer composes any buttons).
TeachingPopoverCarouselFooterships a local hook + render returning only{ root }for the same reason.Not in scope
appearance,trapFocus(TBA), andinlineprops from the v9 component areintentionally dropped
Stories
Two stories under
stories/src/TeachingPopover/:Default— header (icon + label + dismiss), media placeholder, title, body,primary + secondary footer.
WithCarousel— three‑card tour with nav buttons, page count, and prev / nextcontrols.