diff --git a/packages/react-components/react-button/library/src/components/Button/Button.types.ts b/packages/react-components/react-button/library/src/components/Button/Button.types.ts index 201f264913be06..f28686ea5f6dc4 100644 --- a/packages/react-components/react-button/library/src/components/Button/Button.types.ts +++ b/packages/react-components/react-button/library/src/components/Button/Button.types.ts @@ -29,7 +29,7 @@ export type ButtonProps = ComponentProps & { * * @default 'secondary' */ - appearance?: 'secondary' | 'primary' | 'outline' | 'subtle' | 'transparent'; + appearance?: 'secondary' | 'primary' | 'outline' | 'subtle' | 'transparent' | 'tint'; /** * When set, allows the button to be focusable even when it has been disabled. This is used in scenarios where it diff --git a/packages/react-components/react-button/library/src/components/Button/useButtonStyles.styles.ts b/packages/react-components/react-button/library/src/components/Button/useButtonStyles.styles.ts index 186d0f7a86d58e..1221c9f082615b 100644 --- a/packages/react-components/react-button/library/src/components/Button/useButtonStyles.styles.ts +++ b/packages/react-components/react-button/library/src/components/Button/useButtonStyles.styles.ts @@ -562,7 +562,8 @@ export const useButtonStyles_unstable = (state: ButtonState): ButtonState => { const rootIconOnlyStyles = useRootIconOnlyStyles(); const iconStyles = useIconStyles(); - const { appearance, disabled, disabledFocusable, icon, iconOnly, iconPosition, shape, size } = state; + const { disabled, disabledFocusable, icon, iconOnly, iconPosition, shape, size } = state; + const appearance = state.appearance === 'tint' ? 'secondary' : state.appearance; state.root.className = mergeClasses( buttonClassNames.root, diff --git a/packages/react-components/react-button/stories/src/Button/ButtonAppearance.stories.tsx b/packages/react-components/react-button/stories/src/Button/ButtonAppearance.stories.tsx index 2f37e55d501842..439821a3448da9 100644 --- a/packages/react-components/react-button/stories/src/Button/ButtonAppearance.stories.tsx +++ b/packages/react-components/react-button/stories/src/Button/ButtonAppearance.stories.tsx @@ -30,6 +30,9 @@ export const Appearance = (): JSXElement => { + ); }; diff --git a/packages/react-components/react-provider/library/src/components/CAPThemeProvider/CAPTheme.tsx b/packages/react-components/react-provider/library/src/components/CAPThemeProvider/CAPTheme.tsx new file mode 100644 index 00000000000000..cd8067dfea3899 --- /dev/null +++ b/packages/react-components/react-provider/library/src/components/CAPThemeProvider/CAPTheme.tsx @@ -0,0 +1,126 @@ +import { tokens } from '@fluentui/react-components'; + +const EXPECTED_SEMANTIC_TOKENS = [ + // card + 'stroke/card/onPrimary/default/rest', + 'cornerRadius/ctrl/card', + 'padding/card/header/body/default/inside', + 'padding/card/header/body/default/outside', +] as const; +type ExpectedSemanticToken = (typeof EXPECTED_SEMANTIC_TOKENS)[number]; + +const TOKEN_TYPES = ['color', 'dimension'] as const; + +type TokenType = (typeof TOKEN_TYPES)[number]; + +export interface TokenSchema { + type: TokenType; + /** + * What's the name of the semantic token that we expect to exist? When semantic tokens v2 + * is released, our token should be replaced by this one. + */ + semanticToken: ExpectedSemanticToken | null; +} + +const BadgeTokens = { + colorBrandForegroundCompound: { type: 'color', semanticToken: null }, +} as const satisfies Record; + +const ButtonTokens = { + buttonPrimaryBackgroundColor: { type: 'color', semanticToken: null }, + buttonPrimaryBackgroundColorHover: { type: 'color', semanticToken: null }, + buttonSecondaryBackgroundColor: { type: 'color', semanticToken: null }, + buttonSecondaryBackgroundColorHover: { type: 'color', semanticToken: null }, + buttonSubtleBackgroundColor: { type: 'color', semanticToken: null }, + buttonSubtleBackgroundColorHover: { type: 'color', semanticToken: null }, + buttonOutlineBackgroundColor: { type: 'color', semanticToken: null }, + buttonOutlineBackgroundColorHover: { type: 'color', semanticToken: null }, + buttonTintBackgroundColor: { type: 'color', semanticToken: null }, + buttonTintBackgroundColorHover: { type: 'color', semanticToken: null }, +} as const satisfies Record; + +const CardTokens = { + cardBackgroundColor: { type: 'color', semanticToken: null }, + cardForegroundColor: { type: 'color', semanticToken: null }, + cardBackgroundColorHover: { type: 'color', semanticToken: null }, + cardForegroundColorHover: { type: 'color', semanticToken: null }, + cardBackgroundColorPressed: { type: 'color', semanticToken: null }, + cardForegroundColorPressed: { type: 'color', semanticToken: null }, + cardBackgroundColorDisabled: { type: 'color', semanticToken: null }, + cardForegroundColorDisabled: { type: 'color', semanticToken: null }, + cardCornerRadius: { type: 'dimension', semanticToken: 'cornerRadius/ctrl/card' }, + cardHeaderPaddingOutside: { type: 'dimension', semanticToken: 'padding/card/header/body/default/outside' }, + cardHeaderPaddingInside: { type: 'dimension', semanticToken: 'padding/card/header/body/default/inside' }, + cardFooterHorizontalGap: { type: 'dimension', semanticToken: null }, +} as const satisfies Record; + +const DialogTokens = {} as const satisfies Record; + +const InputTokens = {} as const satisfies Record; + +const MenuTokens = {} as const satisfies Record; + +const TooltipTokens = {} as const satisfies Record; + +export const CAPTokensSchema = { + ...BadgeTokens, + ...ButtonTokens, + ...CardTokens, + ...DialogTokens, + ...InputTokens, + ...MenuTokens, + ...TooltipTokens, +} as const satisfies { [key: string]: TokenSchema }; + +export const CAPTokens = { + ...(Object.keys(CAPTokensSchema).reduce((acc: any, key) => { + return { ...acc, [key]: `var(--${key})` }; + }) as any), +} as Record; + +export type CAPTheme = { + [k in keyof typeof CAPTokens]: string | null; +}; + +export const CAP_THEME = { + // button + buttonPrimaryBackgroundColor: tokens.colorBrandBackground, + buttonPrimaryBackgroundColorHover: tokens.colorBrandBackgroundHover, + buttonSecondaryBackgroundColor: null, + buttonSecondaryBackgroundColorHover: null, + buttonSubtleBackgroundColor: tokens.colorBrandBackground, + buttonSubtleBackgroundColorHover: tokens.colorBrandBackground, + buttonOutlineBackgroundColor: tokens.colorTransparentBackground, + buttonOutlineBackgroundColorHover: tokens.colorTransparentBackground, + buttonTintBackgroundColor: 'red', + buttonTintBackgroundColorHover: null, + + // card + cardCornerRadius: tokens.borderRadiusXLarge, // 8px + cardBackgroundColor: tokens.colorNeutralBackground1, + cardForegroundColor: tokens.colorNeutralBackground1, + cardBackgroundColorHover: '', + cardForegroundColorHover: '', + cardBackgroundColorPressed: '', + cardForegroundColorPressed: '', + cardBackgroundColorDisabled: '', + cardForegroundColorDisabled: '', + cardHeaderPaddingOutside: tokens.spacingVerticalM, + cardHeaderPaddingInside: tokens.spacingVerticalS, + cardFooterHorizontalGap: tokens.spacingHorizontalS, + + // TODO: switch to BrandForegroundCompound when available + colorBrandForegroundCompound: tokens.colorBrandForeground1, +} as const satisfies CAPTheme; + +export const CAP_THEME_TEAMS = { + ...CAP_THEME, +} as const satisfies CAPTheme; + +export const CAP_THEME_ONE_DRIVE = { + ...CAP_THEME, +} as const satisfies CAPTheme; + +export const CAP_THEME_SHAREPOINT = { + ...CAP_THEME, +} as const satisfies CAPTheme; diff --git a/packages/react-components/react-provider/library/src/components/CAPThemeProvider/CAPThemeProvider.tsx b/packages/react-components/react-provider/library/src/components/CAPThemeProvider/CAPThemeProvider.tsx new file mode 100644 index 00000000000000..4da13f4eba7855 --- /dev/null +++ b/packages/react-components/react-provider/library/src/components/CAPThemeProvider/CAPThemeProvider.tsx @@ -0,0 +1,41 @@ +import * as React from 'react'; +import { + BadgeState, + ButtonState, + CardFooterState, + CardHeaderState, + CardState, + FluentProvider, + InputState, + Theme, +} from '@fluentui/react-components'; +import { useCAPButtonStylesHook } from './components/CAPButton'; +import { CustomStyleHooksContext_unstable } from '@fluentui/react-shared-contexts'; +import { CAPTheme } from './CAPTheme'; +import { useCAPBadgeStylesHook } from './components/CAPBadge'; +import { useCAPInputStylesHook } from './components/CAPInput'; +import { useCAPCardFooterStylesHook, useCAPCardHeaderStylesHook, useCAPCardStylesHook } from './components/CAPCard'; + +export const CAPThemeProvider = ({ + children, + theme, +}: { + children: React.ReactElement; + theme: Partial & Partial; +}) => { + const customStyleHooks = React.useMemo((): React.ContextType => { + return { + useBadgeStyles_unstable: state => useCAPBadgeStylesHook(state as BadgeState), + useButtonStyles_unstable: state => useCAPButtonStylesHook(state as ButtonState), + useCardStyles_unstable: state => useCAPCardStylesHook(state as CardState), + useCardHeaderStyles_unstable: state => useCAPCardHeaderStylesHook(state as CardHeaderState), + useCardFooterStyles_unstable: state => useCAPCardFooterStylesHook(state as CardFooterState), + useInputStyles_unstable: state => useCAPInputStylesHook(state as InputState), + }; + }, []); + return ( + + {children} + + ); +}; diff --git a/packages/react-components/react-provider/library/src/components/CAPThemeProvider/components/CAPBadge.tsx b/packages/react-components/react-provider/library/src/components/CAPThemeProvider/components/CAPBadge.tsx new file mode 100644 index 00000000000000..8c89c7184390ab --- /dev/null +++ b/packages/react-components/react-provider/library/src/components/CAPThemeProvider/components/CAPBadge.tsx @@ -0,0 +1,139 @@ +import { makeStyles, mergeClasses, shorthands } from '@griffel/react'; +import { BadgeState, useBadgeStyles_unstable } from '@fluentui/react-components'; +import { tokens } from '@fluentui/react-theme'; +import { CAP_THEME } from '../CAPTheme'; + +const textPadding = tokens.spacingHorizontalXXS; + +const useCAPBadgeStyles = makeStyles({ + root: { + padding: `0 calc(${tokens.spacingHorizontalSNudge} + ${textPadding})`, + }, + + tiny: { + padding: 'unset', + }, + + 'extra-small': { + padding: 'unset', + }, + + small: { + padding: `0 calc(${tokens.spacingHorizontalXS} + ${textPadding})`, + }, + + medium: { + // Set by root + }, + + large: { + padding: `0 calc(${tokens.spacingHorizontalSNudge} + ${textPadding})`, + }, + + 'extra-large': { + padding: `0 calc(${tokens.spacingHorizontalS} + ${textPadding})`, + }, + + // shape + 'rounded-extra-large': { borderRadius: tokens.borderRadiusXLarge }, + 'rounded-large': { borderRadius: tokens.borderRadiusLarge }, + 'rounded-medium': { borderRadius: tokens.borderRadiusMedium }, + 'rounded-small': { borderRadius: tokens.borderRadiusMedium }, + 'rounded-extra-small': { borderRadius: tokens.borderRadiusSmall }, + 'rounded-tiny': { borderRadius: tokens.borderRadiusSmall }, + + 'outline-brand': { + ...shorthands.borderColor(tokens.colorBrandStroke2), + }, + 'outline-warning': { + ...shorthands.borderColor(tokens.colorStatusWarningBorder1), + }, + 'outline-important': { + ...shorthands.borderColor(tokens.colorNeutralStroke1), + }, + 'outline-danger': { + ...shorthands.borderColor(tokens.colorStatusDangerBorder1), + }, + 'outline-success': { + ...shorthands.borderColor(tokens.colorStatusSuccessBorder1), + }, + 'outline-informative': { + ...shorthands.borderColor(tokens.colorNeutralStroke1), + }, + 'outline-subtle': { + ...shorthands.borderColor(tokens.colorNeutralForegroundOnBrand), + }, + + 'tint-brand': { + color: CAP_THEME.colorBrandForegroundCompound, + }, + + 'ghost-brand': { + color: CAP_THEME.colorBrandForegroundCompound, + }, + + 'filled-warning': { + color: tokens.colorNeutralForegroundOnBrand, + backgroundColor: tokens.colorStatusWarningBackground3, + }, + + 'tint-informative': { + backgroundColor: tokens.colorNeutralBackground5, + ...shorthands.borderColor(tokens.colorNeutralStroke1), + }, + + 'filled-important': { + backgroundColor: tokens.colorNeutralBackgroundInverted, + color: tokens.colorNeutralForegroundOnBrand, + }, + + 'tint-important': { + backgroundColor: tokens.colorNeutralBackground5, + color: tokens.colorNeutralForeground3, + ...shorthands.borderColor(tokens.colorNeutralStroke1), + }, + + 'filled-subtle': { + color: tokens.colorNeutralForeground3, + backgroundColor: tokens.colorNeutralBackground5, + }, + + 'tint-subtle': { + ...shorthands.borderColor(tokens.colorNeutralStroke1), + }, +}); + +const useCAPBadgeIconStyles = makeStyles({ + beforeTextSmall: { + marginRight: textPadding, + }, + afterTextSmall: { + marginLeft: textPadding, + }, +}); + +export function useCAPBadgeStylesHook(state: BadgeState) { + // Apply base Badge styles first + useBadgeStyles_unstable(state); + + // Then override with CAP styles + const styles = useCAPBadgeStyles(); + const iconStyles = useCAPBadgeIconStyles(); + + state.root.className = mergeClasses( + state.root.className, + styles.root, + styles[state.size], + state.shape === 'rounded' && styles[`rounded-${state.size}`], + `${state.appearance}-${state.color}` in styles && + styles[`${state.appearance}-${state.color}` as keyof typeof styles], + ); + + // Override icon spacing for small size + if (state.icon && state.size === 'small') { + const iconPositionClass = state.iconPosition === 'after' ? iconStyles.afterTextSmall : iconStyles.beforeTextSmall; + state.icon.className = mergeClasses(state.icon.className, iconPositionClass); + } + + return state; +} diff --git a/packages/react-components/react-provider/library/src/components/CAPThemeProvider/components/CAPButton.tsx b/packages/react-components/react-provider/library/src/components/CAPThemeProvider/components/CAPButton.tsx new file mode 100644 index 00000000000000..2a77354de98c53 --- /dev/null +++ b/packages/react-components/react-provider/library/src/components/CAPThemeProvider/components/CAPButton.tsx @@ -0,0 +1,45 @@ +import { makeStyles, mergeClasses } from '@griffel/react'; +import { ButtonState } from '@fluentui/react-components'; +import { CAPTokens } from '../CAPTheme'; + +const useCAPButtonStyles = makeStyles({ + root: { + borderRadius: '12px', + }, + primary: { + backgroundColor: CAPTokens.buttonPrimaryBackgroundColor, + + ':hover': { + backgroundColor: CAPTokens.buttonPrimaryBackgroundColorHover, + }, + }, + secondary: { + backgroundColor: CAPTokens.buttonSecondaryBackgroundColor, + + ':hover': { + backgroundColor: CAPTokens.buttonSecondaryBackgroundColorHover, + }, + }, + outline: { + backgroundColor: CAPTokens.buttonOutlineBackgroundColor, + + ':hover': { + backgroundColor: CAPTokens.buttonOutlineBackgroundColorHover, + }, + }, + subtle: {}, + tint: { + backgroundColor: CAPTokens.buttonTintBackgroundColor, + + ':hover': { + backgroundColor: CAPTokens.buttonTintBackgroundColorHover, + }, + }, + transparent: {}, +}); + +export function useCAPButtonStylesHook(state: ButtonState) { + const styles = useCAPButtonStyles(); + state.root.className = mergeClasses(state.root.className, styles.root, state.appearance && styles[state.appearance]); + return state; +} diff --git a/packages/react-components/react-provider/library/src/components/CAPThemeProvider/components/CAPCard.tsx b/packages/react-components/react-provider/library/src/components/CAPThemeProvider/components/CAPCard.tsx new file mode 100644 index 00000000000000..4814683b4bc7de --- /dev/null +++ b/packages/react-components/react-provider/library/src/components/CAPThemeProvider/components/CAPCard.tsx @@ -0,0 +1,35 @@ +import { makeStyles, mergeClasses } from '@griffel/react'; +import { CardFooterState, CardHeaderState, CardState } from '@fluentui/react-components'; +import { CAPTokens } from '../CAPTheme'; + +const useCAPCardStyles = makeStyles({ + root: { + borderRadius: CAPTokens.cardCornerRadius, + }, +}); + +export function useCAPCardStylesHook(state: CardState) { + const styles = useCAPCardStyles(); + state.root.className = mergeClasses(state.root.className, styles.root); + return state; +} + +const useCAPCardHeaderStyles = makeStyles({ + root: {}, +}); + +export function useCAPCardHeaderStylesHook(state: CardHeaderState) { + const styles = useCAPCardHeaderStyles(); + state.root.className = mergeClasses(state.root.className, styles.root); + return state; +} + +const useCAPCardFooterStyles = makeStyles({ + root: {}, +}); + +export function useCAPCardFooterStylesHook(state: CardFooterState) { + const styles = useCAPCardFooterStyles(); + state.root.className = mergeClasses(state.root.className, styles.root); + return state; +} diff --git a/packages/react-components/react-provider/library/src/components/CAPThemeProvider/components/CAPInput.tsx b/packages/react-components/react-provider/library/src/components/CAPThemeProvider/components/CAPInput.tsx new file mode 100644 index 00000000000000..ee50d5f766e763 --- /dev/null +++ b/packages/react-components/react-provider/library/src/components/CAPThemeProvider/components/CAPInput.tsx @@ -0,0 +1,12 @@ +import { makeStyles, mergeClasses } from '@griffel/react'; +import { InputState } from '@fluentui/react-components'; + +const useCAPInputStyles = makeStyles({ + root: {}, +}); + +export function useCAPInputStylesHook(state: InputState) { + const styles = useCAPInputStyles(); + state.root.className = mergeClasses(state.root.className, styles.root); + return state; +} diff --git a/packages/react-components/react-provider/library/src/components/CAPThemeProvider/components/CAPMenu.tsx b/packages/react-components/react-provider/library/src/components/CAPThemeProvider/components/CAPMenu.tsx new file mode 100644 index 00000000000000..0c8bbedf8cb039 --- /dev/null +++ b/packages/react-components/react-provider/library/src/components/CAPThemeProvider/components/CAPMenu.tsx @@ -0,0 +1,5 @@ +import { MenuState } from '@fluentui/react-components'; + +export function useCAPMenuStylesHook(state: MenuState) { + return state; +} diff --git a/packages/react-components/react-provider/library/src/index.ts b/packages/react-components/react-provider/library/src/index.ts index 5062bf63333163..070338fc47802c 100644 --- a/packages/react-components/react-provider/library/src/index.ts +++ b/packages/react-components/react-provider/library/src/index.ts @@ -15,3 +15,5 @@ export type { FluentProviderState, FluentProviderSlots, } from './FluentProvider'; +export { CAPThemeProvider } from './components/CAPThemeProvider/CAPThemeProvider'; +export { CAP_THEME_ONE_DRIVE, CAP_THEME_SHAREPOINT, CAP_THEME_TEAMS } from './components/CAPThemeProvider/CAPTheme'; diff --git a/packages/react-components/react-provider/stories/src/CAPThemeProvider/CAPBadge.stories.tsx b/packages/react-components/react-provider/stories/src/CAPThemeProvider/CAPBadge.stories.tsx new file mode 100644 index 00000000000000..e2f786d5bd313b --- /dev/null +++ b/packages/react-components/react-provider/stories/src/CAPThemeProvider/CAPBadge.stories.tsx @@ -0,0 +1,345 @@ +import * as React from 'react'; +import { Badge } from '@fluentui/react-components'; +import { CAPThemeExamples } from './CAPStorybookUtil'; +import { CircleRegular } from '@fluentui/react-icons'; + +export const CAPBadgeStory = () => { + return ( + } />; + }, + }, + { + title: 'Extra Small', + render() { + return } />; + }, + }, + { + title: 'Small', + render() { + return ( + }> + Badge + + ); + }, + }, + { + title: 'Default/Medium', + render() { + return }> Badge; + }, + }, + { + title: 'Medium No Icon', + render() { + return Badge; + }, + }, + { + title: 'Large', + render() { + return ( + }> + Badge + + ); + }, + }, + { + title: 'Extra Large', + render() { + return ( + }> + Badge + + ); + }, + }, + { + title: 'Tiny Square', + render() { + return } shape="square" />; + }, + }, + { + title: 'Extra Small Square', + render() { + return } shape="square" />; + }, + }, + { + title: 'Small Square', + render() { + return ( + } shape="square"> + Badge + + ); + }, + }, + { + title: 'Default/Medium Square', + render() { + return ( + } shape="square"> + {' '} + Badge + + ); + }, + }, + { + title: 'Medium No Icon Square', + render() { + return Badge; + }, + }, + { + title: 'Large Square', + render() { + return ( + } shape="square"> + Badge + + ); + }, + }, + { + title: 'Extra Large Square', + render() { + return ( + } shape="square"> + Badge + + ); + }, + }, + { + title: 'Tiny Rounded', + render() { + return } shape="rounded" />; + }, + }, + { + title: 'Extra Small Rounded ', + render() { + return } shape="rounded" />; + }, + }, + { + title: 'Small Rounded', + render() { + return ( + } shape="rounded"> + Badge + + ); + }, + }, + { + title: 'Default/Medium Rounded', + render() { + return ( + } shape="rounded"> + {' '} + Badge + + ); + }, + }, + { + title: 'Medium No Icon Rounded', + render() { + return Badge; + }, + }, + { + title: 'Large Rounded', + render() { + return ( + } shape="rounded"> + Badge + + ); + }, + }, + { + title: 'Extra Large Rounded', + render() { + return ( + } shape="rounded"> + Badge + + ); + }, + }, + { + title: 'Outline / Important', + render() { + return ( + } color="important" appearance="outline"> + Badge + + ); + }, + }, + { + title: 'Outline / Brand', + render() { + return ( + } color="brand" appearance="outline"> + Badge + + ); + }, + }, + { + title: 'Outline / Danger', + render() { + return ( + } color="danger" appearance="outline"> + Badge + + ); + }, + }, + { + title: 'Outline / Warning', + render() { + return ( + } color="warning" appearance="outline"> + Badge + + ); + }, + }, + { + title: 'Outline / Success', + render() { + return ( + } color="success" appearance="outline"> + Badge + + ); + }, + }, + { + title: 'Outline / Informative', + render() { + return ( + } color="informative" appearance="outline"> + Badge + + ); + }, + }, + { + title: 'Outline / Subtle', + render() { + return ( + } color="subtle" appearance="outline"> + Badge + + ); + }, + }, + { + title: 'Outline / Severe', + render() { + return ( + } color="severe" appearance="outline"> + Badge + + ); + }, + }, + { + title: 'Brand / Tint', + render() { + return ( + } color="brand" appearance="tint"> + Badge + + ); + }, + }, + { + title: 'Brand / Ghost', + render() { + return ( + } color="brand" appearance="ghost"> + Badge + + ); + }, + }, + { + title: 'Warning / Filled', + render() { + return ( + } color="warning" appearance="filled"> + Badge + + ); + }, + }, + { + title: 'Informative / Tint', + render() { + return ( + } color="informative" appearance="tint"> + Badge + + ); + }, + }, + { + title: 'Important / Filled', + render() { + return ( + } color="important" appearance="filled"> + Badge + + ); + }, + }, + { + title: 'Important / Tint', + render() { + return ( + } color="important" appearance="tint"> + Badge + + ); + }, + }, + { + title: 'Subtle / Filled', + render() { + return ( + } color="subtle" appearance="filled"> + Badge + + ); + }, + }, + { + title: 'Subtle / Tint', + render() { + return ( + } color="subtle" appearance="tint"> + Badge + + ); + }, + }, + ]} + /> + ); +}; diff --git a/packages/react-components/react-provider/stories/src/CAPThemeProvider/CAPButton.stories.tsx b/packages/react-components/react-provider/stories/src/CAPThemeProvider/CAPButton.stories.tsx new file mode 100644 index 00000000000000..bf5234f15dc1e4 --- /dev/null +++ b/packages/react-components/react-provider/stories/src/CAPThemeProvider/CAPButton.stories.tsx @@ -0,0 +1,74 @@ +import * as React from 'react'; +import { Button } from '@fluentui/react-components'; +import { CAPThemeExamples } from './CAPStorybookUtil'; +import { bundleIcon, CalendarMonthFilled, CalendarMonthRegular } from '@fluentui/react-icons'; + +const CalendarMonth = bundleIcon(CalendarMonthFilled, CalendarMonthRegular); + +export const CAPButtonStory = () => { + return ( + }>Default; + }, + }, + { + title: 'Primary', + render() { + return ( + + ); + }, + }, + { + title: 'Outline', + render() { + return ( + + ); + }, + }, + { + title: 'Subtle', + render() { + return ( + + ); + }, + }, + { + title: 'Transparent', + render() { + return ( + + ); + }, + }, + { + title: 'Tint', + render(variant) { + if (variant === 'v9') { + return 'NOT_IMPLEMENTED'; + } + return ( + + ); + }, + }, + ]} + /> + ); +}; diff --git a/packages/react-components/react-provider/stories/src/CAPThemeProvider/CAPCard.stories.tsx b/packages/react-components/react-provider/stories/src/CAPThemeProvider/CAPCard.stories.tsx new file mode 100644 index 00000000000000..c5f2d73f635b75 --- /dev/null +++ b/packages/react-components/react-provider/stories/src/CAPThemeProvider/CAPCard.stories.tsx @@ -0,0 +1,37 @@ +import * as React from 'react'; +import { Button, Caption1, Card, CardHeader, Text } from '@fluentui/react-components'; +import { CAPThemeExamples } from './CAPStorybookUtil'; +import { MoreHorizontal20Regular } from '@fluentui/react-icons'; + +export const CAPCardStory = () => { + return ( + + + App Name + + } + description={Developer} + action={ +