Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Carousel: Separate draggable area from controls #33155

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "feat: Add CarouselViewport to correctly define CarouselSlider within a static container",
"packageName": "@fluentui/react-carousel",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "feat: Add CarouselViewport and deprecate CarouselSlider",
"packageName": "@fluentui/react-components",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "feat: Add Carousel CustomStyleHook definitions",
"packageName": "@fluentui/react-provider",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "feat: Add custom style hooks for Carousel components",
"packageName": "@fluentui/react-shared-contexts",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ export type CarouselContextValue = {
enableAutoplay: (autoplay: boolean) => void;
resetAutoplay: () => void;
containerRef?: React_2.RefObject<HTMLDivElement>;
viewportRef?: React_2.RefObject<HTMLDivElement>;
};

// @public
Expand Down Expand Up @@ -246,6 +247,23 @@ export type CarouselSlots = {
// @public
export type CarouselState = ComponentState<CarouselSlots> & CarouselContextValue;

// @public
export const CarouselViewport: ForwardRefComponent<CarouselViewportProps>;

// @public (undocumented)
export const carouselViewportClassNames: SlotClassNames<CarouselViewportSlots>;

// @public
export type CarouselViewportProps = ComponentProps<CarouselViewportSlots>;

// @public (undocumented)
export type CarouselViewportSlots = {
root: Slot<'div'>;
};

// @public
export type CarouselViewportState = ComponentState<Required<CarouselViewportSlots>> & CarouselSliderContextValue;

// @public (undocumented)
export type NavButtonRenderFunction = (index: number) => React_2.ReactNode;

Expand Down Expand Up @@ -276,6 +294,9 @@ export const renderCarouselNavImageButton_unstable: (state: CarouselNavImageButt
// @public
export const renderCarouselSlider_unstable: (state: CarouselSliderState, contextValues: CarouselSliderContextValues) => JSX.Element;

// @public
export const renderCarouselViewport_unstable: (state: CarouselViewportState, contextValues: CarouselSliderContextValues) => JSX.Element;

// @public
export function useCarousel_unstable(props: CarouselProps, ref: React_2.Ref<HTMLDivElement>): CarouselState;

Expand Down Expand Up @@ -333,6 +354,12 @@ export const useCarouselSliderStyles_unstable: (state: CarouselSliderState) => C
// @public
export const useCarouselStyles_unstable: (state: CarouselState) => CarouselState;

// @public
export const useCarouselViewport_unstable: (props: CarouselViewportProps, ref: React_2.Ref<HTMLDivElement>) => CarouselViewportState;

// @public
export const useCarouselViewportStyles_unstable: (state: CarouselViewportState) => CarouselViewportState;

// (No @packageDocumentation comment for this package)

```
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './components/CarouselViewport/index';
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { renderCarousel_unstable } from './renderCarousel';
import { useCarouselStyles_unstable } from './useCarouselStyles.styles';
import type { CarouselProps } from './Carousel.types';
import { useCarouselContextValues_unstable } from './useCarouselContextValues';
import { useCustomStyleHook_unstable } from '@fluentui/react-shared-contexts';

/**
* Carousel is the context wrapper and container for all carousel content/controls,
Expand All @@ -16,11 +17,10 @@ export const Carousel: ForwardRefComponent<CarouselProps> = React.forwardRef((pr
const state = useCarousel_unstable(props, ref);

useCarouselStyles_unstable(state);
useCustomStyleHook_unstable('useCarouselStyles_unstable')(state);

const contextValues = useCarouselContextValues_unstable(state);
// TODO update types in packages/react-components/react-shared-contexts/src/CustomStyleHooksContext/CustomStyleHooksContext.ts
// https://github.com/microsoft/fluentui/blob/master/rfcs/react-components/convergence/custom-styling.md
// useCustomStyleHook_unstable('useCarouselStyles_unstable')(state);

return renderCarousel_unstable(state, contextValues);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function useCarousel_unstable(props: CarouselProps, ref: React.Ref<HTMLDi
} = props;

const { dir } = useFluent();
const { activeIndex, carouselApi, containerRef, subscribeForValues, enableAutoplay, resetAutoplay } =
const { activeIndex, carouselApi, containerRef, viewportRef, subscribeForValues, enableAutoplay, resetAutoplay } =
useEmblaCarousel({
align,
direction: dir,
Expand Down Expand Up @@ -71,7 +71,7 @@ export function useCarousel_unstable(props: CarouselProps, ref: React.Ref<HTMLDi
return nextPageIndex;
});

const mergedRefs = useMergedRefs(ref, containerRef);
const mergedContainerRef = useMergedRefs(ref, containerRef);

// Announce carousel updates
const announcementTextRef = React.useRef<string>('');
Expand Down Expand Up @@ -118,7 +118,7 @@ export function useCarousel_unstable(props: CarouselProps, ref: React.Ref<HTMLDi
},
root: slot.always(
getIntrinsicElementProps('div', {
ref: mergedRefs,
ref: mergedContainerRef,
role: 'region',
...props,
}),
Expand All @@ -127,7 +127,8 @@ export function useCarousel_unstable(props: CarouselProps, ref: React.Ref<HTMLDi

activeIndex,
circular,
containerRef: mergedRefs,
containerRef: mergedContainerRef,
viewportRef,
selectPageByElement,
selectPageByDirection,
selectPageByIndex,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export function useCarouselContextValues_unstable(state: CarouselState): Carouse
resetAutoplay,
circular,
containerRef,
viewportRef,
} = state;

const carousel = React.useMemo(
Expand All @@ -27,6 +28,7 @@ export function useCarouselContextValues_unstable(state: CarouselState): Carouse
resetAutoplay,
circular,
containerRef,
viewportRef,
}),
[
activeIndex,
Expand All @@ -38,6 +40,7 @@ export function useCarouselContextValues_unstable(state: CarouselState): Carouse
resetAutoplay,
circular,
containerRef,
viewportRef,
],
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { makeStyles, mergeClasses } from '@griffel/react';
import type { SlotClassNames } from '@fluentui/react-utilities';

import type { CarouselSlots, CarouselState } from './Carousel.types';
import { tokens } from '@fluentui/react-theme';

export const carouselClassNames: SlotClassNames<CarouselSlots> = {
root: 'fui-Carousel',
Expand All @@ -13,8 +12,8 @@ export const carouselClassNames: SlotClassNames<CarouselSlots> = {
*/
const useStyles = makeStyles({
root: {
paddingTop: tokens.strokeWidthThick, // Leave room for focus border & overflow hidden
overflow: 'hidden',
// Only hide horizontal overflow to enable focus border to bleed bounds vertically
overflowX: 'hidden',
overflowAnchor: 'none',
position: 'relative',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useCarouselAutoplayButton_unstable } from './useCarouselAutoplayButton'
import { renderCarouselAutoplayButton_unstable } from './renderCarouselAutoplayButton';
import { useCarouselAutoplayButtonStyles_unstable } from './useCarouselAutoplayButtonStyles.styles';
import type { CarouselAutoplayButtonProps } from './CarouselAutoplayButton.types';
import { useCustomStyleHook_unstable } from '@fluentui/react-shared-contexts';

/**
* If the Carousel is on auto-play, the user may opt into pausing the auto-play feature via the
Expand All @@ -16,9 +17,8 @@ export const CarouselAutoplayButton: ForwardRefComponent<CarouselAutoplayButtonP
const state = useCarouselAutoplayButton_unstable(props, ref);

useCarouselAutoplayButtonStyles_unstable(state);
// TODO update types in packages/react-components/react-shared-contexts/src/CustomStyleHooksContext/CustomStyleHooksContext.ts
// https://github.com/microsoft/fluentui/blob/master/rfcs/react-components/convergence/custom-styling.md
// useCustomStyleHook_unstable('useCarouselAutoplayButtonStyles_unstable')(state);
useCustomStyleHook_unstable('useCarouselAutoplayButtonStyles_unstable')(state);

return renderCarouselAutoplayButton_unstable(state);
},
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useCarouselButton_unstable } from './useCarouselButton';
import { renderCarouselButton_unstable } from './renderCarouselButton';
import { useCarouselButtonStyles_unstable } from './useCarouselButtonStyles.styles';
import type { CarouselButtonProps } from './CarouselButton.types';
import { useCustomStyleHook_unstable } from '@fluentui/react-shared-contexts';

/**
* A default navigation button that will set value to the next/previous page,
Expand All @@ -13,9 +14,7 @@ export const CarouselButton: ForwardRefComponent<CarouselButtonProps> = React.fo
const state = useCarouselButton_unstable(props, ref);

useCarouselButtonStyles_unstable(state);
// TODO update types in packages/react-components/react-shared-contexts/src/CustomStyleHooksContext/CustomStyleHooksContext.ts
// https://github.com/microsoft/fluentui/blob/master/rfcs/react-components/convergence/custom-styling.md
// useCustomStyleHook_unstable('useCarouselButtonStyles_unstable')(state);
useCustomStyleHook_unstable('useCarouselButtonStyles_unstable')(state);

return renderCarouselButton_unstable(state);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useCarouselCard_unstable } from './useCarouselCard';
import { renderCarouselCard_unstable } from './renderCarouselCard';
import { useCarouselCardStyles_unstable } from './useCarouselCardStyles.styles';
import type { CarouselCardProps } from './CarouselCard.types';
import { useCustomStyleHook_unstable } from '@fluentui/react-shared-contexts';

/**
* The defining wrapper of a carousel's indexed content, they will take up the full
Expand All @@ -17,9 +18,8 @@ export const CarouselCard: ForwardRefComponent<CarouselCardProps> = React.forwar
const state = useCarouselCard_unstable(props, ref);

useCarouselCardStyles_unstable(state);
// TODO update types in packages/react-components/react-shared-contexts/src/CustomStyleHooksContext/CustomStyleHooksContext.ts
// https://github.com/microsoft/fluentui/blob/master/rfcs/react-components/convergence/custom-styling.md
// useCustomStyleHook_unstable('useCarouselCardStyles_unstable')(state);
useCustomStyleHook_unstable('useCarouselCardStyles_unstable')(state);

return renderCarouselCard_unstable(state);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export const useCarouselCard_unstable = (
}
}, [cardFocus]);

const handleFocusCapture = React.useCallback(
const handleFocus = React.useCallback(
(e: React.FocusEvent) => {
if (!e.defaultPrevented && isHTMLElement(e.currentTarget) && !isMouseEvent.current) {
// We want to prevent any browser scroll intervention for 'offscreen' focus
Expand All @@ -88,7 +88,7 @@ export const useCarouselCard_unstable = (
}
};

const onFocusCapture = mergeCallbacks(props.onFocusCapture, handleFocusCapture);
const onFocus = mergeCallbacks(props.onFocus, handleFocus);
const onMouseUp = mergeCallbacks(props.onMouseUp, handleMouseUp);
const onMouseDown = mergeCallbacks(props.onMouseDown, handleMouseDown);
const state: CarouselCardState = {
Expand All @@ -103,7 +103,7 @@ export const useCarouselCard_unstable = (
tabIndex: cardFocus ? 0 : undefined,
...props,
id,
onFocusCapture,
onFocus,
onMouseDown,
onMouseUp,
...focusAttrProps,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const carouselContextDefaultValue: CarouselContextValue = {
},
circular: false,
containerRef: undefined,
viewportRef: undefined,
};

const CarouselContext = createContext<CarouselContextValue | undefined>(undefined);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ export type CarouselContextValue = {
subscribeForValues: (listener: (data: CarouselUpdateData) => void) => () => void;
enableAutoplay: (autoplay: boolean) => void;
resetAutoplay: () => void;
// Container with controls passed to carousel engine
containerRef?: React.RefObject<HTMLDivElement>;
// Viewport without controls used for interactive functionality (draggable, pause autoplay etc.)
viewportRef?: React.RefObject<HTMLDivElement>;
};

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useCarouselNavContextValues_unstable } from './CarouselNavContext';
import { renderCarouselNav_unstable } from './renderCarouselNav';
import { useCarouselNav_unstable } from './useCarouselNav';
import { useCarouselNavStyles_unstable } from './useCarouselNavStyles.styles';
import { useCustomStyleHook_unstable } from '@fluentui/react-shared-contexts';

/**
* Used to jump to a card based on index, using arrow navigation via Tabster.
Expand All @@ -18,9 +19,7 @@ export const CarouselNav: ForwardRefComponent<CarouselNavProps> = React.forwardR
const contextValues = useCarouselNavContextValues_unstable(state);

useCarouselNavStyles_unstable(state);
// TODO update types in packages/react-components/react-shared-contexts/src/CustomStyleHooksContext/CustomStyleHooksContext.ts
// https://github.com/microsoft/fluentui/blob/master/rfcs/react-components/convergence/custom-styling.md
// useCustomStyleHook_unstable('useCarouselNavStyles_unstable')(state);
useCustomStyleHook_unstable('useCarouselNavStyles_unstable')(state);

return renderCarouselNav_unstable(state, contextValues);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useCarouselNavButton_unstable } from './useCarouselNavButton';
import { renderCarouselNavButton_unstable } from './renderCarouselNavButton';
import { useCarouselNavButtonStyles_unstable } from './useCarouselNavButtonStyles.styles';
import type { CarouselNavButtonProps } from './CarouselNavButton.types';
import { useCustomStyleHook_unstable } from '@fluentui/react-shared-contexts';

/**
* The child element of CarouselNav, a singular button that will set the carousels active value on click.
Expand All @@ -12,9 +13,8 @@ export const CarouselNavButton: ForwardRefComponent<CarouselNavButtonProps> = Re
const state = useCarouselNavButton_unstable(props, ref);

useCarouselNavButtonStyles_unstable(state);
// TODO update types in packages/react-components/react-shared-contexts/src/CustomStyleHooksContext/CustomStyleHooksContext.ts
// https://github.com/microsoft/fluentui/blob/master/rfcs/react-components/convergence/custom-styling.md
// useCustomStyleHook_unstable('useCarouselNavButtonStyles_unstable')(state);
useCustomStyleHook_unstable('useCarouselNavButtonStyles_unstable')(state);

return renderCarouselNavButton_unstable(state);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useCarouselNavContainer_unstable } from './useCarouselNavContainer';
import { renderCarouselNavContainer_unstable } from './renderCarouselNavContainer';
import { useCarouselNavContainerStyles_unstable } from './useCarouselNavContainerStyles.styles';
import type { CarouselNavContainerProps } from './CarouselNavContainer.types';
import { useCustomStyleHook_unstable } from '@fluentui/react-shared-contexts';

/**
* CarouselNavContainer component - This container will provide multiple valid layout options for the underlying carousel controls
Expand All @@ -12,16 +13,7 @@ export const CarouselNavContainer: ForwardRefComponent<CarouselNavContainerProps
const state = useCarouselNavContainer_unstable(props, ref);

useCarouselNavContainerStyles_unstable(state);

/**
* @see https://github.com/microsoft/fluentui/blob/master/docs/react-v9/contributing/rfcs/react-components/convergence/custom-styling.md
*
* TODO: 💡 once package will become stable (PR which will be part of promoting PREVIEW package to STABLE),
* - uncomment this line
* - update types {@link file://./../../../../../../../packages/react-components/react-shared-contexts/library/src/CustomStyleHooksContext/CustomStyleHooksContext.ts#CustomStyleHooksContextValue}
* - verify that custom global style override works for your component
*/
// useCustomStyleHook_unstable('useCarouselNavContainerStyles_unstable')(state);
useCustomStyleHook_unstable('useCarouselNavContainerStyles_unstable')(state);

return renderCarouselNavContainer_unstable(state);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useCarouselNavImageButton_unstable } from './useCarouselNavImageButton'
import { renderCarouselNavImageButton_unstable } from './renderCarouselNavImageButton';
import { useCarouselNavImageButtonStyles_unstable } from './useCarouselNavImageButtonStyles.styles';
import type { CarouselNavImageButtonProps } from './CarouselNavImageButton.types';
import { useCustomStyleHook_unstable } from '@fluentui/react-shared-contexts';

/**
* A variant child element of CarouselNav, a singular image button that displays a
Expand All @@ -14,9 +15,8 @@ export const CarouselNavImageButton: ForwardRefComponent<CarouselNavImageButtonP
const state = useCarouselNavImageButton_unstable(props, ref);

useCarouselNavImageButtonStyles_unstable(state);
// TODO update types in packages/react-components/react-shared-contexts/src/CustomStyleHooksContext/CustomStyleHooksContext.ts
// https://github.com/microsoft/fluentui/blob/master/rfcs/react-components/convergence/custom-styling.md
// useCustomStyleHook_unstable('useCarouselNavImageButtonStyles_unstable')(state);
useCustomStyleHook_unstable('useCarouselNavImageButtonStyles_unstable')(state);

return renderCarouselNavImageButton_unstable(state);
},
);
Expand Down
Loading
Loading