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

MenuButton: Re-introducing MenuButton using the latest version of makeStyles #18168

Merged
merged 33 commits into from
Jun 3, 2021
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
fb90b01
MenuButton: Re-introducing MenuButton using the latest version of mak…
khmakoto May 13, 2021
d0e7240
Change files
khmakoto May 13, 2021
96ab486
Fixing merge conflict.
khmakoto May 13, 2021
6bc4667
Updating API.
khmakoto May 13, 2021
e40175f
Improving example by showing MenuButton working with both v8's Contex…
khmakoto May 13, 2021
e0710cf
Fixing merge conflict.
khmakoto May 13, 2021
d175e8b
Change files
khmakoto May 13, 2021
b0df477
Fixing wrong Button vr-tests.
khmakoto May 14, 2021
2b635d0
Fixing merge conflict.
khmakoto May 21, 2021
b48333f
Change files
khmakoto May 21, 2021
db120f7
Calculating iconOnly in useButtonState.
khmakoto May 21, 2021
4857c38
Fixing merge conflict.
khmakoto May 21, 2021
7545114
Change files
khmakoto May 21, 2021
fa958a0
Updating API.
khmakoto May 21, 2021
1b7b33c
Fixing merge conflicts.
khmakoto May 28, 2021
5d40317
Addressing some PR feedback.
khmakoto May 29, 2021
7ab9997
Addressing some PR feedback around the use of the useControllableValu…
khmakoto May 29, 2021
9efd212
Using resolveShorthandProps on the defaultProps of Button and Compoun…
khmakoto May 29, 2021
b6133f9
Moving onlyChild as part of react-utilities and adding tests.
khmakoto May 29, 2021
6b40d32
Change files
khmakoto May 29, 2021
2841d5e
Modifying MenuButton.stories.tsx to adhere to new Playground type gua…
khmakoto May 29, 2021
0fc0e3b
Fixing errors in stories due to changes in Playground type guards.
khmakoto May 29, 2021
34b904a
Delete @fluentui-react-components-ba379fbe-3151-4479-a3e8-bfc0ec6a422…
khmakoto May 29, 2021
6a786c7
Delete @fluentui-react-menu-6626299c-5cf8-43f9-ba7f-4081c0a07d2b.json
khmakoto May 29, 2021
fda3ea3
Fixing merge conflict.
khmakoto Jun 1, 2021
b6549ba
Removing menu slot and simplifying API.
khmakoto Jun 1, 2021
b2e29e3
Fixing error in vr stories.
khmakoto Jun 1, 2021
5d3f190
Fixing error in vr stories.
khmakoto Jun 1, 2021
f6ca650
Removing unused contract from MenuButton while we wait for MenuTrigge…
khmakoto Jun 3, 2021
5aba837
Fixing merge conflicts.
khmakoto Jun 3, 2021
33b0c09
Fixing merge conflicts.
khmakoto Jun 3, 2021
92e24d5
Reverting Flex migration changes.
khmakoto Jun 3, 2021
65eeee5
Fixing error in vr-tests.
khmakoto Jun 3, 2021
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
1 change: 1 addition & 0 deletions apps/test-bundles/webpackUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ function createFluentConvergedFixtures() {
'Image',
'Link',
'Menu',
'MenuButton',
'Portal',
'ToggleButton',
'Tooltip',
Expand Down
96 changes: 93 additions & 3 deletions apps/vr-tests/src/stories/ReactButton.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import { storiesOf } from '@storybook/react';
import * as React from 'react';
import Screener from 'screener-storybook/src/screener';
import { Button, ButtonProps, CompoundButton, ToggleButton } from '@fluentui/react-button';
import { ContextualMenu } from '@fluentui/react';
import {
Button,
ButtonProps,
CompoundButton,
ToggleButton,
MenuButton,
} from '@fluentui/react-button';

import { FluentProviderDecorator, FabricDecorator } from '../utilities/index';

Expand Down Expand Up @@ -162,7 +169,7 @@ storiesOf('react-button CompoundButton', module)
</CompoundButton>
))
.addStory('Size small', () => (
<CompoundButton secondaryContent="This is some secondary text" icon="X" size="large">
<CompoundButton secondaryContent="This is some secondary text" icon="X" size="small">
Hello, world
</CompoundButton>
))
Expand Down Expand Up @@ -217,7 +224,7 @@ storiesOf('react-button ToggleButton', module)
</ToggleButton>
))
.addStory('Size small', () => (
<ToggleButton icon="X" size="large">
<ToggleButton icon="X" size="small">
Hello, world
</ToggleButton>
))
Expand Down Expand Up @@ -247,3 +254,86 @@ storiesOf('react-button ToggleButton', module)
Hello, world
</ToggleButton>
));

const menuProps = {
items: [
{
key: 'a',
name: 'Item a',
},
{
key: 'b',
name: 'Item b',
},
],
};

storiesOf('react-button MenuButton', module)
.addDecorator(FabricDecorator)
.addDecorator(FluentProviderDecorator)
.addDecorator(story => (
<Screener
steps={new Screener.Steps()
.snapshot('default', { cropTo: '.testWrapper' })
.hover('button')
.snapshot('hover', { cropTo: '.testWrapper' })
.mouseDown('button')
.snapshot('pressed', { cropTo: '.testWrapper' })
.mouseUp('button')
.end()}
>
{story()}
</Screener>
))
.addStory('Default', () => <MenuButton>Hello, world</MenuButton>)
.addStory('Primary', () => <MenuButton primary>Hello, world</MenuButton>)
.addStory('Subtle', () => <MenuButton subtle>Hello, world</MenuButton>)
.addStory('Transparent', () => <MenuButton transparent>Hello, world</MenuButton>)
.addStory('Disabled', () => <MenuButton disabled>Hello, world</MenuButton>)
.addStory('Primary Disabled', () => (
<MenuButton primary disabled>
Hello, world
</MenuButton>
))
.addStory('Subtle Disabled', () => (
<MenuButton subtle disabled>
Hello, world
</MenuButton>
))
.addStory('Transparent Disabled', () => (
<MenuButton transparent disabled>
Hello, world
</MenuButton>
))
.addStory('With icon', () => <MenuButton icon="X">Hello, world</MenuButton>)
.addStory('Size small', () => (
<MenuButton icon="X" size="small">
Hello, world
</MenuButton>
))
.addStory('Size large', () => (
<MenuButton icon="X" size="large">
Hello, world
</MenuButton>
))
.addStory('Icon only', () => <MenuButton icon="X" />)
.addStory('Expanded', () => (
<MenuButton icon="X" expanded menu={<ContextualMenu {...menuProps} />}>
Hello, world
</MenuButton>
))
.addStory('Primary Expanded', () => (
<MenuButton icon="X" primary expanded menu={<ContextualMenu {...menuProps} />}>
Hello, world
</MenuButton>
))
.addStory('Subtle Expanded', () => (
<MenuButton icon="X" subtle expanded menu={<ContextualMenu {...menuProps} />}>
Hello, world
</MenuButton>
))
.addStory('Transparent Expanded', () => (
<MenuButton icon="X" transparent expanded menu={<ContextualMenu {...menuProps} />}>
Hello, world
</MenuButton>
));
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "MenuButton: Re-introducing MenuButton using the latest version of makeStyles.",
"packageName": "@fluentui/react-button",
"email": "Humberto.Morimoto@microsoft.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "Bumping wrong version of dependency.",
"packageName": "@fluentui/react-components",
"email": "Humberto.Morimoto@microsoft.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Adding MenuButton stories.",
"packageName": "@fluentui/react-examples",
"email": "Humberto.Morimoto@microsoft.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "Prettier update.",
"packageName": "@fluentui/react-menu",
"email": "Humberto.Morimoto@microsoft.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "Modifying MinimalMenuProps target prop to only be React.Ref<HTMLElement> instead of React.Ref<HTMLElement | undefined>.",
"packageName": "@fluentui/react-shared-contexts",
"email": "Humberto.Morimoto@microsoft.com",
"dependentChangeType": "patch"
}
79 changes: 76 additions & 3 deletions packages/react-button/etc/react-button.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
```ts

import { ComponentProps } from '@fluentui/react-utilities';
import { MinimalMenuProps } from '@fluentui/react-shared-contexts';
import { ObjectShorthandProps } from '@fluentui/react-utilities';
import * as React_2 from 'react';
import { ShorthandProps } from '@fluentui/react-utilities';
Expand All @@ -16,7 +17,6 @@ export const Button: React_2.FunctionComponent<ButtonProps & React_2.RefAttribut
export type ButtonProps = ComponentProps & React_2.ButtonHTMLAttributes<HTMLElement> & {
icon?: ShorthandProps<React_2.HTMLAttributes<HTMLSpanElement>>;
disabled?: boolean;
iconOnly?: boolean;
iconPosition?: 'before' | 'after';
primary?: boolean;
size?: 'small' | 'medium' | 'large';
Expand All @@ -25,14 +25,15 @@ export type ButtonProps = ComponentProps & React_2.ButtonHTMLAttributes<HTMLElem
};

// @public
export const buttonShorthandProps: readonly ["icon", "children"];
export const buttonShorthandProps: readonly ["children", "icon"];

// @public (undocumented)
export interface ButtonState extends ButtonProps {
// (undocumented)
children?: ObjectShorthandProps<React_2.HTMLAttributes<HTMLSpanElement>>;
// (undocumented)
icon?: ObjectShorthandProps<React_2.HTMLAttributes<HTMLSpanElement>>;
iconOnly?: boolean;
// (undocumented)
ref: React_2.Ref<HTMLElement>;
}
Expand Down Expand Up @@ -115,7 +116,7 @@ export interface CompoundButtonProps extends ButtonProps {
}

// @public
export const compoundButtonShorthandProps: readonly ["icon", "children", "contentContainer", "secondaryContent"];
export const compoundButtonShorthandProps: readonly ["children", "contentContainer", "icon", "secondaryContent"];

// @public (undocumented)
export interface CompoundButtonState extends Omit<CompoundButtonProps, 'children' | 'icon'>, ButtonState {
Expand Down Expand Up @@ -144,6 +145,63 @@ export type CompoundButtonVariantTokens = Partial<{
[variant in CompoundButtonVariants]: Partial<CompoundButtonTokens>;
}>;

// @public (undocumented)
export type ExpandedState = {
menu?: MenuButtonState['menu'];
defaultExpanded?: boolean;
expanded?: boolean;
onClick?: MenuButtonState['onClick'];
onKeyDown?: MenuButtonState['onKeyDown'];
onMenuDismiss?: MenuButtonState['onMenuDismiss'];
ref?: React_2.Ref<unknown>;
'aria-expanded'?: MenuButtonState['aria-expanded'];
'aria-haspopup'?: MenuButtonState['aria-haspopup'];
};

// @public
export const MenuButton: React_2.FunctionComponent<MenuButtonProps & React_2.RefAttributes<HTMLElement>>;

// @public (undocumented)
export type MenuButtonProps = Omit<ButtonProps, 'iconPosition'> & {
menu?: ShorthandProps<MinimalMenuProps & ComponentProps>;
menuIcon?: ShorthandProps<React_2.HTMLAttributes<HTMLSpanElement>>;
defaultExpanded?: boolean;
expanded?: boolean;
persistMenu?: boolean;
onMenuDismiss?: (ev?: Event | React_2.MouseEvent<HTMLElement> | React_2.KeyboardEvent<HTMLElement>) => void;
};

// @public
export const menuButtonShorthandProps: readonly ["children", "icon", "menu", "menuIcon"];

// @public (undocumented)
export interface MenuButtonState extends Omit<MenuButtonProps, 'children' | 'icon' | 'menu'>, Omit<ButtonState, 'iconPosition'> {
// (undocumented)
menu?: ObjectShorthandProps<MinimalMenuProps & ComponentProps>;
// (undocumented)
menuIcon?: ObjectShorthandProps<React_2.HTMLAttributes<HTMLSpanElement>>;
}

// @public (undocumented)
export type MenuButtonStyleSelectors = ButtonStyleSelectors & {
expanded?: boolean;
};

// @public (undocumented)
export type MenuButtonTokens = ButtonTokens & {
menuIconFontSize?: string;
menuIconHeight?: string;
menuIconWidth?: string;
};

// @public (undocumented)
export type MenuButtonVariants = ButtonVariants;

// @public (undocumented)
export type MenuButtonVariantTokens = Partial<{
[variant in MenuButtonVariants]: Partial<MenuButtonTokens>;
}>;

// @public
const renderButton: (state: ButtonState) => JSX.Element;

Expand All @@ -154,6 +212,9 @@ export { renderButton as renderToggleButton }
// @public
export const renderCompoundButton: (state: CompoundButtonState) => JSX.Element;

// @public
export const renderMenuButton: (state: MenuButtonState) => JSX.Element;

// @public
export const ToggleButton: React_2.ForwardRefExoticComponent<ToggleButtonProps & React_2.RefAttributes<HTMLElement>>;

Expand Down Expand Up @@ -201,6 +262,18 @@ export const useCompoundButton: (props: CompoundButtonProps, ref: React_2.Ref<HT
// @public (undocumented)
export const useCompoundButtonStyles: (state: CompoundButtonState, selectors: CompoundButtonStyleSelectors) => void;

// @public (undocumented)
export const useExpanded: <TState extends ExpandedState>(state: TState) => TState;

// @public
export const useMenuButton: (props: MenuButtonProps, ref: React_2.Ref<HTMLElement>, defaultProps?: MenuButtonProps | undefined) => MenuButtonState;

// @public (undocumented)
export const useMenuButtonState: (state: MenuButtonState) => MenuButtonState;

// @public (undocumented)
export const useMenuButtonStyles: (state: MenuButtonState, selectors: MenuButtonStyleSelectors) => void;

// @public (undocumented)
export const useToggleButton: (props: ToggleButtonProps, ref: React_2.Ref<HTMLElement>, defaultProps?: ToggleButtonProps | undefined) => ToggleButtonState;

Expand Down
2 changes: 2 additions & 0 deletions packages/react-button/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@
},
"dependencies": {
"@fluentui/keyboard-key": "^0.3.1",
"@fluentui/react-icons-mdl2": "^1.1.1",
khmakoto marked this conversation as resolved.
Show resolved Hide resolved
"@fluentui/react-make-styles": "^9.0.0-alpha.37",
"@fluentui/react-shared-contexts": "^9.0.0-alpha.12",
khmakoto marked this conversation as resolved.
Show resolved Hide resolved
"@fluentui/react-theme": "^9.0.0-alpha.13",
"@fluentui/react-utilities": "^9.0.0-alpha.24",
"tslib": "^2.1.0"
Expand Down
1 change: 1 addition & 0 deletions packages/react-button/src/MenuButton.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './components/MenuButton/index';
5 changes: 1 addition & 4 deletions packages/react-button/src/components/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,9 @@ export const Button: React.FunctionComponent<ButtonProps & React.RefAttributes<H
>((props, ref) => {
const state = useButton(props, ref);

const receivedChildren = !!state.children?.children;
const receivedIcon = !!state.icon?.children;

const styleSelectors: ButtonStyleSelectors = {
disabled: state.disabled,
iconOnly: receivedIcon && !receivedChildren,
iconOnly: state.iconOnly,
primary: state.primary,
size: state.size,
subtle: state.subtle,
Expand Down
12 changes: 6 additions & 6 deletions packages/react-button/src/components/Button/Button.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,6 @@ export type ButtonProps = ComponentProps &
// */
// disabledFocusable?: boolean;

/**
* A button can contain only an icon.
* @default false
*/
iconOnly?: boolean;

/**
* A button can format its icon to appear before or after its content.
* @default 'before'
Expand Down Expand Up @@ -104,6 +98,12 @@ export type ButtonProps = ComponentProps &
* {@docCategory Button}
*/
export interface ButtonState extends ButtonProps {
/**
* A button can contain only an icon.
* @default false
*/
iconOnly?: boolean;

ref: React.Ref<HTMLElement>;

icon?: ObjectShorthandProps<React.HTMLAttributes<HTMLSpanElement>>;
Expand Down
3 changes: 1 addition & 2 deletions packages/react-button/src/components/Button/useButton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useButtonState } from './useButtonState';
/**
* Consts listing which props are shorthand props.
*/
export const buttonShorthandProps = ['icon', 'children'] as const;
export const buttonShorthandProps = ['children', 'icon'] as const;

// eslint-disable-next-line deprecation/deprecation
const mergeProps = makeMergePropsCompat<ButtonState>({ deepMerge: buttonShorthandProps });
Expand All @@ -24,7 +24,6 @@ export const useButton = (props: ButtonProps, ref: React.Ref<HTMLElement>, defau
ref: resolvedRef,
as: 'button',
icon: { as: 'span' },
loader: { as: 'span' },
},
defaultProps,
resolveShorthandProps(props, buttonShorthandProps),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import { ButtonState } from './Button.types';
* @param state - Button draft state to mutate.
*/
export const useButtonState = (state: ButtonState): ButtonState => {
const { as, disabled, /*disabledFocusable,*/ onClick, onKeyDown: onKeyDownCallback } = state;
const { as, children, disabled, /*disabledFocusable,*/ icon, onClick, onKeyDown: onKeyDownCallback } = state;
khmakoto marked this conversation as resolved.
Show resolved Hide resolved

const receivedChildren = !!children?.children;
const receivedIcon = !!icon?.children;
state.iconOnly = receivedIcon && !receivedChildren;

const onNonAnchorOrButtonKeyDown = (ev: React.KeyboardEvent<HTMLElement>) => {
onKeyDownCallback?.(ev);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,9 @@ import { useCompoundButtonStyles } from './useCompoundButtonStyles';
export const CompoundButton = React.forwardRef<HTMLElement, CompoundButtonProps>((props, ref) => {
const state = useCompoundButton(props, ref);

const receivedChildren = !!state.children?.children;
const receivedIcon = !!state.icon?.children;

const styleSelectors: CompoundButtonStyleSelectors = {
disabled: state.disabled,
iconOnly: receivedIcon && !receivedChildren,
iconOnly: state.iconOnly,
primary: state.primary,
size: state.size,
subtle: state.subtle,
Expand Down
Loading