Skip to content
Draft
2 changes: 1 addition & 1 deletion packages/react-cap-theme/.storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { CAP_STYLE_HOOKS } from '../src/index';
import type { JSXElement } from '@fluentui/react-utilities';

import type { Preview, StoryFn } from '@storybook/react';
import { CAPTokens } from '../src/components/tokens/types';
import { CAPTokens } from '../src/customStyleHooks/tokens/types';

const capTheme: Record<keyof Theme & keyof CAPTokens, string> = {
...webLightTheme,
Expand Down
3 changes: 2 additions & 1 deletion packages/react-cap-theme/.swcrc
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
".*\\.test.tsx?$",
"./src/jest-setup.ts$",
"./**/jest-setup.ts$",
".*.js$"
".*.js$",
"src/components"
],
"$schema": "https://json.schemastore.org/swcrc"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import * as React from 'react';
import type { ForwardRefComponent } from '@fluentui/react-utilities';
import {
renderAccordionHeader_unstable,
useAccordionHeaderContextValues_unstable,
type AccordionHeaderProps,
} from '@fluentui/react-accordion';
import { useAccordionHeader } from './useAccordionHeader';
import { useAccordionHeaderStyles_unstable } from '@fluentui/react-components';
import { useAccordionHeaderStyles as useCAPAccordionHeader } from '../../../../customStyleHooks/react-accordion';
/**
* An accordion header is used as a button in the heading
*
* @param props - The accordion header configuration and event handlers
* @param ref - Reference to the accordion header element
* @returns The rendered accordion header component
* @alpha
*/
export const AccordionHeader: ForwardRefComponent<AccordionHeaderProps> =
React.forwardRef((props, ref) => {
const state = useAccordionHeader(props, ref);

useAccordionHeaderStyles_unstable(state);
useCAPAccordionHeader(state);

return renderAccordionHeader_unstable(
state,
useAccordionHeaderContextValues_unstable(state)
);
});
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export { useAccordionHeaderStyles } from './components/AccordionHeader/useAccordionHeaderStyles.styles';
export { useAccordionPanelStyles } from './components/AccordionPanel/useAccordionPanelStyles.styles';
export { AccordionHeader as CAPAccordionHeader } from './components/AccordionHeader/AccordionHeader';
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {
renderAvatarGroupPopover_unstable,
useAvatarGroupPopoverContextValues_unstable,
type AvatarGroupPopoverState as FluentAvatarGroupPopoverState,
} from '@fluentui/react-avatar';
import type * as React from 'react';
import { useAvatarGroupPopoverStyles_unstable } from '@fluentui/react-components';
import { useAvatarGroupPopover } from './useAvatarGroupPopover';
import type { AvatarGroupPopoverProps } from '../../../../customStyleHooks/react-avatar';
import { useAvatarGroupPopoverStyles as useCAPAvatarGroupPopoverStyles } from '../../../../customStyleHooks/react-avatar';

export const AvatarGroupPopover: React.FC<AvatarGroupPopoverProps> = (
props
) => {
const state = useAvatarGroupPopover(props);
const baseState = state as unknown as FluentAvatarGroupPopoverState;
const contextValues = useAvatarGroupPopoverContextValues_unstable(baseState);

useAvatarGroupPopoverStyles_unstable(baseState);
useCAPAvatarGroupPopoverStyles(state);

return renderAvatarGroupPopover_unstable(baseState, contextValues);
};

AvatarGroupPopover.displayName = 'AvatarGroupPopover';
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { useAvatarGroupPopover_unstable } from '@fluentui/react-avatar';
import { slot } from '@fluentui/react-utilities';
import { PopoverSurface } from '../../../react-popover';
import { CAPTooltip } from '../../../react-tooltip';
import type {
AvatarGroupPopoverProps,
AvatarGroupPopoverState,
} from '../../../../customStyleHooks/react-avatar';

export const useAvatarGroupPopover = (
props: AvatarGroupPopoverProps
): AvatarGroupPopoverState => {
const { tooltip: tooltipProps, ...baseProps } = props;
const state = useAvatarGroupPopover_unstable(baseProps);

const popoverSurface = slot.always(props.popoverSurface, {
defaultProps: {
'aria-label': 'Overflow',
tabIndex: 0,
},
elementType: PopoverSurface,
});
const tooltip = slot.always(tooltipProps, {
defaultProps: {
content: 'View more people.',
relationship: 'label',
},
elementType: CAPTooltip,
});

return {
...state,
components: {
...state.components,
popoverSurface: PopoverSurface,
tooltip: CAPTooltip,
},
popoverSurface,
tooltip,
};
};
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
export { useAvatarStyles } from './components/Avatar/useAvatarStyles.styles';
export { useAvatarGroupItemStyles } from './components/AvatarGroupItem/useAvatarGroupItemStyles.styles';
export { useAvatarGroupPopoverStyles } from './components/AvatarGroupPopover/useAvatarGroupPopoverStyles.styles';
export { AvatarGroupPopover as CAPAvatarGroupPopover } from './components/AvatarGroupPopover/AvatarGroupPopover';
10 changes: 3 additions & 7 deletions packages/react-cap-theme/src/components/react-button/Button.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
export { useButtonStyles } from './components/Button/useButtonStyles.styles';
export type {
ButtonProps,
ButtonSlots,
ButtonState,
ButtonAppearance,
} from './components/Button/Button.types';
export { Button as CAPButton } from './components/Button/Button';
export { renderButton } from './components/Button/renderButton';
export { useButton } from './components/Button/useButton';
Original file line number Diff line number Diff line change
@@ -1,6 +1 @@
export { useMenuButtonStyles } from './components/MenuButton/useMenuButtonStyles.styles';
export type {
MenuButtonProps,
MenuButtonSlots,
MenuButtonState,
} from './components/MenuButton/MenuButton.types';
export { MenuButton as CAPMenuButton } from './components/MenuButton/MenuButton';
Original file line number Diff line number Diff line change
@@ -1,6 +1 @@
export { useSplitButtonStyles } from './components/SplitButton/useSplitButtonStyles.styles';
export type {
SplitButtonProps,
SplitButtonSlots,
SplitButtonState,
} from './components/SplitButton/SplitButton.types';
export { SplitButton as CAPSplitButton } from './components/SplitButton/SplitButton';
Original file line number Diff line number Diff line change
@@ -1,5 +1,2 @@
export { useToggleButtonStyles } from './components/ToggleButton/useToggleButtonStyles.styles';
export type {
ToggleButtonProps,
ToggleButtonState,
} from './components/ToggleButton/ToggleButton.types';
export { ToggleButton as CAPToggleButton } from './components/ToggleButton/ToggleButton';
export { useToggleButton } from './components/ToggleButton/useToggleButton';
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { ForwardRefComponent } from '@fluentui/react-utilities';
import * as React from 'react';
import { renderButton } from './renderButton';
import { useButton } from './useButton';
import { useButtonStyles_unstable } from '@fluentui/react-components';
import { useButtonStyles as useCAPButtonStyles } from '../../../../customStyleHooks/react-button';
import type { ButtonProps } from '../../../../customStyleHooks/react-button/';
import { toBaseState } from '../../utils/toBaseState';

export const Button: ForwardRefComponent<ButtonProps> = React.forwardRef(
(props, ref) => {
const state = useButton(props, ref);

useButtonStyles_unstable(toBaseState(state));
useCAPButtonStyles(state);

return renderButton(state);
// Casting is required due to lack of distributive union to support unions on @types/react
}
) as ForwardRefComponent<ButtonProps>;

Button.displayName = 'Button';
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { ButtonProps as BaseButtonProps } from '@fluentui/react-button';
import type {
ButtonAppearance,
ButtonProps,
} from '../../../../customStyleHooks/react-button';

export const baseAppearanceMap: Record<
ButtonAppearance,
BaseButtonProps['appearance']
> = {
secondary: 'secondary',
primary: 'primary',
outline: 'outline',
subtle: 'subtle',
transparent: 'transparent',
tint: 'primary',
};

export const toBaseProps = (props: ButtonProps): BaseButtonProps => ({
...props,
appearance: props.appearance && baseAppearanceMap[props.appearance],
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import {
renderButton_unstable,
type ButtonState as BaseButtonState,
} from '@fluentui/react-button';
import type { JSXElement } from '@fluentui/react-utilities';
import type { ButtonState } from '../../../../customStyleHooks/react-button';
import { toBaseState } from '../../utils/toBaseState';

export const renderButton = (state: ButtonState): JSXElement => {
const baseState: BaseButtonState = toBaseState(state);
return renderButton_unstable(baseState);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { useButton_unstable as useBaseState } from '@fluentui/react-button';
import type {
ButtonProps,
ButtonState,
} from '../../../../customStyleHooks/react-button';
import { toBaseProps } from './Button.utils';

export const useButton = (
props: ButtonProps,
ref: React.Ref<HTMLButtonElement | HTMLAnchorElement>
): ButtonState => {
const appearance = props.appearance ?? 'secondary';

return {
...useBaseState(toBaseProps(props), ref),
appearance,
} as ButtonState;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { ForwardRefComponent } from '@fluentui/react-utilities';
import * as React from 'react';
import { renderMenuButton } from './renderMenuButton';
import { useMenuButton } from './useMenuButton';
import { useMenuButtonStyles_unstable } from '@fluentui/react-components';
import { useMenuButtonStyles as useCAPMenuButtonStyles } from '../../../../customStyleHooks/react-button';
import type { MenuButtonProps } from '../../../../customStyleHooks/react-button';
import { toBaseState } from '../../utils/toBaseState';

export const MenuButton: ForwardRefComponent<MenuButtonProps> =
React.forwardRef((props, ref) => {
const state = useMenuButton(props, ref);
useMenuButtonStyles_unstable(toBaseState(state));
useCAPMenuButtonStyles(state);
return renderMenuButton(state);
}) as ForwardRefComponent<MenuButtonProps>;

MenuButton.displayName = 'MenuButton';
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { renderMenuButton_unstable } from '@fluentui/react-button';
import type { JSXElement } from '@fluentui/react-utilities';
import { baseAppearanceMap } from '../Button/Button.utils';
import type { MenuButtonState } from '../../../../customStyleHooks/react-button';

export const renderMenuButton = (state: MenuButtonState): JSXElement => {
return renderMenuButton_unstable({
...state,
appearance: baseAppearanceMap[state.appearance] ?? 'secondary',
});
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { useMenuButton_unstable } from '@fluentui/react-button';
import {
bundleIcon,
ChevronDownFilled,
ChevronDownRegular,
} from '@fluentui/react-icons';
import { slot } from '@fluentui/react-utilities';
import * as React from 'react';
import { baseAppearanceMap } from '../Button/Button.utils';
import type {
MenuButtonProps,
MenuButtonState,
} from '../../../../customStyleHooks/react-button';

const ChevronDownIcon = bundleIcon(ChevronDownFilled, ChevronDownRegular);

export const useMenuButton = (
props: MenuButtonProps,
ref: React.Ref<HTMLButtonElement | HTMLAnchorElement>
): MenuButtonState => {
const { appearance = 'secondary' } = props;
const baseState = useMenuButton_unstable(
{
...props,
appearance: appearance && baseAppearanceMap[appearance],
},
ref
);

return {
...baseState,
appearance,
menuIcon: slot.optional(props.menuIcon, {
defaultProps: {
children: <ChevronDownIcon />,
},
renderByDefault: true,
elementType: 'span',
}),
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { ForwardRefComponent } from '@fluentui/react-utilities';
import * as React from 'react';
import { renderSplitButton } from './renderSplitButton';
import type { SplitButtonProps } from '../../../../customStyleHooks/react-button/components/SplitButton/SplitButton.types';
import { useSplitButton } from './useSplitButton';
import { useSplitButtonStyles as useCAPSplitButtonStyles } from '../../../../customStyleHooks/react-button/components/SplitButton/useSplitButtonStyles.styles';
import { useSplitButtonStyles_unstable } from '@fluentui/react-components';
import { toBaseState } from '../../utils/toBaseState';

export const SplitButton: ForwardRefComponent<SplitButtonProps> =
React.forwardRef((props, ref) => {
const state = useSplitButton(props, ref);
useSplitButtonStyles_unstable(toBaseState(state));
useCAPSplitButtonStyles(state);

return renderSplitButton(state);
});

SplitButton.displayName = 'SplitButton';
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/** @jsx createElement */
/** @jsxRuntime classic */

import { assertSlots, type JSXElement } from '@fluentui/react-utilities';
import type {
SplitButtonSlots,
SplitButtonState,
} from '../../../../customStyleHooks/react-button';

export const renderSplitButton = (state: SplitButtonState): JSXElement => {
assertSlots<SplitButtonSlots>(state);

return (
<state.root>
{state.primaryActionButton && <state.primaryActionButton />}
{state.menuButton && <state.menuButton />}
</state.root>
);
};
Loading
Loading