Skip to content

Commit

Permalink
feat(Button): support warning color with outlined variant (#1499)
Browse files Browse the repository at this point in the history
## 📝 Changes

- Supports warning color and outlined variant combination

![Screenshot 2024-11-27 at 12 43
00 PM](https://github.com/user-attachments/assets/9703ce8c-eaae-48c4-b3ea-4c8c20df7a4b)



## ✅ Checklist

Easy UI has certain UX standards that must be met. In general,
non-trivial changes should meet the following criteria:

- [x] Visuals match Design Specs in Figma
- [x] Stories accompany any component changes
- [x] Code is in accordance with our style guide
- [ ] ~Design tokens are utilized~
- [x] Unit tests accompany any component changes
- [x] TSDoc is written for any API surface area
- [ ] ~Specs are up-to-date~
- [x] Console is free from warnings
- [x] No accessibility violations are reported
- [x] Cross-browser check is performed (Chrome, Safari, Firefox)
- [x] Changeset is added

~Strikethrough~ any items that are not applicable to this pull request.
  • Loading branch information
OskiTheCoder authored Nov 27, 2024
1 parent 439294c commit a747675
Show file tree
Hide file tree
Showing 11 changed files with 291 additions and 145 deletions.
5 changes: 5 additions & 0 deletions .changeset/modern-guests-bake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@easypost/easy-ui": minor
---

feat(Button): support warning color with outlined variant
60 changes: 44 additions & 16 deletions easy-ui-react/src/Button/Button.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,65 @@ import * as ButtonStories from "./Button.stories";

# Button

## Filled buttons
A `<Button />` enables users to take an action or transition to other pages. They are designed with multiple styles to address various needs, and they are ideal for highlighting an action for the user to take in order to move forward in a flow.

<Canvas of={ButtonStories.FilledButtons} />
**Note**: Each `<Button />` variant support a subset of colors from the `color` property.

## Outlined buttons
## Filled

<Canvas of={ButtonStories.OutlinedButtons} />
By default, a `<Button />` renders as a filled variant.

## Link buttons
<Canvas of={ButtonStories.Filled} />

<Canvas of={ButtonStories.LinkButtons} />
<Controls of={ButtonStories.Filled} include={["color"]} />

## Inverse buttons
## Outlined

<Canvas of={ButtonStories.InverseButtons} />
Use `variant="outlined"` to render an outlined variant.

## With href
<Canvas of={ButtonStories.Outlined} />

<Canvas of={ButtonStories.WithHref} />
<Controls of={ButtonStories.Outlined} include={["color"]} />

## With icons
## Link

<Canvas of={ButtonStories.WithIcons} />
Use `variant="link"` to render a link variant.

## Block button
<Canvas of={ButtonStories.Link} />

<Canvas of={ButtonStories.BlockButton} />
<Controls of={ButtonStories.Link} include={["color"]} />

## Disabled buttons
## Icons

<Canvas of={ButtonStories.DisabledButtons} />
Use `iconAtStart` or `iconAtEnd` to render an icon.

<Canvas of={ButtonStories.Icons} />

<Controls of={ButtonStories.Icons} />

## Href

Use `href` to for navigation.

<Canvas of={ButtonStories.Href} />

## Small

Use `size="sm"` to render a smaller `<Button />`.

<Canvas of={ButtonStories.Small} />

## Inverse

<Canvas of={ButtonStories.Inverse} />

## Block

<Canvas of={ButtonStories.Block} />

## Disabled

<Canvas of={ButtonStories.Disabled} />

## Click event

Expand Down
118 changes: 65 additions & 53 deletions easy-ui-react/src/Button/Button.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import {
InlineStoryDecorator,
InlineStoryOnDarkBackgroundDecorator,
createLabelledOptionsControl,
getFilledButtonsColorMapping,
getLinkButtonsColorMapping,
getOutlinedButtonsColorMapping,
} from "../utilities/storybook";
import { Button, ButtonProps } from "./Button";

Expand All @@ -22,10 +25,16 @@ const meta: Meta<typeof Button> = {
iconAtStart: createLabelledOptionsControl({
ArrowBack: ArrowBackIcon,
Add: AddIcon,
CheckCircle: CheckCircleIcon,
Info: InfoIcon,
None: undefined,
}),
iconAtEnd: createLabelledOptionsControl({
ArrowBack: ArrowBackIcon,
Add: AddIcon,
CheckCircle: CheckCircleIcon,
Info: InfoIcon,
None: undefined,
}),
children: {
control: "text",
Expand All @@ -36,91 +45,89 @@ const meta: Meta<typeof Button> = {

export default meta;

export const Controls: Story = {
export const Filled: Story = {
render: Template.bind({}),
args: {},
args: {
color: "primary",
},
};

export const FilledButtons: Story = {
render: () => (
<>
<Button />
<Button color="secondary" />
<Button color="success" />
<Button color="warning" />
<Button color="neutral" />
<Button size="sm" />
<Button color="secondary" size="sm" />
<Button color="success" size="sm" />
<Button color="warning" size="sm" />
<Button color="neutral" size="sm" />
</>
),
decorators: [InlineStoryDecorator],
Filled.argTypes = {
color: getFilledButtonsColorMapping(),
};

export const OutlinedButtons: Story = {
render: () => (
<>
<Button variant="outlined" />
<Button color="secondary" variant="outlined" />
<Button color="support" variant="outlined" />
<Button variant="outlined" size="sm" />
<Button color="secondary" variant="outlined" size="sm" />
<Button color="support" variant="outlined" size="sm" />
</>
),
decorators: [InlineStoryDecorator],
export const Outlined: Story = {
render: Template.bind({}),
args: {
variant: "outlined",
color: "primary",
},
};

export const LinkButtons: Story = {
render: () => (
<>
<Button variant="link" />
<Button color="secondary" variant="link" />
</>
),
decorators: [InlineStoryDecorator],
Outlined.argTypes = {
color: getOutlinedButtonsColorMapping(),
};

export const Link: Story = {
render: Template.bind({}),
args: {
variant: "link",
color: "primary",
},
};

export const InverseButtons: Story = {
Link.argTypes = {
color: getLinkButtonsColorMapping(),
};

export const Icons: Story = {
render: Template.bind({}),
args: {
iconAtStart: AddIcon,
},
parameters: {
controls: {
include: ["iconAtStart", "iconAtEnd", "children"],
},
},
};

export const Href: Story = {
render: () => (
<>
<Button color="inverse" variant="outlined" />
<Button color="inverse" variant="outlined" size="sm" />
<Button href="https://www.easypost.com/" />
<Button variant="outlined" href="https://www.easypost.com/" />
</>
),
decorators: [InlineStoryOnDarkBackgroundDecorator],
decorators: [InlineStoryDecorator],
};

export const WithHref: Story = {
export const Small: Story = {
render: () => (
<>
<Button href="https://www.easypost.com/" />
<Button variant="outlined" href="https://www.easypost.com/" />
<Button size="sm" />
<Button variant="outlined" size="sm" />
</>
),
decorators: [InlineStoryDecorator],
};

export const WithIcons: Story = {
export const Inverse: Story = {
render: () => (
<>
<Button iconAtEnd={CheckCircleIcon} />
<Button color="neutral" iconAtEnd={AddIcon} />
<Button color="success" iconAtStart={ArrowBackIcon} />
<Button color="warning" iconAtStart={InfoIcon} />
<Button color="inverse" variant="outlined" />
<Button color="inverse" variant="outlined" size="sm" />
</>
),
decorators: [InlineStoryDecorator],
decorators: [InlineStoryOnDarkBackgroundDecorator],
};

export const BlockButton: Story = {
export const Block: Story = {
render: () => <Button isBlock />,
decorators: [InlineStoryDecorator],
};

export const DisabledButtons: Story = {
export const Disabled: Story = {
render: () => (
<>
<Button isDisabled />
Expand All @@ -134,3 +141,8 @@ export const ClickEvent: Story = {
render: () => <Button onPress={action("clicked!")} />,
decorators: [InlineStoryDecorator],
};

export const Controls: Story = {
render: Template.bind({}),
args: {},
};
12 changes: 12 additions & 0 deletions easy-ui-react/src/Button/Button.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,18 @@ describe("<Button />", () => {
);
});

it("should apply the outlined variant class with a color", () => {
render(<Button color="warning" variant="outlined" />);
expect(screen.getByRole("button")).toHaveAttribute(
"class",
expect.stringContaining("variantOutlined"),
);
expect(screen.getByRole("button")).toHaveAttribute(
"class",
expect.stringContaining("colorWarning"),
);
});

it("should render a disabled button", () => {
render(<Button isDisabled />);
expect(screen.getByRole("button")).toBeDisabled();
Expand Down
4 changes: 3 additions & 1 deletion easy-ui-react/src/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ export type ButtonProps = AriaButtonProps & {
};

/**
* Allow users to perform an action or to navigate to another page.
* A `<Button />` enables users to take an action or transition to other pages.
* They are designed with multiple styles to address various needs, and they are
* ideal for highlighting an action for the user to take in order to move forward in a flow.
*
* @remarks
* Use to communicate an action the user can take in order to continue
Expand Down
24 changes: 21 additions & 3 deletions easy-ui-react/src/Button/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,32 @@ import omit from "lodash/omit";
import { ButtonColor } from "./Button";
import { ButtonVariant } from "./Button";

export const FILLED_BUTTON_COLORS = [
"primary",
"secondary",
"success",
"warning",
"neutral",
];

export const OUTLINED_BUTTON_COLORS = [
"primary",
"secondary",
"support",
"warning",
"inverse",
];

export const LINK_BUTTON_COLORS = ["primary", "secondary"];

export function logWarningIfInvalidColorVariantCombination(
color: ButtonColor,
variant: ButtonVariant,
): void {
const validColorVariantCombinations = {
filled: ["primary", "secondary", "success", "warning", "neutral"],
outlined: ["primary", "secondary", "support", "inverse"],
link: ["primary", "secondary"],
filled: FILLED_BUTTON_COLORS,
outlined: OUTLINED_BUTTON_COLORS,
link: LINK_BUTTON_COLORS,
};
if (!validColorVariantCombinations[variant]?.includes(color)) {
// eslint-disable-next-line no-console
Expand Down
24 changes: 16 additions & 8 deletions easy-ui-react/src/DropdownButton/DropdownButton.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,29 @@ import * as DropdownButtonStories from "./DropdownButton.stories";

# DropdownButton

## Filled buttons
## Filled

<Canvas of={DropdownButtonStories.FilledButtons} />
By default, a `<DropdownButton />` renders as a filled variant.

## Outlined buttons
<Canvas of={DropdownButtonStories.Filled} />

<Canvas of={DropdownButtonStories.OutlinedButtons} />
<Controls of={DropdownButtonStories.Filled} include={["color"]} />

## Inverse button
## Outlined

<Canvas of={DropdownButtonStories.InverseButtons} />
Use `variant="outlined"` to render an outlined variant.

## Disabled buttons
<Canvas of={DropdownButtonStories.Outlined} />

<Canvas of={DropdownButtonStories.DisabledButtons} />
<Controls of={DropdownButtonStories.Outlined} include={["color"]} />

## Inverse

<Canvas of={DropdownButtonStories.Inverse} />

## Disabled

<Canvas of={DropdownButtonStories.Disabled} />

## Click event

Expand Down
Loading

0 comments on commit a747675

Please sign in to comment.