Skip to content

Commit

Permalink
add disabled style to MenuItem (#129)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kerry authored Nov 12, 2023
1 parent b971ce2 commit ab18737
Show file tree
Hide file tree
Showing 5 changed files with 462 additions and 24 deletions.
10 changes: 10 additions & 0 deletions src/components/MenuItem/MenuItem.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,13 @@ button.item {
.item.interactive[data-kind="critical"]:active {
background: var(--cpd-color-bg-critical-subtle);
}

.item[data-kind].disabled {
pointer-events: none;
}

.item[data-kind].disabled > .label,
.item[data-kind].disabled > .icon,
.item[data-kind].disabled > .nav-hint {
color: var(--cpd-color-text-disabled);
}
114 changes: 90 additions & 24 deletions src/components/MenuItem/MenuItem.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,32 +27,98 @@ export default {
title: "MenuItem",
component: MenuItemComponent,
tags: ["autodocs"],
argTypes: {},
args: {},
} as Meta<typeof MenuItemComponent>;

const Template: StoryFn<typeof MenuItemComponent> = (args) => (
<div style={{ width: 300 }}>
<MenuItemComponent {...args} Icon={ChatIcon} label="First item">
argTypes: {
onClick: { action: "clicked!" },
},
args: {
label: "Menu item",
children: (
<Text as="span" size="sm">
99
</Text>
</MenuItemComponent>
<MenuItemComponent
{...args}
Icon={ExtensionsIcon}
label="Second item with a name that's quite long"
/>
<MenuItemComponent {...args} Icon={SettingsLabel} label={undefined}>
<Text as="span" size="sm">
Third item without a label
</Text>
</MenuItemComponent>
</div>
);
),
Icon: ChatIcon,
},
decorators: [
(Story: StoryFn) => (
<div style={{ width: 300 }}>
<Story />
</div>
),
],
} as Meta<typeof MenuItemComponent>;

export const Example = {
render: () => (
<div style={{ width: 300 }}>
<MenuItemComponent Icon={ChatIcon} label="First item">
<Text as="span" size="sm">
99
</Text>
</MenuItemComponent>
<MenuItemComponent
Icon={ExtensionsIcon}
label="Second item with a name that's quite long"
/>
<MenuItemComponent Icon={SettingsLabel} label={undefined}>
<Text as="span" size="sm">
Third item without a label
</Text>
</MenuItemComponent>
</div>
),
};

export const Primary = {
args: {
kind: "primary",
},
};

export const Primary = Template.bind({});
Primary.args = { kind: "primary" };
export const Critical = {
args: {
kind: "critical",
},
};

export const Critical = Template.bind({});
Critical.args = { kind: "critical" };
export const PrimaryDisabled = {
args: {
...Primary.args,
disabled: true,
},
};

export const CriticalDisabled = {
args: {
...Critical.args,
disabled: true,
},
};

export const WithoutLabel = {
args: {
...Primary.args,
label: undefined,
},
};

export const WithALongLabel = {
args: {
...Primary.args,
label:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
},
};

export const WithALongLabelAndChildren = {
args: {
...Primary.args,
label:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, empor incididunt ut labore et dolore magna aliqua.",
children: (
<Text as="span" size="sm">
Longer children too
</Text>
),
},
};
37 changes: 37 additions & 0 deletions src/components/MenuItem/MenuItem.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@ import MicOnOutlineIcon from "@vector-im/compound-design-tokens/icons/mic-on-out
import { MenuItem } from "./MenuItem";
import { Text } from "../Typography/Text";

import * as stories from "./MenuItem.stories";
import { composeStories } from "@storybook/react";

const {
Primary,
Critical,
PrimaryDisabled,
CriticalDisabled,
WithALongLabel,
WithALongLabelAndChildren,
} = composeStories(stories);

describe("MenuItem", () => {
it("renders", () => {
const { asFragment } = render(
Expand Down Expand Up @@ -51,4 +63,29 @@ describe("MenuItem", () => {
);
expect(asFragment()).toMatchSnapshot();
});

it("renders a Primary menu item", () => {
const { container } = render(<Primary />);
expect(container).toMatchSnapshot();
});
it("renders a Critical menu item", () => {
const { container } = render(<Critical />);
expect(container).toMatchSnapshot();
});
it("renders a Primary Disabled menu item", () => {
const { container } = render(<PrimaryDisabled />);
expect(container).toMatchSnapshot();
});
it("renders a Critical Disabled menu item", () => {
const { container } = render(<CriticalDisabled />);
expect(container).toMatchSnapshot();
});
it("renders a menu item with a long label", () => {
const { container } = render(<WithALongLabel />);
expect(container).toMatchSnapshot();
});
it("renders a menu item with a long label and children", () => {
const { container } = render(<WithALongLabelAndChildren />);
expect(container).toMatchSnapshot();
});
});
5 changes: 5 additions & 0 deletions src/components/MenuItem/MenuItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ type Props<C extends MenuItemElement> = {
* @default primary
*/
kind?: "primary" | "critical";

disabled?: boolean;
} & ComponentPropsWithoutRef<C>;

/**
Expand All @@ -64,6 +66,7 @@ export const MenuItem = <C extends MenuItemElement = "button">({
label,
kind = "primary",
children,
disabled,
...props
}: Props<C>): JSX.Element => {
const Component = as ?? ("button" as ElementType);
Expand All @@ -75,8 +78,10 @@ export const MenuItem = <C extends MenuItemElement = "button">({
className={classnames(className, styles.item, {
[styles.interactive]: as !== "div",
[styles["no-label"]]: label === undefined,
[styles["disabled"]]: disabled,
})}
data-kind={kind}
disabled={disabled}
>
<Icon width={24} height={24} className={styles.icon} aria-hidden={true} />
{label !== undefined && (
Expand Down
Loading

0 comments on commit ab18737

Please sign in to comment.