diff --git a/change/@fluentui-react-headless-components-preview-7c305eb6-2458-4126-b561-228475292c80.json b/change/@fluentui-react-headless-components-preview-7c305eb6-2458-4126-b561-228475292c80.json new file mode 100644 index 00000000000000..37cadcb05535da --- /dev/null +++ b/change/@fluentui-react-headless-components-preview-7c305eb6-2458-4126-b561-228475292c80.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "feat: add headless TeachingPopover composed on top of the headless Popover and the v9 react-teaching-popover base hooks", + "packageName": "@fluentui/react-headless-components-preview", + "email": "viktorgenaev@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/packages/react-components/react-headless-components-preview/library/etc/teaching-popover.api.md b/packages/react-components/react-headless-components-preview/library/etc/teaching-popover.api.md new file mode 100644 index 00000000000000..b3f7b54c037e03 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/etc/teaching-popover.api.md @@ -0,0 +1,316 @@ +## API Report File for "@fluentui/react-headless-components-preview" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import type { ARIAButtonType } from '@fluentui/react-aria'; +import type { ComponentProps } from '@fluentui/react-utilities'; +import type { ComponentState } from '@fluentui/react-utilities'; +import type { EventData } from '@fluentui/react-utilities'; +import type { EventHandler } from '@fluentui/react-utilities'; +import type { ForwardRefComponent } from '@fluentui/react-utilities'; +import type { JSXElement } from '@fluentui/react-utilities'; +import type { PopoverContextValue as PopoverContextValue_2 } from '@fluentui/react-popover'; +import type { PopoverTriggerChildProps } from '@fluentui/react-popover'; +import { PositioningShorthand } from '@fluentui/react-positioning'; +import * as React_2 from 'react'; +import { renderTeachingPopoverBody_unstable as renderTeachingPopoverBody } from '@fluentui/react-teaching-popover'; +import { renderTeachingPopoverCarouselCard_unstable as renderTeachingPopoverCarouselCard } from '@fluentui/react-teaching-popover'; +import { renderTeachingPopoverCarouselNav_unstable as renderTeachingPopoverCarouselNav } from '@fluentui/react-teaching-popover'; +import { renderTeachingPopoverCarouselPageCount_unstable as renderTeachingPopoverCarouselPageCount } from '@fluentui/react-teaching-popover'; +import type { Slot } from '@fluentui/react-utilities'; +import { TeachingPopoverBodyProps } from '@fluentui/react-teaching-popover'; +import { TeachingPopoverBodySlots } from '@fluentui/react-teaching-popover'; +import { TeachingPopoverBodyState } from '@fluentui/react-teaching-popover'; +import { TeachingPopoverCarouselCardProps } from '@fluentui/react-teaching-popover'; +import { TeachingPopoverCarouselCardSlots } from '@fluentui/react-teaching-popover'; +import { TeachingPopoverCarouselCardState } from '@fluentui/react-teaching-popover'; +import { TeachingPopoverCarouselFooterButtonBaseProps as TeachingPopoverCarouselFooterButtonProps } from '@fluentui/react-teaching-popover'; +import { TeachingPopoverCarouselFooterButtonSlots } from '@fluentui/react-teaching-popover'; +import { TeachingPopoverCarouselFooterButtonBaseState as TeachingPopoverCarouselFooterButtonState } from '@fluentui/react-teaching-popover'; +import { TeachingPopoverCarouselNavButtonBaseProps as TeachingPopoverCarouselNavButtonProps } from '@fluentui/react-teaching-popover'; +import { TeachingPopoverCarouselNavButtonSlots } from '@fluentui/react-teaching-popover'; +import { TeachingPopoverCarouselNavButtonBaseState as TeachingPopoverCarouselNavButtonState } from '@fluentui/react-teaching-popover'; +import { TeachingPopoverCarouselNavBaseProps as TeachingPopoverCarouselNavProps } from '@fluentui/react-teaching-popover'; +import { TeachingPopoverCarouselNavSlots } from '@fluentui/react-teaching-popover'; +import { TeachingPopoverCarouselNavBaseState as TeachingPopoverCarouselNavState } from '@fluentui/react-teaching-popover'; +import { TeachingPopoverCarouselPageCountProps } from '@fluentui/react-teaching-popover'; +import { TeachingPopoverCarouselPageCountRenderFunction } from '@fluentui/react-teaching-popover'; +import { TeachingPopoverCarouselPageCountSlots } from '@fluentui/react-teaching-popover'; +import { TeachingPopoverCarouselPageCountState } from '@fluentui/react-teaching-popover'; +import { TeachingPopoverCarouselBaseProps as TeachingPopoverCarouselProps } from '@fluentui/react-teaching-popover'; +import { TeachingPopoverCarouselSlots } from '@fluentui/react-teaching-popover'; +import { TeachingPopoverCarouselBaseState as TeachingPopoverCarouselState } from '@fluentui/react-teaching-popover'; +import type { TeachingPopoverFooterBaseProps } from '@fluentui/react-teaching-popover'; +import type { TeachingPopoverFooterBaseState } from '@fluentui/react-teaching-popover'; +import type { TeachingPopoverHeaderBaseProps } from '@fluentui/react-teaching-popover'; +import type { TeachingPopoverHeaderBaseState } from '@fluentui/react-teaching-popover'; +import type { TeachingPopoverHeaderSlots } from '@fluentui/react-teaching-popover'; +import type { TeachingPopoverTitleBaseProps } from '@fluentui/react-teaching-popover'; +import type { TeachingPopoverTitleBaseState } from '@fluentui/react-teaching-popover'; +import type { TeachingPopoverTitleSlots } from '@fluentui/react-teaching-popover'; +import type { TriggerProps } from '@fluentui/react-utilities'; +import { useTeachingPopoverBody_unstable as useTeachingPopoverBody } from '@fluentui/react-teaching-popover'; +import { useTeachingPopoverCarouselBase_unstable as useTeachingPopoverCarousel } from '@fluentui/react-teaching-popover'; +import { useTeachingPopoverCarouselCard_unstable as useTeachingPopoverCarouselCard } from '@fluentui/react-teaching-popover'; +import type { useTeachingPopoverCarouselContextValues_unstable } from '@fluentui/react-teaching-popover'; +import { useTeachingPopoverCarouselFooterButtonBase_unstable as useTeachingPopoverCarouselFooterButton } from '@fluentui/react-teaching-popover'; +import { useTeachingPopoverCarouselNavBase_unstable as useTeachingPopoverCarouselNav } from '@fluentui/react-teaching-popover'; +import { useTeachingPopoverCarouselNavButtonBase_unstable as useTeachingPopoverCarouselNavButton } from '@fluentui/react-teaching-popover'; +import { useTeachingPopoverCarouselPageCount_unstable as useTeachingPopoverCarouselPageCount } from '@fluentui/react-teaching-popover'; +import { useTeachingPopoverFooterBase_unstable as useTeachingPopoverFooter } from '@fluentui/react-teaching-popover'; +import { useTeachingPopoverHeaderBase_unstable as useTeachingPopoverHeader } from '@fluentui/react-teaching-popover'; +import { useTeachingPopoverTitleBase_unstable as useTeachingPopoverTitle } from '@fluentui/react-teaching-popover'; + +// @public +export type NavButtonRenderFunction = TeachingPopoverCarouselNavState['renderNavButton']; + +// @public +export const renderTeachingPopover: (state: TeachingPopoverState, contextValues: TeachingPopoverContextValues) => React_2.ReactElement; + +export { renderTeachingPopoverBody } + +// @public +export const renderTeachingPopoverCarousel: (state: TeachingPopoverCarouselState, contextValues: TeachingPopoverCarouselContextValues) => JSXElement; + +export { renderTeachingPopoverCarouselCard } + +// @public (undocumented) +export const renderTeachingPopoverCarouselFooter: (state: TeachingPopoverCarouselFooterState) => JSXElement; + +// @public (undocumented) +export const renderTeachingPopoverCarouselFooterButton: (state: TeachingPopoverCarouselFooterButtonState) => JSXElement; + +export { renderTeachingPopoverCarouselNav } + +// @public (undocumented) +export const renderTeachingPopoverCarouselNavButton: (state: TeachingPopoverCarouselNavButtonState) => JSXElement; + +export { renderTeachingPopoverCarouselPageCount } + +// @public +export const renderTeachingPopoverFooter: (state: TeachingPopoverFooterState) => JSXElement; + +// @public +export const renderTeachingPopoverHeader: (state: TeachingPopoverHeaderState) => JSXElement; + +// @public (undocumented) +export const renderTeachingPopoverSurface: (state: TeachingPopoverSurfaceState) => JSXElement; + +// @public +export const renderTeachingPopoverTitle: (state: TeachingPopoverTitleState) => JSXElement; + +// @public +export const renderTeachingPopoverTrigger: (state: TeachingPopoverTriggerState) => JSXElement | null; + +// @public +export const TeachingPopover: { + (props: TeachingPopoverProps): JSXElement; + displayName: string; +}; + +// @public +export type TeachingPopoverBaseBridgedContextValue = Pick; + +// @public (undocumented) +export const TeachingPopoverBody: ForwardRefComponent; + +export { TeachingPopoverBodyProps } + +export { TeachingPopoverBodySlots } + +export { TeachingPopoverBodyState } + +// @public (undocumented) +export const TeachingPopoverCarousel: ForwardRefComponent; + +// @public (undocumented) +export const TeachingPopoverCarouselCard: ForwardRefComponent; + +export { TeachingPopoverCarouselCardProps } + +export { TeachingPopoverCarouselCardSlots } + +export { TeachingPopoverCarouselCardState } + +// @public +export type TeachingPopoverCarouselContextValues = ReturnType; + +// @public (undocumented) +export const TeachingPopoverCarouselFooter: ForwardRefComponent; + +// @public (undocumented) +export const TeachingPopoverCarouselFooterButton: ForwardRefComponent; + +export { TeachingPopoverCarouselFooterButtonProps } + +export { TeachingPopoverCarouselFooterButtonSlots } + +export { TeachingPopoverCarouselFooterButtonState } + +// @public (undocumented) +export type TeachingPopoverCarouselFooterProps = ComponentProps; + +// @public (undocumented) +export type TeachingPopoverCarouselFooterSlots = { + root: NonNullable>; +}; + +// @public (undocumented) +export type TeachingPopoverCarouselFooterState = ComponentState; + +// @public (undocumented) +export const TeachingPopoverCarouselNav: ForwardRefComponent; + +// @public (undocumented) +export const TeachingPopoverCarouselNavButton: ForwardRefComponent; + +export { TeachingPopoverCarouselNavButtonProps } + +export { TeachingPopoverCarouselNavButtonSlots } + +export { TeachingPopoverCarouselNavButtonState } + +export { TeachingPopoverCarouselNavProps } + +export { TeachingPopoverCarouselNavSlots } + +export { TeachingPopoverCarouselNavState } + +// @public (undocumented) +export const TeachingPopoverCarouselPageCount: ForwardRefComponent; + +export { TeachingPopoverCarouselPageCountProps } + +export { TeachingPopoverCarouselPageCountRenderFunction } + +export { TeachingPopoverCarouselPageCountSlots } + +export { TeachingPopoverCarouselPageCountState } + +export { TeachingPopoverCarouselProps } + +export { TeachingPopoverCarouselSlots } + +export { TeachingPopoverCarouselState } + +// @public (undocumented) +export type TeachingPopoverContextValues = { + popover: PopoverContextValue; + basePopover: TeachingPopoverBaseBridgedContextValue; +}; + +// @public (undocumented) +export const TeachingPopoverFooter: ForwardRefComponent; + +// @public (undocumented) +export type TeachingPopoverFooterProps = TeachingPopoverFooterBaseProps; + +// @public (undocumented) +export type TeachingPopoverFooterState = TeachingPopoverFooterBaseState; + +// @public (undocumented) +export const TeachingPopoverHeader: ForwardRefComponent; + +// @public (undocumented) +export type TeachingPopoverHeaderProps = TeachingPopoverHeaderBaseProps; + +export { TeachingPopoverHeaderSlots } + +// @public (undocumented) +export type TeachingPopoverHeaderState = TeachingPopoverHeaderBaseState; + +// @public +export type TeachingPopoverProps = PopoverProps; + +// @public +export type TeachingPopoverState = PopoverState; + +// @public +export const TeachingPopoverSurface: ForwardRefComponent; + +// @public (undocumented) +export type TeachingPopoverSurfaceProps = ComponentProps; + +// @public +export type TeachingPopoverSurfaceSlots = { + root: Slot<'div'>; +}; + +// @public (undocumented) +export type TeachingPopoverSurfaceState = ComponentState & { + withArrow: boolean | undefined; + arrowRef: React_2.RefObject; + 'data-open': string; +}; + +// @public (undocumented) +export const TeachingPopoverTitle: ForwardRefComponent; + +// @public (undocumented) +export type TeachingPopoverTitleProps = TeachingPopoverTitleBaseProps; + +export { TeachingPopoverTitleSlots } + +// @public (undocumented) +export type TeachingPopoverTitleState = TeachingPopoverTitleBaseState; + +// @public +export const TeachingPopoverTrigger: React_2.FC; + +// @public +export type TeachingPopoverTriggerChildProps = PopoverTriggerChildProps; + +// @public +export type TeachingPopoverTriggerProps = Omit, 'children'> & { + children: React_2.ReactElement; + disableButtonEnhancement?: boolean; +}; + +// @public +export type TeachingPopoverTriggerState = { + children: React_2.ReactElement | null; +}; + +// @public +export const useTeachingPopover: (props: TeachingPopoverProps) => TeachingPopoverState; + +export { useTeachingPopoverBody } + +export { useTeachingPopoverCarousel } + +export { useTeachingPopoverCarouselCard } + +// @public (undocumented) +export const useTeachingPopoverCarouselContextValues: (state: TeachingPopoverCarouselState) => TeachingPopoverCarouselContextValues; + +// @public (undocumented) +export const useTeachingPopoverCarouselFooter: (props: TeachingPopoverCarouselFooterProps, ref: React_2.Ref) => TeachingPopoverCarouselFooterState; + +export { useTeachingPopoverCarouselFooterButton } + +export { useTeachingPopoverCarouselNav } + +export { useTeachingPopoverCarouselNavButton } + +export { useTeachingPopoverCarouselPageCount } + +// @public +export const useTeachingPopoverContextValues: (state: TeachingPopoverState) => TeachingPopoverContextValues; + +export { useTeachingPopoverFooter } + +export { useTeachingPopoverHeader } + +// @public +export const useTeachingPopoverSurface: (props: TeachingPopoverSurfaceProps, ref: React_2.Ref) => TeachingPopoverSurfaceState; + +export { useTeachingPopoverTitle } + +// @public +export const useTeachingPopoverTrigger: (props: TeachingPopoverTriggerProps) => TeachingPopoverTriggerState; + +// (No @packageDocumentation comment for this package) + +``` diff --git a/packages/react-components/react-headless-components-preview/library/package.json b/packages/react-components/react-headless-components-preview/library/package.json index 527a2145fbe4ad..b9ab9ec6438a04 100644 --- a/packages/react-components/react-headless-components-preview/library/package.json +++ b/packages/react-components/react-headless-components-preview/library/package.json @@ -56,6 +56,7 @@ "@fluentui/react-switch": "^9.7.2", "@fluentui/react-tabs": "^9.12.1", "@fluentui/react-tabster": "^9.26.14", + "@fluentui/react-teaching-popover": "^9.6.21", "@fluentui/react-tags": "^9.8.1", "@fluentui/react-textarea": "^9.7.2", "@fluentui/react-toolbar": "^9.8.0", @@ -274,6 +275,12 @@ "import": "./lib/tab-list.js", "require": "./lib-commonjs/tab-list.js" }, + "./teaching-popover": { + "types": "./dist/teaching-popover.d.ts", + "node": "./lib-commonjs/teaching-popover.js", + "import": "./lib/teaching-popover.js", + "require": "./lib-commonjs/teaching-popover.js" + }, "./textarea": { "types": "./dist/textarea.d.ts", "node": "./lib-commonjs/textarea.js", diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopover.tsx b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopover.tsx new file mode 100644 index 00000000000000..fbbd5cb5af8b6e --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopover.tsx @@ -0,0 +1,23 @@ +'use client'; + +import type { JSXElement } from '@fluentui/react-utilities'; +import type { TeachingPopoverProps } from './TeachingPopover.types'; +import { useTeachingPopover } from './useTeachingPopover'; +import { useTeachingPopoverContextValues } from './useTeachingPopoverContextValues'; +import { renderTeachingPopover } from './renderTeachingPopover'; + +/** + * Headless TeachingPopover component. + * + * Wraps the headless `Popover` and additionally bridges the v9 + * `PopoverContext` so sub-components built on `useTeachingPopover*Base_unstable` + * hooks from `@fluentui/react-teaching-popover` resolve their context reads. + */ +export const TeachingPopover = (props: TeachingPopoverProps): JSXElement => { + const state = useTeachingPopover(props); + const contextValues = useTeachingPopoverContextValues(state); + + return renderTeachingPopover(state, contextValues); +}; + +TeachingPopover.displayName = 'TeachingPopover'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopover.types.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopover.types.ts new file mode 100644 index 00000000000000..52ddc2f03464d5 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopover.types.ts @@ -0,0 +1,38 @@ +import type { PopoverContextValue as BasePopoverContextValue } from '@fluentui/react-popover'; +import type { PopoverProps, PopoverState, PopoverContextValue } from '../Popover/Popover.types'; + +/** + * TeachingPopover Props + */ +export type TeachingPopoverProps = PopoverProps; + +/** + * TeachingPopover State — identical to the headless Popover state. Styling + * concerns from `@fluentui/react-teaching-popover` (`appearance`, `trapFocus`, + * `inline`) are intentionally omitted; consumers control presentation. + */ +export type TeachingPopoverState = PopoverState; + +/** + * Subset of the `@fluentui/react-popover` `PopoverContextValue` that the + * `@fluentui/react-teaching-popover` base hooks actually read (`toggleOpen`, + * `setOpen`, `triggerRef`). The other fields fall back to + * `popoverContextDefaultValue` from `@fluentui/react-popover`. + */ +export type TeachingPopoverBaseBridgedContextValue = Pick< + BasePopoverContextValue, + | 'open' + | 'setOpen' + | 'toggleOpen' + | 'triggerRef' + | 'contentRef' + | 'arrowRef' + | 'openOnHover' + | 'openOnContext' + | 'withArrow' +>; + +export type TeachingPopoverContextValues = { + popover: PopoverContextValue; + basePopover: TeachingPopoverBaseBridgedContextValue; +}; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverBody/TeachingPopoverBody.tsx b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverBody/TeachingPopoverBody.tsx new file mode 100644 index 00000000000000..ff2c17262f98d5 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverBody/TeachingPopoverBody.tsx @@ -0,0 +1,14 @@ +'use client'; + +import * as React from 'react'; +import type { ForwardRefComponent } from '@fluentui/react-utilities'; +import type { TeachingPopoverBodyProps } from './TeachingPopoverBody.types'; +import { useTeachingPopoverBody } from './useTeachingPopoverBody'; +import { renderTeachingPopoverBody } from './renderTeachingPopoverBody'; + +export const TeachingPopoverBody: ForwardRefComponent = React.forwardRef((props, ref) => { + const state = useTeachingPopoverBody(props, ref); + return renderTeachingPopoverBody(state); +}); + +TeachingPopoverBody.displayName = 'TeachingPopoverBody'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverBody/TeachingPopoverBody.types.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverBody/TeachingPopoverBody.types.ts new file mode 100644 index 00000000000000..29dc0c22fe142d --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverBody/TeachingPopoverBody.types.ts @@ -0,0 +1,5 @@ +export type { + TeachingPopoverBodyProps, + TeachingPopoverBodySlots, + TeachingPopoverBodyState, +} from '@fluentui/react-teaching-popover'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverBody/index.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverBody/index.ts new file mode 100644 index 00000000000000..56c5d3d564796d --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverBody/index.ts @@ -0,0 +1,8 @@ +export { TeachingPopoverBody } from './TeachingPopoverBody'; +export { useTeachingPopoverBody } from './useTeachingPopoverBody'; +export { renderTeachingPopoverBody } from './renderTeachingPopoverBody'; +export type { + TeachingPopoverBodyProps, + TeachingPopoverBodySlots, + TeachingPopoverBodyState, +} from './TeachingPopoverBody.types'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverBody/renderTeachingPopoverBody.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverBody/renderTeachingPopoverBody.ts new file mode 100644 index 00000000000000..28077e68cbfd41 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverBody/renderTeachingPopoverBody.ts @@ -0,0 +1 @@ +export { renderTeachingPopoverBody_unstable as renderTeachingPopoverBody } from '@fluentui/react-teaching-popover'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverBody/useTeachingPopoverBody.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverBody/useTeachingPopoverBody.ts new file mode 100644 index 00000000000000..bdb775e24fbd6f --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverBody/useTeachingPopoverBody.ts @@ -0,0 +1 @@ +export { useTeachingPopoverBody_unstable as useTeachingPopoverBody } from '@fluentui/react-teaching-popover'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarousel/TeachingPopoverCarousel.tsx b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarousel/TeachingPopoverCarousel.tsx new file mode 100644 index 00000000000000..01c1d61731a1af --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarousel/TeachingPopoverCarousel.tsx @@ -0,0 +1,17 @@ +'use client'; + +import * as React from 'react'; +import type { ForwardRefComponent } from '@fluentui/react-utilities'; +import type { TeachingPopoverCarouselProps } from './TeachingPopoverCarousel.types'; +import { useTeachingPopoverCarousel, useTeachingPopoverCarouselContextValues } from './useTeachingPopoverCarousel'; +import { renderTeachingPopoverCarousel } from './renderTeachingPopoverCarousel'; + +export const TeachingPopoverCarousel: ForwardRefComponent = React.forwardRef( + (props, ref) => { + const state = useTeachingPopoverCarousel(props, ref); + const contextValues = useTeachingPopoverCarouselContextValues(state); + return renderTeachingPopoverCarousel(state, contextValues); + }, +); + +TeachingPopoverCarousel.displayName = 'TeachingPopoverCarousel'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarousel/TeachingPopoverCarousel.types.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarousel/TeachingPopoverCarousel.types.ts new file mode 100644 index 00000000000000..3f0fbf7f857f56 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarousel/TeachingPopoverCarousel.types.ts @@ -0,0 +1,15 @@ +import type { useTeachingPopoverCarouselContextValues_unstable } from '@fluentui/react-teaching-popover'; + +export type { + TeachingPopoverCarouselBaseProps as TeachingPopoverCarouselProps, + TeachingPopoverCarouselBaseState as TeachingPopoverCarouselState, + TeachingPopoverCarouselSlots, +} from '@fluentui/react-teaching-popover'; + +/** + * Context shared between TeachingPopoverCarousel and its children components. + * + * Derived from the v9 `useTeachingPopoverCarouselContextValues_unstable` return + * type, which is the package's public contract for this shape. + */ +export type TeachingPopoverCarouselContextValues = ReturnType; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarousel/index.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarousel/index.ts new file mode 100644 index 00000000000000..d9384c9a2ea826 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarousel/index.ts @@ -0,0 +1,9 @@ +export { TeachingPopoverCarousel } from './TeachingPopoverCarousel'; +export { useTeachingPopoverCarousel, useTeachingPopoverCarouselContextValues } from './useTeachingPopoverCarousel'; +export { renderTeachingPopoverCarousel } from './renderTeachingPopoverCarousel'; +export type { + TeachingPopoverCarouselProps, + TeachingPopoverCarouselState, + TeachingPopoverCarouselSlots, + TeachingPopoverCarouselContextValues, +} from './TeachingPopoverCarousel.types'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarousel/renderTeachingPopoverCarousel.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarousel/renderTeachingPopoverCarousel.ts new file mode 100644 index 00000000000000..8bbbaefee7691a --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarousel/renderTeachingPopoverCarousel.ts @@ -0,0 +1,19 @@ +import { renderTeachingPopoverCarousel_unstable } from '@fluentui/react-teaching-popover'; +import type { JSXElement } from '@fluentui/react-utilities'; +import type { + TeachingPopoverCarouselContextValues, + TeachingPopoverCarouselState, +} from './TeachingPopoverCarousel.types'; + +/** + * Cast to v9's render signature — base state omits `appearance` and the + * render only reads the root slot and wraps with `CarouselProvider`. + */ +export const renderTeachingPopoverCarousel = ( + state: TeachingPopoverCarouselState, + contextValues: TeachingPopoverCarouselContextValues, +): JSXElement => + renderTeachingPopoverCarousel_unstable( + state as Parameters[0], + contextValues, + ); diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarousel/useTeachingPopoverCarousel.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarousel/useTeachingPopoverCarousel.ts new file mode 100644 index 00000000000000..5f87a4c43747cf --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarousel/useTeachingPopoverCarousel.ts @@ -0,0 +1,13 @@ +'use client'; + +import { useTeachingPopoverCarouselContextValues_unstable } from '@fluentui/react-teaching-popover'; +import type { + TeachingPopoverCarouselContextValues, + TeachingPopoverCarouselState, +} from './TeachingPopoverCarousel.types'; + +export { useTeachingPopoverCarouselBase_unstable as useTeachingPopoverCarousel } from '@fluentui/react-teaching-popover'; + +export const useTeachingPopoverCarouselContextValues = useTeachingPopoverCarouselContextValues_unstable as ( + state: TeachingPopoverCarouselState, +) => TeachingPopoverCarouselContextValues; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselCard/TeachingPopoverCarouselCard.tsx b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselCard/TeachingPopoverCarouselCard.tsx new file mode 100644 index 00000000000000..05187f14c36577 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselCard/TeachingPopoverCarouselCard.tsx @@ -0,0 +1,16 @@ +'use client'; + +import * as React from 'react'; +import type { ForwardRefComponent } from '@fluentui/react-utilities'; +import type { TeachingPopoverCarouselCardProps } from './TeachingPopoverCarouselCard.types'; +import { useTeachingPopoverCarouselCard } from './useTeachingPopoverCarouselCard'; +import { renderTeachingPopoverCarouselCard } from './renderTeachingPopoverCarouselCard'; + +export const TeachingPopoverCarouselCard: ForwardRefComponent = React.forwardRef( + (props, ref) => { + const state = useTeachingPopoverCarouselCard(props, ref); + return renderTeachingPopoverCarouselCard(state); + }, +); + +TeachingPopoverCarouselCard.displayName = 'TeachingPopoverCarouselCard'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselCard/TeachingPopoverCarouselCard.types.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselCard/TeachingPopoverCarouselCard.types.ts new file mode 100644 index 00000000000000..d5b40c259db6d4 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselCard/TeachingPopoverCarouselCard.types.ts @@ -0,0 +1,5 @@ +export type { + TeachingPopoverCarouselCardProps, + TeachingPopoverCarouselCardSlots, + TeachingPopoverCarouselCardState, +} from '@fluentui/react-teaching-popover'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselCard/index.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselCard/index.ts new file mode 100644 index 00000000000000..a53dead1da05f1 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselCard/index.ts @@ -0,0 +1,8 @@ +export { TeachingPopoverCarouselCard } from './TeachingPopoverCarouselCard'; +export { useTeachingPopoverCarouselCard } from './useTeachingPopoverCarouselCard'; +export { renderTeachingPopoverCarouselCard } from './renderTeachingPopoverCarouselCard'; +export type { + TeachingPopoverCarouselCardProps, + TeachingPopoverCarouselCardSlots, + TeachingPopoverCarouselCardState, +} from './TeachingPopoverCarouselCard.types'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselCard/renderTeachingPopoverCarouselCard.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselCard/renderTeachingPopoverCarouselCard.ts new file mode 100644 index 00000000000000..a81ed09667e72b --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselCard/renderTeachingPopoverCarouselCard.ts @@ -0,0 +1 @@ +export { renderTeachingPopoverCarouselCard_unstable as renderTeachingPopoverCarouselCard } from '@fluentui/react-teaching-popover'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselCard/useTeachingPopoverCarouselCard.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselCard/useTeachingPopoverCarouselCard.ts new file mode 100644 index 00000000000000..6e36fd10ce16b0 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselCard/useTeachingPopoverCarouselCard.ts @@ -0,0 +1 @@ +export { useTeachingPopoverCarouselCard_unstable as useTeachingPopoverCarouselCard } from '@fluentui/react-teaching-popover'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooter/TeachingPopoverCarouselFooter.tsx b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooter/TeachingPopoverCarouselFooter.tsx new file mode 100644 index 00000000000000..30ee96c879ab11 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooter/TeachingPopoverCarouselFooter.tsx @@ -0,0 +1,16 @@ +'use client'; + +import * as React from 'react'; +import type { ForwardRefComponent } from '@fluentui/react-utilities'; +import type { TeachingPopoverCarouselFooterProps } from './TeachingPopoverCarouselFooter.types'; +import { useTeachingPopoverCarouselFooter } from './useTeachingPopoverCarouselFooter'; +import { renderTeachingPopoverCarouselFooter } from './renderTeachingPopoverCarouselFooter'; + +export const TeachingPopoverCarouselFooter: ForwardRefComponent = React.forwardRef( + (props, ref) => { + const state = useTeachingPopoverCarouselFooter(props, ref); + return renderTeachingPopoverCarouselFooter(state); + }, +); + +TeachingPopoverCarouselFooter.displayName = 'TeachingPopoverCarouselFooter'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooter/TeachingPopoverCarouselFooter.types.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooter/TeachingPopoverCarouselFooter.types.ts new file mode 100644 index 00000000000000..9b5ee386be94c7 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooter/TeachingPopoverCarouselFooter.types.ts @@ -0,0 +1,13 @@ +import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities'; + +export type TeachingPopoverCarouselFooterSlots = { + /** + * The element wrapping carousel navigation children (previous/next buttons, + * page count, etc.). Consumers compose children directly — no default slots. + */ + root: NonNullable>; +}; + +export type TeachingPopoverCarouselFooterProps = ComponentProps; + +export type TeachingPopoverCarouselFooterState = ComponentState; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooter/index.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooter/index.ts new file mode 100644 index 00000000000000..3f21fc3b86db9f --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooter/index.ts @@ -0,0 +1,8 @@ +export { TeachingPopoverCarouselFooter } from './TeachingPopoverCarouselFooter'; +export { useTeachingPopoverCarouselFooter } from './useTeachingPopoverCarouselFooter'; +export { renderTeachingPopoverCarouselFooter } from './renderTeachingPopoverCarouselFooter'; +export type { + TeachingPopoverCarouselFooterProps, + TeachingPopoverCarouselFooterSlots, + TeachingPopoverCarouselFooterState, +} from './TeachingPopoverCarouselFooter.types'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooter/renderTeachingPopoverCarouselFooter.tsx b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooter/renderTeachingPopoverCarouselFooter.tsx new file mode 100644 index 00000000000000..e79819a55a84d2 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooter/renderTeachingPopoverCarouselFooter.tsx @@ -0,0 +1,14 @@ +/** @jsxRuntime automatic */ +/** @jsxImportSource @fluentui/react-jsx-runtime */ +import { assertSlots } from '@fluentui/react-utilities'; +import type { JSXElement } from '@fluentui/react-utilities'; +import type { + TeachingPopoverCarouselFooterSlots, + TeachingPopoverCarouselFooterState, +} from './TeachingPopoverCarouselFooter.types'; + +export const renderTeachingPopoverCarouselFooter = (state: TeachingPopoverCarouselFooterState): JSXElement => { + assertSlots(state); + + return ; +}; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooter/useTeachingPopoverCarouselFooter.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooter/useTeachingPopoverCarouselFooter.ts new file mode 100644 index 00000000000000..0cb7e56def2a73 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooter/useTeachingPopoverCarouselFooter.ts @@ -0,0 +1,14 @@ +import type * as React from 'react'; +import { getIntrinsicElementProps, slot } from '@fluentui/react-utilities'; +import type { + TeachingPopoverCarouselFooterProps, + TeachingPopoverCarouselFooterState, +} from './TeachingPopoverCarouselFooter.types'; + +export const useTeachingPopoverCarouselFooter = ( + props: TeachingPopoverCarouselFooterProps, + ref: React.Ref, +): TeachingPopoverCarouselFooterState => ({ + components: { root: 'div' }, + root: slot.always(getIntrinsicElementProps('div', { ref, ...props }), { elementType: 'div' }), +}); diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooterButton/TeachingPopoverCarouselFooterButton.tsx b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooterButton/TeachingPopoverCarouselFooterButton.tsx new file mode 100644 index 00000000000000..64bf60d65284ea --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooterButton/TeachingPopoverCarouselFooterButton.tsx @@ -0,0 +1,15 @@ +'use client'; + +import * as React from 'react'; +import type { ForwardRefComponent } from '@fluentui/react-utilities'; +import type { TeachingPopoverCarouselFooterButtonProps } from './TeachingPopoverCarouselFooterButton.types'; +import { useTeachingPopoverCarouselFooterButton } from './useTeachingPopoverCarouselFooterButton'; +import { renderTeachingPopoverCarouselFooterButton } from './renderTeachingPopoverCarouselFooterButton'; + +export const TeachingPopoverCarouselFooterButton: ForwardRefComponent = + React.forwardRef((props, ref) => { + const state = useTeachingPopoverCarouselFooterButton(props, ref); + return renderTeachingPopoverCarouselFooterButton(state); + }); + +TeachingPopoverCarouselFooterButton.displayName = 'TeachingPopoverCarouselFooterButton'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooterButton/TeachingPopoverCarouselFooterButton.types.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooterButton/TeachingPopoverCarouselFooterButton.types.ts new file mode 100644 index 00000000000000..4cbc1e7df06769 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooterButton/TeachingPopoverCarouselFooterButton.types.ts @@ -0,0 +1,5 @@ +export type { + TeachingPopoverCarouselFooterButtonBaseProps as TeachingPopoverCarouselFooterButtonProps, + TeachingPopoverCarouselFooterButtonBaseState as TeachingPopoverCarouselFooterButtonState, + TeachingPopoverCarouselFooterButtonSlots, +} from '@fluentui/react-teaching-popover'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooterButton/index.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooterButton/index.ts new file mode 100644 index 00000000000000..d856cd93ae5feb --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooterButton/index.ts @@ -0,0 +1,8 @@ +export { TeachingPopoverCarouselFooterButton } from './TeachingPopoverCarouselFooterButton'; +export { useTeachingPopoverCarouselFooterButton } from './useTeachingPopoverCarouselFooterButton'; +export { renderTeachingPopoverCarouselFooterButton } from './renderTeachingPopoverCarouselFooterButton'; +export type { + TeachingPopoverCarouselFooterButtonProps, + TeachingPopoverCarouselFooterButtonSlots, + TeachingPopoverCarouselFooterButtonState, +} from './TeachingPopoverCarouselFooterButton.types'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooterButton/renderTeachingPopoverCarouselFooterButton.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooterButton/renderTeachingPopoverCarouselFooterButton.ts new file mode 100644 index 00000000000000..58b4612770b39d --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooterButton/renderTeachingPopoverCarouselFooterButton.ts @@ -0,0 +1,7 @@ +import { renderTeachingPopoverCarouselFooterButton_unstable } from '@fluentui/react-teaching-popover'; +import type { JSXElement } from '@fluentui/react-utilities'; +import type { TeachingPopoverCarouselFooterButtonState } from './TeachingPopoverCarouselFooterButton.types'; + +export const renderTeachingPopoverCarouselFooterButton = renderTeachingPopoverCarouselFooterButton_unstable as ( + state: TeachingPopoverCarouselFooterButtonState, +) => JSXElement; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooterButton/useTeachingPopoverCarouselFooterButton.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooterButton/useTeachingPopoverCarouselFooterButton.ts new file mode 100644 index 00000000000000..20b5a5fbc27746 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooterButton/useTeachingPopoverCarouselFooterButton.ts @@ -0,0 +1 @@ +export { useTeachingPopoverCarouselFooterButtonBase_unstable as useTeachingPopoverCarouselFooterButton } from '@fluentui/react-teaching-popover'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNav/TeachingPopoverCarouselNav.tsx b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNav/TeachingPopoverCarouselNav.tsx new file mode 100644 index 00000000000000..1f14f8df92338c --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNav/TeachingPopoverCarouselNav.tsx @@ -0,0 +1,16 @@ +'use client'; + +import * as React from 'react'; +import type { ForwardRefComponent } from '@fluentui/react-utilities'; +import type { TeachingPopoverCarouselNavProps } from './TeachingPopoverCarouselNav.types'; +import { useTeachingPopoverCarouselNav } from './useTeachingPopoverCarouselNav'; +import { renderTeachingPopoverCarouselNav } from './renderTeachingPopoverCarouselNav'; + +export const TeachingPopoverCarouselNav: ForwardRefComponent = React.forwardRef( + (props, ref) => { + const state = useTeachingPopoverCarouselNav(props, ref); + return renderTeachingPopoverCarouselNav(state); + }, +); + +TeachingPopoverCarouselNav.displayName = 'TeachingPopoverCarouselNav'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNav/TeachingPopoverCarouselNav.types.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNav/TeachingPopoverCarouselNav.types.ts new file mode 100644 index 00000000000000..d8c5d7b6b4770f --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNav/TeachingPopoverCarouselNav.types.ts @@ -0,0 +1,15 @@ +import type { TeachingPopoverCarouselNavBaseState } from '@fluentui/react-teaching-popover'; + +export type { + TeachingPopoverCarouselNavBaseProps as TeachingPopoverCarouselNavProps, + TeachingPopoverCarouselNavBaseState as TeachingPopoverCarouselNavState, + TeachingPopoverCarouselNavSlots, +} from '@fluentui/react-teaching-popover'; + +/** + * Render function for the carousel nav buttons. + * + * Derived from the v9 `TeachingPopoverCarouselNavBaseState.renderNavButton` + * field, which is the package's public contract for this shape. + */ +export type NavButtonRenderFunction = TeachingPopoverCarouselNavBaseState['renderNavButton']; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNav/index.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNav/index.ts new file mode 100644 index 00000000000000..6c1cef917871f7 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNav/index.ts @@ -0,0 +1,9 @@ +export { TeachingPopoverCarouselNav } from './TeachingPopoverCarouselNav'; +export { useTeachingPopoverCarouselNav } from './useTeachingPopoverCarouselNav'; +export { renderTeachingPopoverCarouselNav } from './renderTeachingPopoverCarouselNav'; +export type { + NavButtonRenderFunction, + TeachingPopoverCarouselNavProps, + TeachingPopoverCarouselNavSlots, + TeachingPopoverCarouselNavState, +} from './TeachingPopoverCarouselNav.types'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNav/renderTeachingPopoverCarouselNav.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNav/renderTeachingPopoverCarouselNav.ts new file mode 100644 index 00000000000000..fab62afc1d776d --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNav/renderTeachingPopoverCarouselNav.ts @@ -0,0 +1 @@ +export { renderTeachingPopoverCarouselNav_unstable as renderTeachingPopoverCarouselNav } from '@fluentui/react-teaching-popover'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNav/useTeachingPopoverCarouselNav.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNav/useTeachingPopoverCarouselNav.ts new file mode 100644 index 00000000000000..b45308f926dbde --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNav/useTeachingPopoverCarouselNav.ts @@ -0,0 +1 @@ +export { useTeachingPopoverCarouselNavBase_unstable as useTeachingPopoverCarouselNav } from '@fluentui/react-teaching-popover'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNavButton/TeachingPopoverCarouselNavButton.tsx b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNavButton/TeachingPopoverCarouselNavButton.tsx new file mode 100644 index 00000000000000..950ef5cd35f011 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNavButton/TeachingPopoverCarouselNavButton.tsx @@ -0,0 +1,15 @@ +'use client'; + +import * as React from 'react'; +import type { ForwardRefComponent } from '@fluentui/react-utilities'; +import type { TeachingPopoverCarouselNavButtonProps } from './TeachingPopoverCarouselNavButton.types'; +import { useTeachingPopoverCarouselNavButton } from './useTeachingPopoverCarouselNavButton'; +import { renderTeachingPopoverCarouselNavButton } from './renderTeachingPopoverCarouselNavButton'; + +export const TeachingPopoverCarouselNavButton: ForwardRefComponent = + React.forwardRef((props, ref) => { + const state = useTeachingPopoverCarouselNavButton(props, ref); + return renderTeachingPopoverCarouselNavButton(state); + }); + +TeachingPopoverCarouselNavButton.displayName = 'TeachingPopoverCarouselNavButton'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNavButton/TeachingPopoverCarouselNavButton.types.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNavButton/TeachingPopoverCarouselNavButton.types.ts new file mode 100644 index 00000000000000..7dfec37bacd764 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNavButton/TeachingPopoverCarouselNavButton.types.ts @@ -0,0 +1,5 @@ +export type { + TeachingPopoverCarouselNavButtonBaseProps as TeachingPopoverCarouselNavButtonProps, + TeachingPopoverCarouselNavButtonBaseState as TeachingPopoverCarouselNavButtonState, + TeachingPopoverCarouselNavButtonSlots, +} from '@fluentui/react-teaching-popover'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNavButton/index.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNavButton/index.ts new file mode 100644 index 00000000000000..67988db7679214 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNavButton/index.ts @@ -0,0 +1,8 @@ +export { TeachingPopoverCarouselNavButton } from './TeachingPopoverCarouselNavButton'; +export { useTeachingPopoverCarouselNavButton } from './useTeachingPopoverCarouselNavButton'; +export { renderTeachingPopoverCarouselNavButton } from './renderTeachingPopoverCarouselNavButton'; +export type { + TeachingPopoverCarouselNavButtonProps, + TeachingPopoverCarouselNavButtonSlots, + TeachingPopoverCarouselNavButtonState, +} from './TeachingPopoverCarouselNavButton.types'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNavButton/renderTeachingPopoverCarouselNavButton.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNavButton/renderTeachingPopoverCarouselNavButton.ts new file mode 100644 index 00000000000000..5d7a19c1b6b62f --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNavButton/renderTeachingPopoverCarouselNavButton.ts @@ -0,0 +1,7 @@ +import { renderTeachingPopoverCarouselNavButton_unstable } from '@fluentui/react-teaching-popover'; +import type { JSXElement } from '@fluentui/react-utilities'; +import type { TeachingPopoverCarouselNavButtonState } from './TeachingPopoverCarouselNavButton.types'; + +export const renderTeachingPopoverCarouselNavButton = renderTeachingPopoverCarouselNavButton_unstable as ( + state: TeachingPopoverCarouselNavButtonState, +) => JSXElement; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNavButton/useTeachingPopoverCarouselNavButton.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNavButton/useTeachingPopoverCarouselNavButton.ts new file mode 100644 index 00000000000000..bbeeaee8591be6 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselNavButton/useTeachingPopoverCarouselNavButton.ts @@ -0,0 +1 @@ +export { useTeachingPopoverCarouselNavButtonBase_unstable as useTeachingPopoverCarouselNavButton } from '@fluentui/react-teaching-popover'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselPageCount/TeachingPopoverCarouselPageCount.tsx b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselPageCount/TeachingPopoverCarouselPageCount.tsx new file mode 100644 index 00000000000000..0db9501040dbfa --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselPageCount/TeachingPopoverCarouselPageCount.tsx @@ -0,0 +1,15 @@ +'use client'; + +import * as React from 'react'; +import type { ForwardRefComponent } from '@fluentui/react-utilities'; +import type { TeachingPopoverCarouselPageCountProps } from './TeachingPopoverCarouselPageCount.types'; +import { useTeachingPopoverCarouselPageCount } from './useTeachingPopoverCarouselPageCount'; +import { renderTeachingPopoverCarouselPageCount } from './renderTeachingPopoverCarouselPageCount'; + +export const TeachingPopoverCarouselPageCount: ForwardRefComponent = + React.forwardRef((props, ref) => { + const state = useTeachingPopoverCarouselPageCount(props, ref); + return renderTeachingPopoverCarouselPageCount(state); + }); + +TeachingPopoverCarouselPageCount.displayName = 'TeachingPopoverCarouselPageCount'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselPageCount/TeachingPopoverCarouselPageCount.types.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselPageCount/TeachingPopoverCarouselPageCount.types.ts new file mode 100644 index 00000000000000..66b1eb6baf46f9 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselPageCount/TeachingPopoverCarouselPageCount.types.ts @@ -0,0 +1,6 @@ +export type { + TeachingPopoverCarouselPageCountProps, + TeachingPopoverCarouselPageCountRenderFunction, + TeachingPopoverCarouselPageCountSlots, + TeachingPopoverCarouselPageCountState, +} from '@fluentui/react-teaching-popover'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselPageCount/index.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselPageCount/index.ts new file mode 100644 index 00000000000000..0dcdbf4256f6e6 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselPageCount/index.ts @@ -0,0 +1,9 @@ +export { TeachingPopoverCarouselPageCount } from './TeachingPopoverCarouselPageCount'; +export { useTeachingPopoverCarouselPageCount } from './useTeachingPopoverCarouselPageCount'; +export { renderTeachingPopoverCarouselPageCount } from './renderTeachingPopoverCarouselPageCount'; +export type { + TeachingPopoverCarouselPageCountProps, + TeachingPopoverCarouselPageCountRenderFunction, + TeachingPopoverCarouselPageCountSlots, + TeachingPopoverCarouselPageCountState, +} from './TeachingPopoverCarouselPageCount.types'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselPageCount/renderTeachingPopoverCarouselPageCount.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselPageCount/renderTeachingPopoverCarouselPageCount.ts new file mode 100644 index 00000000000000..5798ec16684b31 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselPageCount/renderTeachingPopoverCarouselPageCount.ts @@ -0,0 +1 @@ +export { renderTeachingPopoverCarouselPageCount_unstable as renderTeachingPopoverCarouselPageCount } from '@fluentui/react-teaching-popover'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselPageCount/useTeachingPopoverCarouselPageCount.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselPageCount/useTeachingPopoverCarouselPageCount.ts new file mode 100644 index 00000000000000..a0a18015d5f719 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselPageCount/useTeachingPopoverCarouselPageCount.ts @@ -0,0 +1 @@ +export { useTeachingPopoverCarouselPageCount_unstable as useTeachingPopoverCarouselPageCount } from '@fluentui/react-teaching-popover'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverFooter/TeachingPopoverFooter.tsx b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverFooter/TeachingPopoverFooter.tsx new file mode 100644 index 00000000000000..120f7c363d83ab --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverFooter/TeachingPopoverFooter.tsx @@ -0,0 +1,14 @@ +'use client'; + +import * as React from 'react'; +import type { ForwardRefComponent } from '@fluentui/react-utilities'; +import type { TeachingPopoverFooterProps } from './TeachingPopoverFooter.types'; +import { useTeachingPopoverFooter } from './useTeachingPopoverFooter'; +import { renderTeachingPopoverFooter } from './renderTeachingPopoverFooter'; + +export const TeachingPopoverFooter: ForwardRefComponent = React.forwardRef((props, ref) => { + const state = useTeachingPopoverFooter(props, ref); + return renderTeachingPopoverFooter(state); +}); + +TeachingPopoverFooter.displayName = 'TeachingPopoverFooter'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverFooter/TeachingPopoverFooter.types.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverFooter/TeachingPopoverFooter.types.ts new file mode 100644 index 00000000000000..b4e52191960dee --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverFooter/TeachingPopoverFooter.types.ts @@ -0,0 +1,5 @@ +import type { TeachingPopoverFooterBaseProps, TeachingPopoverFooterBaseState } from '@fluentui/react-teaching-popover'; + +export type TeachingPopoverFooterProps = TeachingPopoverFooterBaseProps; + +export type TeachingPopoverFooterState = TeachingPopoverFooterBaseState; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverFooter/index.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverFooter/index.ts new file mode 100644 index 00000000000000..c707b46e7fb6dc --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverFooter/index.ts @@ -0,0 +1,4 @@ +export { TeachingPopoverFooter } from './TeachingPopoverFooter'; +export { useTeachingPopoverFooter } from './useTeachingPopoverFooter'; +export { renderTeachingPopoverFooter } from './renderTeachingPopoverFooter'; +export type { TeachingPopoverFooterProps, TeachingPopoverFooterState } from './TeachingPopoverFooter.types'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverFooter/renderTeachingPopoverFooter.tsx b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverFooter/renderTeachingPopoverFooter.tsx new file mode 100644 index 00000000000000..09e91fd559a944 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverFooter/renderTeachingPopoverFooter.tsx @@ -0,0 +1,16 @@ +/** @jsxRuntime automatic */ +/** @jsxImportSource @fluentui/react-jsx-runtime */ +import { assertSlots } from '@fluentui/react-utilities'; +import type { JSXElement } from '@fluentui/react-utilities'; +import type { TeachingPopoverFooterState } from './TeachingPopoverFooter.types'; + +/** + * The headless footer leaves button composition to consumers — unlike the + * v9 render which emits dedicated `primary`/`secondary` Button slots that + * the headless base hook intentionally omits. + */ +export const renderTeachingPopoverFooter = (state: TeachingPopoverFooterState): JSXElement => { + assertSlots<{ root: NonNullable }>(state); + + return ; +}; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverFooter/useTeachingPopoverFooter.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverFooter/useTeachingPopoverFooter.ts new file mode 100644 index 00000000000000..b76c06142bfbbd --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverFooter/useTeachingPopoverFooter.ts @@ -0,0 +1 @@ +export { useTeachingPopoverFooterBase_unstable as useTeachingPopoverFooter } from '@fluentui/react-teaching-popover'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverHeader/TeachingPopoverHeader.tsx b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverHeader/TeachingPopoverHeader.tsx new file mode 100644 index 00000000000000..22a5e686afe947 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverHeader/TeachingPopoverHeader.tsx @@ -0,0 +1,14 @@ +'use client'; + +import * as React from 'react'; +import type { ForwardRefComponent } from '@fluentui/react-utilities'; +import type { TeachingPopoverHeaderProps } from './TeachingPopoverHeader.types'; +import { useTeachingPopoverHeader } from './useTeachingPopoverHeader'; +import { renderTeachingPopoverHeader } from './renderTeachingPopoverHeader'; + +export const TeachingPopoverHeader: ForwardRefComponent = React.forwardRef((props, ref) => { + const state = useTeachingPopoverHeader(props, ref); + return renderTeachingPopoverHeader(state); +}); + +TeachingPopoverHeader.displayName = 'TeachingPopoverHeader'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverHeader/TeachingPopoverHeader.types.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverHeader/TeachingPopoverHeader.types.ts new file mode 100644 index 00000000000000..918fb56e19c9a6 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverHeader/TeachingPopoverHeader.types.ts @@ -0,0 +1,11 @@ +import type { + TeachingPopoverHeaderBaseProps, + TeachingPopoverHeaderBaseState, + TeachingPopoverHeaderSlots, +} from '@fluentui/react-teaching-popover'; + +export type TeachingPopoverHeaderProps = TeachingPopoverHeaderBaseProps; + +export type TeachingPopoverHeaderState = TeachingPopoverHeaderBaseState; + +export type { TeachingPopoverHeaderSlots }; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverHeader/index.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverHeader/index.ts new file mode 100644 index 00000000000000..cc67d538310a3e --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverHeader/index.ts @@ -0,0 +1,8 @@ +export { TeachingPopoverHeader } from './TeachingPopoverHeader'; +export { useTeachingPopoverHeader } from './useTeachingPopoverHeader'; +export { renderTeachingPopoverHeader } from './renderTeachingPopoverHeader'; +export type { + TeachingPopoverHeaderProps, + TeachingPopoverHeaderSlots, + TeachingPopoverHeaderState, +} from './TeachingPopoverHeader.types'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverHeader/renderTeachingPopoverHeader.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverHeader/renderTeachingPopoverHeader.ts new file mode 100644 index 00000000000000..b1c1142eb79eb0 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverHeader/renderTeachingPopoverHeader.ts @@ -0,0 +1,11 @@ +import { renderTeachingPopoverHeader_unstable } from '@fluentui/react-teaching-popover'; +import type { JSXElement } from '@fluentui/react-utilities'; +import type { TeachingPopoverHeaderState } from './TeachingPopoverHeader.types'; + +/** + * v9's render asserts a full `TeachingPopoverHeaderState` (which includes + * `appearance`). The base state intentionally omits it, but the render + * only reads slot fields — safe to cast. + */ +export const renderTeachingPopoverHeader = (state: TeachingPopoverHeaderState): JSXElement => + renderTeachingPopoverHeader_unstable(state as Parameters[0]); diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverHeader/useTeachingPopoverHeader.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverHeader/useTeachingPopoverHeader.ts new file mode 100644 index 00000000000000..82ee8f1e2abcfc --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverHeader/useTeachingPopoverHeader.ts @@ -0,0 +1 @@ +export { useTeachingPopoverHeaderBase_unstable as useTeachingPopoverHeader } from '@fluentui/react-teaching-popover'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverSurface/TeachingPopoverSurface.tsx b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverSurface/TeachingPopoverSurface.tsx new file mode 100644 index 00000000000000..cb1c2d807fbd3d --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverSurface/TeachingPopoverSurface.tsx @@ -0,0 +1 @@ +export { PopoverSurface as TeachingPopoverSurface } from '../../Popover/PopoverSurface/PopoverSurface'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverSurface/TeachingPopoverSurface.types.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverSurface/TeachingPopoverSurface.types.ts new file mode 100644 index 00000000000000..9c95aae7ba3e17 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverSurface/TeachingPopoverSurface.types.ts @@ -0,0 +1,5 @@ +export type { + PopoverSurfaceSlots as TeachingPopoverSurfaceSlots, + PopoverSurfaceProps as TeachingPopoverSurfaceProps, + PopoverSurfaceState as TeachingPopoverSurfaceState, +} from '../../Popover/PopoverSurface/PopoverSurface.types'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverSurface/index.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverSurface/index.ts new file mode 100644 index 00000000000000..57cf99f6e0edb1 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverSurface/index.ts @@ -0,0 +1,8 @@ +export { TeachingPopoverSurface } from './TeachingPopoverSurface'; +export { useTeachingPopoverSurface } from './useTeachingPopoverSurface'; +export { renderTeachingPopoverSurface } from './renderTeachingPopoverSurface'; +export type { + TeachingPopoverSurfaceSlots, + TeachingPopoverSurfaceProps, + TeachingPopoverSurfaceState, +} from './TeachingPopoverSurface.types'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverSurface/renderTeachingPopoverSurface.tsx b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverSurface/renderTeachingPopoverSurface.tsx new file mode 100644 index 00000000000000..a9a47ead60481f --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverSurface/renderTeachingPopoverSurface.tsx @@ -0,0 +1 @@ +export { renderPopoverSurface as renderTeachingPopoverSurface } from '../../Popover/PopoverSurface/renderPopoverSurface'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverSurface/useTeachingPopoverSurface.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverSurface/useTeachingPopoverSurface.ts new file mode 100644 index 00000000000000..0ae40ec8f123a1 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverSurface/useTeachingPopoverSurface.ts @@ -0,0 +1 @@ +export { usePopoverSurface as useTeachingPopoverSurface } from '../../Popover/PopoverSurface/usePopoverSurface'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTitle/TeachingPopoverTitle.tsx b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTitle/TeachingPopoverTitle.tsx new file mode 100644 index 00000000000000..8ae7a2cece3cb8 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTitle/TeachingPopoverTitle.tsx @@ -0,0 +1,14 @@ +'use client'; + +import * as React from 'react'; +import type { ForwardRefComponent } from '@fluentui/react-utilities'; +import type { TeachingPopoverTitleProps } from './TeachingPopoverTitle.types'; +import { useTeachingPopoverTitle } from './useTeachingPopoverTitle'; +import { renderTeachingPopoverTitle } from './renderTeachingPopoverTitle'; + +export const TeachingPopoverTitle: ForwardRefComponent = React.forwardRef((props, ref) => { + const state = useTeachingPopoverTitle(props, ref); + return renderTeachingPopoverTitle(state); +}); + +TeachingPopoverTitle.displayName = 'TeachingPopoverTitle'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTitle/TeachingPopoverTitle.types.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTitle/TeachingPopoverTitle.types.ts new file mode 100644 index 00000000000000..00ec8519bf9a00 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTitle/TeachingPopoverTitle.types.ts @@ -0,0 +1,11 @@ +import type { + TeachingPopoverTitleBaseProps, + TeachingPopoverTitleBaseState, + TeachingPopoverTitleSlots, +} from '@fluentui/react-teaching-popover'; + +export type TeachingPopoverTitleProps = TeachingPopoverTitleBaseProps; + +export type TeachingPopoverTitleState = TeachingPopoverTitleBaseState; + +export type { TeachingPopoverTitleSlots }; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTitle/index.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTitle/index.ts new file mode 100644 index 00000000000000..ba438d142db770 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTitle/index.ts @@ -0,0 +1,8 @@ +export { TeachingPopoverTitle } from './TeachingPopoverTitle'; +export { useTeachingPopoverTitle } from './useTeachingPopoverTitle'; +export { renderTeachingPopoverTitle } from './renderTeachingPopoverTitle'; +export type { + TeachingPopoverTitleProps, + TeachingPopoverTitleSlots, + TeachingPopoverTitleState, +} from './TeachingPopoverTitle.types'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTitle/renderTeachingPopoverTitle.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTitle/renderTeachingPopoverTitle.ts new file mode 100644 index 00000000000000..0035964ed061a6 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTitle/renderTeachingPopoverTitle.ts @@ -0,0 +1,10 @@ +import { renderTeachingPopoverTitle_unstable } from '@fluentui/react-teaching-popover'; +import type { JSXElement } from '@fluentui/react-utilities'; +import type { TeachingPopoverTitleState } from './TeachingPopoverTitle.types'; + +/** + * Cast to v9's render signature — base state omits `appearance` and the + * render only reads slot fields. + */ +export const renderTeachingPopoverTitle = (state: TeachingPopoverTitleState): JSXElement => + renderTeachingPopoverTitle_unstable(state as Parameters[0]); diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTitle/useTeachingPopoverTitle.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTitle/useTeachingPopoverTitle.ts new file mode 100644 index 00000000000000..c0da4bf53107d5 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTitle/useTeachingPopoverTitle.ts @@ -0,0 +1 @@ +export { useTeachingPopoverTitleBase_unstable as useTeachingPopoverTitle } from '@fluentui/react-teaching-popover'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTrigger/TeachingPopoverTrigger.tsx b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTrigger/TeachingPopoverTrigger.tsx new file mode 100644 index 00000000000000..a1846c9e6f3cf5 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTrigger/TeachingPopoverTrigger.tsx @@ -0,0 +1 @@ +export { PopoverTrigger as TeachingPopoverTrigger } from '../../Popover/PopoverTrigger/PopoverTrigger'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTrigger/TeachingPopoverTrigger.types.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTrigger/TeachingPopoverTrigger.types.ts new file mode 100644 index 00000000000000..4fc687e3f0ed75 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTrigger/TeachingPopoverTrigger.types.ts @@ -0,0 +1,5 @@ +export type { + PopoverTriggerProps as TeachingPopoverTriggerProps, + PopoverTriggerState as TeachingPopoverTriggerState, + PopoverTriggerChildProps as TeachingPopoverTriggerChildProps, +} from '../../Popover/PopoverTrigger/PopoverTrigger.types'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTrigger/index.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTrigger/index.ts new file mode 100644 index 00000000000000..f55474197a1469 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTrigger/index.ts @@ -0,0 +1,8 @@ +export { TeachingPopoverTrigger } from './TeachingPopoverTrigger'; +export { useTeachingPopoverTrigger } from './useTeachingPopoverTrigger'; +export { renderTeachingPopoverTrigger } from './renderTeachingPopoverTrigger'; +export type { + TeachingPopoverTriggerProps, + TeachingPopoverTriggerState, + TeachingPopoverTriggerChildProps, +} from './TeachingPopoverTrigger.types'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTrigger/renderTeachingPopoverTrigger.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTrigger/renderTeachingPopoverTrigger.ts new file mode 100644 index 00000000000000..f9b2198f6968c3 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTrigger/renderTeachingPopoverTrigger.ts @@ -0,0 +1 @@ +export { renderPopoverTrigger as renderTeachingPopoverTrigger } from '../../Popover/PopoverTrigger/renderPopoverTrigger'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTrigger/useTeachingPopoverTrigger.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTrigger/useTeachingPopoverTrigger.ts new file mode 100644 index 00000000000000..3cc001b10e140b --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverTrigger/useTeachingPopoverTrigger.ts @@ -0,0 +1 @@ +export { usePopoverTrigger as useTeachingPopoverTrigger } from '../../Popover/PopoverTrigger/usePopoverTrigger'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/index.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/index.ts new file mode 100644 index 00000000000000..59ef4828fbd7a1 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/index.ts @@ -0,0 +1,137 @@ +export { TeachingPopover } from './TeachingPopover'; +export { useTeachingPopover } from './useTeachingPopover'; +export { useTeachingPopoverContextValues } from './useTeachingPopoverContextValues'; +export { renderTeachingPopover } from './renderTeachingPopover'; +export type { + TeachingPopoverProps, + TeachingPopoverState, + TeachingPopoverContextValues, + TeachingPopoverBaseBridgedContextValue, +} from './TeachingPopover.types'; + +export { + TeachingPopoverTrigger, + useTeachingPopoverTrigger, + renderTeachingPopoverTrigger, +} from './TeachingPopoverTrigger'; +export type { + TeachingPopoverTriggerProps, + TeachingPopoverTriggerState, + TeachingPopoverTriggerChildProps, +} from './TeachingPopoverTrigger'; + +export { + TeachingPopoverSurface, + useTeachingPopoverSurface, + renderTeachingPopoverSurface, +} from './TeachingPopoverSurface'; +export type { + TeachingPopoverSurfaceProps, + TeachingPopoverSurfaceSlots, + TeachingPopoverSurfaceState, +} from './TeachingPopoverSurface'; + +export { TeachingPopoverBody, useTeachingPopoverBody, renderTeachingPopoverBody } from './TeachingPopoverBody'; +export type { + TeachingPopoverBodyProps, + TeachingPopoverBodySlots, + TeachingPopoverBodyState, +} from './TeachingPopoverBody'; + +export { TeachingPopoverHeader, useTeachingPopoverHeader, renderTeachingPopoverHeader } from './TeachingPopoverHeader'; +export type { + TeachingPopoverHeaderProps, + TeachingPopoverHeaderSlots, + TeachingPopoverHeaderState, +} from './TeachingPopoverHeader'; + +export { TeachingPopoverTitle, useTeachingPopoverTitle, renderTeachingPopoverTitle } from './TeachingPopoverTitle'; +export type { + TeachingPopoverTitleProps, + TeachingPopoverTitleSlots, + TeachingPopoverTitleState, +} from './TeachingPopoverTitle'; + +export { TeachingPopoverFooter, useTeachingPopoverFooter, renderTeachingPopoverFooter } from './TeachingPopoverFooter'; +export type { TeachingPopoverFooterProps, TeachingPopoverFooterState } from './TeachingPopoverFooter'; + +export { + TeachingPopoverCarousel, + useTeachingPopoverCarousel, + useTeachingPopoverCarouselContextValues, + renderTeachingPopoverCarousel, +} from './TeachingPopoverCarousel'; +export type { + TeachingPopoverCarouselProps, + TeachingPopoverCarouselSlots, + TeachingPopoverCarouselState, + TeachingPopoverCarouselContextValues, +} from './TeachingPopoverCarousel'; + +export { + TeachingPopoverCarouselCard, + useTeachingPopoverCarouselCard, + renderTeachingPopoverCarouselCard, +} from './TeachingPopoverCarouselCard'; +export type { + TeachingPopoverCarouselCardProps, + TeachingPopoverCarouselCardSlots, + TeachingPopoverCarouselCardState, +} from './TeachingPopoverCarouselCard'; + +export { + TeachingPopoverCarouselFooter, + useTeachingPopoverCarouselFooter, + renderTeachingPopoverCarouselFooter, +} from './TeachingPopoverCarouselFooter'; +export type { + TeachingPopoverCarouselFooterProps, + TeachingPopoverCarouselFooterSlots, + TeachingPopoverCarouselFooterState, +} from './TeachingPopoverCarouselFooter'; + +export { + TeachingPopoverCarouselFooterButton, + useTeachingPopoverCarouselFooterButton, + renderTeachingPopoverCarouselFooterButton, +} from './TeachingPopoverCarouselFooterButton'; +export type { + TeachingPopoverCarouselFooterButtonProps, + TeachingPopoverCarouselFooterButtonSlots, + TeachingPopoverCarouselFooterButtonState, +} from './TeachingPopoverCarouselFooterButton'; + +export { + TeachingPopoverCarouselNav, + useTeachingPopoverCarouselNav, + renderTeachingPopoverCarouselNav, +} from './TeachingPopoverCarouselNav'; +export type { + NavButtonRenderFunction, + TeachingPopoverCarouselNavProps, + TeachingPopoverCarouselNavSlots, + TeachingPopoverCarouselNavState, +} from './TeachingPopoverCarouselNav'; + +export { + TeachingPopoverCarouselNavButton, + useTeachingPopoverCarouselNavButton, + renderTeachingPopoverCarouselNavButton, +} from './TeachingPopoverCarouselNavButton'; +export type { + TeachingPopoverCarouselNavButtonProps, + TeachingPopoverCarouselNavButtonSlots, + TeachingPopoverCarouselNavButtonState, +} from './TeachingPopoverCarouselNavButton'; + +export { + TeachingPopoverCarouselPageCount, + useTeachingPopoverCarouselPageCount, + renderTeachingPopoverCarouselPageCount, +} from './TeachingPopoverCarouselPageCount'; +export type { + TeachingPopoverCarouselPageCountProps, + TeachingPopoverCarouselPageCountRenderFunction, + TeachingPopoverCarouselPageCountSlots, + TeachingPopoverCarouselPageCountState, +} from './TeachingPopoverCarouselPageCount'; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/renderTeachingPopover.tsx b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/renderTeachingPopover.tsx new file mode 100644 index 00000000000000..d45b36edd82c0c --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/renderTeachingPopover.tsx @@ -0,0 +1,27 @@ +import * as React from 'react'; +import { + PopoverProvider as BasePopoverProvider, + type PopoverContextValue as BasePopoverContextValue, +} from '@fluentui/react-popover'; +import { PopoverProvider } from '../Popover/popoverContext'; +import type { TeachingPopoverContextValues, TeachingPopoverState } from './TeachingPopover.types'; + +/** + * Renders TeachingPopover by providing both the headless `PopoverContext` + * (consumed by headless sub-components) and the `@fluentui/react-popover` + * `PopoverContext` (consumed by `@fluentui/react-teaching-popover` base + * hooks). The bridged value is cast to `BasePopoverContextValue` — the + * omitted fields (`size`, `inline`, etc.) are styling concerns that no base + * hook reads. + */ +export const renderTeachingPopover = ( + state: TeachingPopoverState, + contextValues: TeachingPopoverContextValues, +): React.ReactElement => ( + + + {state.popoverTrigger} + {state.open ? state.popoverSurface : null} + + +); diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/useTeachingPopover.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/useTeachingPopover.ts new file mode 100644 index 00000000000000..831923bdde6ae8 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/useTeachingPopover.ts @@ -0,0 +1,14 @@ +'use client'; + +import { usePopover } from '../Popover/usePopover'; +import type { TeachingPopoverProps, TeachingPopoverState } from './TeachingPopover.types'; + +/** + * Returns the state for a TeachingPopover component. + * + * Built on top of the headless `Popover` and defaults `withArrow` to `true`, + * matching the v9 TeachingPopover convention. + */ +export const useTeachingPopover = (props: TeachingPopoverProps): TeachingPopoverState => { + return usePopover({ withArrow: true, ...props }); +}; diff --git a/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/useTeachingPopoverContextValues.ts b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/useTeachingPopoverContextValues.ts new file mode 100644 index 00000000000000..d85302a2970137 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/useTeachingPopoverContextValues.ts @@ -0,0 +1,55 @@ +'use client'; + +import * as React from 'react'; +import { usePopoverContextValues } from '../Popover/usePopover'; +import type { + TeachingPopoverContextValues, + TeachingPopoverState, + TeachingPopoverBaseBridgedContextValue, +} from './TeachingPopover.types'; + +type BaseSetOpen = TeachingPopoverBaseBridgedContextValue['setOpen']; +type BaseToggleOpen = TeachingPopoverBaseBridgedContextValue['toggleOpen']; + +/** + * Builds both the headless `PopoverContext` value and a + * `@fluentui/react-popover`-compatible `PopoverContext` value. The bridge + * lets sub-components consume base hooks from + * `@fluentui/react-teaching-popover` (e.g. `useTeachingPopoverHeaderBase_unstable`), + * which read `toggleOpen` / `setOpen` / `triggerRef` from that context. + * + * The `@fluentui/react-popover` `OpenPopoverEvents` union is wider than the + * headless one (it accepts `FocusEvent`). Base hooks never fire focus-driven + * dismisses, so casting `state.setOpen` / `state.toggleOpen` to those + * signatures is safe — no extra event types reach them in practice. + */ +export const useTeachingPopoverContextValues = (state: TeachingPopoverState): TeachingPopoverContextValues => { + const { popover } = usePopoverContextValues(state); + + const basePopover = React.useMemo( + () => ({ + open: state.open, + setOpen: state.setOpen as unknown as BaseSetOpen, + toggleOpen: state.toggleOpen as unknown as BaseToggleOpen, + triggerRef: state.triggerRef, + contentRef: state.contentRef, + arrowRef: state.arrowRef, + openOnHover: state.openOnHover, + openOnContext: state.openOnContext, + withArrow: state.withArrow, + }), + [ + state.open, + state.setOpen, + state.toggleOpen, + state.triggerRef, + state.contentRef, + state.arrowRef, + state.openOnHover, + state.openOnContext, + state.withArrow, + ], + ); + + return { popover, basePopover }; +}; diff --git a/packages/react-components/react-headless-components-preview/library/src/teaching-popover.ts b/packages/react-components/react-headless-components-preview/library/src/teaching-popover.ts new file mode 100644 index 00000000000000..88c13e8c377aae --- /dev/null +++ b/packages/react-components/react-headless-components-preview/library/src/teaching-popover.ts @@ -0,0 +1,93 @@ +export { + TeachingPopover, + useTeachingPopover, + useTeachingPopoverContextValues, + renderTeachingPopover, + TeachingPopoverTrigger, + useTeachingPopoverTrigger, + renderTeachingPopoverTrigger, + TeachingPopoverSurface, + useTeachingPopoverSurface, + renderTeachingPopoverSurface, + TeachingPopoverBody, + useTeachingPopoverBody, + renderTeachingPopoverBody, + TeachingPopoverHeader, + useTeachingPopoverHeader, + renderTeachingPopoverHeader, + TeachingPopoverTitle, + useTeachingPopoverTitle, + renderTeachingPopoverTitle, + TeachingPopoverFooter, + useTeachingPopoverFooter, + renderTeachingPopoverFooter, + TeachingPopoverCarousel, + useTeachingPopoverCarousel, + useTeachingPopoverCarouselContextValues, + renderTeachingPopoverCarousel, + TeachingPopoverCarouselCard, + useTeachingPopoverCarouselCard, + renderTeachingPopoverCarouselCard, + TeachingPopoverCarouselFooter, + useTeachingPopoverCarouselFooter, + renderTeachingPopoverCarouselFooter, + TeachingPopoverCarouselFooterButton, + useTeachingPopoverCarouselFooterButton, + renderTeachingPopoverCarouselFooterButton, + TeachingPopoverCarouselNav, + useTeachingPopoverCarouselNav, + renderTeachingPopoverCarouselNav, + TeachingPopoverCarouselNavButton, + useTeachingPopoverCarouselNavButton, + renderTeachingPopoverCarouselNavButton, + TeachingPopoverCarouselPageCount, + useTeachingPopoverCarouselPageCount, + renderTeachingPopoverCarouselPageCount, +} from './components/TeachingPopover'; +export type { + TeachingPopoverProps, + TeachingPopoverState, + TeachingPopoverContextValues, + TeachingPopoverBaseBridgedContextValue, + TeachingPopoverTriggerProps, + TeachingPopoverTriggerState, + TeachingPopoverTriggerChildProps, + TeachingPopoverSurfaceProps, + TeachingPopoverSurfaceSlots, + TeachingPopoverSurfaceState, + TeachingPopoverBodyProps, + TeachingPopoverBodySlots, + TeachingPopoverBodyState, + TeachingPopoverHeaderProps, + TeachingPopoverHeaderSlots, + TeachingPopoverHeaderState, + TeachingPopoverTitleProps, + TeachingPopoverTitleSlots, + TeachingPopoverTitleState, + TeachingPopoverFooterProps, + TeachingPopoverFooterState, + TeachingPopoverCarouselProps, + TeachingPopoverCarouselSlots, + TeachingPopoverCarouselState, + TeachingPopoverCarouselContextValues, + TeachingPopoverCarouselCardProps, + TeachingPopoverCarouselCardSlots, + TeachingPopoverCarouselCardState, + TeachingPopoverCarouselFooterProps, + TeachingPopoverCarouselFooterSlots, + TeachingPopoverCarouselFooterState, + TeachingPopoverCarouselFooterButtonProps, + TeachingPopoverCarouselFooterButtonSlots, + TeachingPopoverCarouselFooterButtonState, + NavButtonRenderFunction, + TeachingPopoverCarouselNavProps, + TeachingPopoverCarouselNavSlots, + TeachingPopoverCarouselNavState, + TeachingPopoverCarouselNavButtonProps, + TeachingPopoverCarouselNavButtonSlots, + TeachingPopoverCarouselNavButtonState, + TeachingPopoverCarouselPageCountProps, + TeachingPopoverCarouselPageCountRenderFunction, + TeachingPopoverCarouselPageCountSlots, + TeachingPopoverCarouselPageCountState, +} from './components/TeachingPopover'; diff --git a/packages/react-components/react-headless-components-preview/stories/src/TeachingPopover/TeachingPopoverDefault.stories.tsx b/packages/react-components/react-headless-components-preview/stories/src/TeachingPopover/TeachingPopoverDefault.stories.tsx new file mode 100644 index 00000000000000..c4d74d757fc0a3 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/stories/src/TeachingPopover/TeachingPopoverDefault.stories.tsx @@ -0,0 +1,39 @@ +import * as React from 'react'; +import { DismissRegular, ImageRegular, LightbulbRegular } from '@fluentui/react-icons'; +import { + TeachingPopover, + TeachingPopoverBody, + TeachingPopoverFooter, + TeachingPopoverHeader, + TeachingPopoverSurface, + TeachingPopoverTitle, + TeachingPopoverTrigger, +} from '@fluentui/react-headless-components-preview/teaching-popover'; + +import styles from './teaching-popover.module.css'; +import popoverStyles from '../Popover/popover.module.css'; + +export const Default = (): React.ReactNode => ( + + + + + + }} + dismissButton={{ className: styles.dismissButton, children: }} + > + Tips + + }}> + Teaching Bubble Title +

This is a teaching popover body

+
+ + + + +
+
+); diff --git a/packages/react-components/react-headless-components-preview/stories/src/TeachingPopover/TeachingPopoverDescription.md b/packages/react-components/react-headless-components-preview/stories/src/TeachingPopover/TeachingPopoverDescription.md new file mode 100644 index 00000000000000..eecc374abe09bb --- /dev/null +++ b/packages/react-components/react-headless-components-preview/stories/src/TeachingPopover/TeachingPopoverDescription.md @@ -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 `@fluentui/react-teaching-popover` base hooks for its sub-components (`Header`, `Title`, `Footer`, `Carousel*`) and bridges the `@fluentui/react-popover` `PopoverContext` internally so dismiss buttons, finish handlers, and the carousel state machine all work transparently. diff --git a/packages/react-components/react-headless-components-preview/stories/src/TeachingPopover/TeachingPopoverWithCarousel.stories.tsx b/packages/react-components/react-headless-components-preview/stories/src/TeachingPopover/TeachingPopoverWithCarousel.stories.tsx new file mode 100644 index 00000000000000..42257ae3884ad9 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/stories/src/TeachingPopover/TeachingPopoverWithCarousel.stories.tsx @@ -0,0 +1,97 @@ +import * as React from 'react'; +import { DismissRegular } from '@fluentui/react-icons'; +import { + TeachingPopover, + TeachingPopoverBody, + TeachingPopoverCarousel, + TeachingPopoverCarouselCard, + TeachingPopoverCarouselFooter, + TeachingPopoverCarouselFooterButton, + TeachingPopoverCarouselNav, + TeachingPopoverCarouselNavButton, + TeachingPopoverCarouselPageCount, + TeachingPopoverHeader, + TeachingPopoverSurface, + TeachingPopoverTitle, + TeachingPopoverTrigger, +} from '@fluentui/react-headless-components-preview/teaching-popover'; + +import styles from './teaching-popover.module.css'; +import popoverStyles from '../Popover/popover.module.css'; + +const PAGES = ['intro', 'features', 'wrap-up'] as const; + +const dismissButtonSlot = { + className: styles.dismissButton, + children: , +}; + +export const WithCarousel = (): React.ReactNode => ( + + + + + + `Slide ${i + 1} of ${PAGES.length}`}> +
+ + 👋 }} + dismissButton={dismissButtonSlot} + /> + + Welcome +

Let's take a quick tour of the new features.

+
+
+ + + ✨ }} + dismissButton={dismissButtonSlot} + /> + + Better workflows +

Save time with shortcuts you can configure to taste.

+
+
+ + + 🎉 }} + dismissButton={dismissButtonSlot} + /> + + You're ready +

That's the highlights — explore at your own pace.

+
+
+ + + + Back + + + {(value: string) => ( + + )} + + + {(current, total) => `${current} / ${total}`} + + + Next + + +
+
+
+
+); diff --git a/packages/react-components/react-headless-components-preview/stories/src/TeachingPopover/index.stories.tsx b/packages/react-components/react-headless-components-preview/stories/src/TeachingPopover/index.stories.tsx new file mode 100644 index 00000000000000..8c12d7c526fd3a --- /dev/null +++ b/packages/react-components/react-headless-components-preview/stories/src/TeachingPopover/index.stories.tsx @@ -0,0 +1,18 @@ +import { TeachingPopover } from '@fluentui/react-headless-components-preview/teaching-popover'; + +import descriptionMd from './TeachingPopoverDescription.md'; + +export { Default } from './TeachingPopoverDefault.stories'; +export { WithCarousel } from './TeachingPopoverWithCarousel.stories'; + +export default { + title: 'Components/TeachingPopover', + component: TeachingPopover, + parameters: { + docs: { + description: { + component: descriptionMd, + }, + }, + }, +}; diff --git a/packages/react-components/react-headless-components-preview/stories/src/TeachingPopover/teaching-popover.module.css b/packages/react-components/react-headless-components-preview/stories/src/TeachingPopover/teaching-popover.module.css new file mode 100644 index 00000000000000..e8bacfc14a3a11 --- /dev/null +++ b/packages/react-components/react-headless-components-preview/stories/src/TeachingPopover/teaching-popover.module.css @@ -0,0 +1,236 @@ +.surface { + background: var(--bg-elev); + border-radius: var(--radius-lg); + padding: var(--space-5); + min-width: 320px; + max-width: 360px; +} + +.header { + display: flex; + align-items: center; + gap: var(--space-2); + font-size: 13px; + font-weight: 500; + color: var(--text-muted); + margin: 0 0 var(--space-3); +} + +.headerIcon { + display: inline-flex; + align-items: center; + justify-content: center; + width: 16px; + height: 16px; + font-size: 16px; + color: var(--text-muted); +} + +/* Dismiss button — boxed subtle button, mirrors v9 TeachingPopoverHeader__dismissButton. */ +.dismissButton { + display: inline-flex; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; + padding: 0; + margin-inline-start: auto; + border: var(--stroke-thin) solid var(--border-strong); + border-radius: var(--radius-sm); + background: transparent; + color: var(--text-muted); + font-size: 14px; + line-height: 1; + cursor: pointer; + transition: background-color 80ms ease, border-color 80ms ease, color 80ms ease; +} + +.dismissButton:hover { + background: var(--surface-muted); + border-color: var(--border-stronger); + color: var(--text); +} + +.dismissButton:active { + background: var(--surface-sunken); +} + +.dismissButton:focus-visible { + outline: var(--stroke-thick) solid var(--accent); + outline-offset: 1px; +} + +.body { + display: flex; + flex-direction: column; + margin: 0 0 var(--space-4); +} + +/* Media placeholder — 288×176 (v9 'medium' aspect ratio) gray box. */ +.media { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + aspect-ratio: 288 / 176; + background: var(--surface-muted); + border-radius: var(--radius-sm); + margin-bottom: var(--space-3); + color: var(--text-faint); + font-size: 64px; +} + +.title { + font-size: 16px; + font-weight: 600; + color: var(--text); + margin: 0 0 var(--space-1); +} + +.bodyText { + font-size: 14px; + color: var(--text); + line-height: 1.45; + margin: 0; +} + +.footer { + display: flex; + justify-content: flex-end; + gap: var(--space-2); + margin-top: 0; +} + +/* + Action button — mirrors v9 Button medium / secondary appearance: + 32px tall, 1px neutral border, 4px radius, ~96px min-width to match the v9 + TeachingPopoverCarouselFooterButton minimum. +*/ +.actionButton { + display: inline-flex; + align-items: center; + justify-content: center; + height: 32px; + min-width: 96px; + padding: 0 var(--space-3); + border: var(--stroke-thin) solid var(--border-strong); + border-radius: var(--radius-md); + background: var(--bg-elev); + color: var(--text); + font-family: inherit; + font-size: 13px; + font-weight: 600; + line-height: 1; + cursor: pointer; + transition: background-color 80ms ease, border-color 80ms ease, color 80ms ease; +} + +.actionButton:hover { + background: var(--surface-muted); + border-color: var(--border-stronger); +} + +.actionButton:active { + background: var(--surface-sunken); +} + +.actionButton:focus-visible { + outline: var(--stroke-thick) solid var(--accent); + outline-offset: 2px; +} + +.actionButton:disabled { + background: var(--surface-muted); + border-color: var(--border); + color: var(--text-faint); + cursor: not-allowed; +} + +/* Primary variant — mirrors v9 Button primary appearance. */ +.actionButtonPrimary { + background: var(--accent); + border-color: var(--accent); + color: var(--accent-contrast); +} + +.actionButtonPrimary:hover { + background: var(--accent-strong); + border-color: var(--accent-strong); +} + +.actionButtonPrimary:active { + background: var(--accent-strong); + border-color: var(--accent-strong); +} + +.actionButtonPrimary:disabled { + background: var(--accent-soft); + border-color: var(--accent-soft); + color: var(--accent); +} + +.carousel { + display: flex; + flex-direction: column; + gap: var(--space-3); +} + +.carouselCard[hidden] { + display: none; +} + +.carouselFooter { + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--space-2); + margin-top: var(--space-3); +} + +.carouselNav { + display: inline-flex; + align-items: center; + gap: var(--space-2); +} + +/* + Mirrors the v9 TeachingPopoverCarouselNavButton shape: an 8×8 circle when + unselected (30% accent), and a 16×8 rounded-rectangle "pill" when selected + (full accent). Width and border-radius animate so paging feels continuous. +*/ +.carouselNavButton { + display: flex; + box-sizing: border-box; + width: 8px; + height: 8px; + padding: 0; + border: 0; + border-radius: 50%; + background: color-mix(in srgb, var(--accent) 30%, transparent); + cursor: pointer; + transition: width 120ms ease, border-radius 120ms ease, background-color 120ms ease; +} + +@supports not (color: color-mix(in lch, white, black)) { + .carouselNavButton { + background: var(--accent); + opacity: 0.3; + } +} + +.carouselNavButton[aria-selected='true'] { + width: 16px; + border-radius: 4px; + background: var(--accent); + opacity: 1; +} + +.carouselNavButton:focus-visible { + outline: var(--stroke-thick) solid var(--accent); + outline-offset: 2px; +} + +.pageCount { + font-size: 12px; + color: var(--text-muted); +}