✨(react) add icon to Button
The DS does not offer an icons set yet but it seems important to already provide a support for external icons in Button.
This commit is contained in:
@@ -12,6 +12,18 @@
|
|||||||
font-size: var(--c--components--button--font-size);
|
font-size: var(--c--components--button--font-size);
|
||||||
font-weight: var(--c--components--button--font-weight);
|
font-weight: var(--c--components--button--font-weight);
|
||||||
|
|
||||||
|
&--with-icon--left, &--with-icon--right {
|
||||||
|
gap: var(--c--theme--spacings--t);
|
||||||
|
}
|
||||||
|
|
||||||
|
&--with-icon--left {
|
||||||
|
padding: 0 var(--c--theme--spacings--s) 0 var(--c--theme--spacings--t);
|
||||||
|
}
|
||||||
|
|
||||||
|
&--with-icon--right {
|
||||||
|
padding: 0 var(--c--theme--spacings--t) 0 var(--c--theme--spacings--s);
|
||||||
|
}
|
||||||
|
|
||||||
&--primary {
|
&--primary {
|
||||||
background-color: var(--c--theme--colors--primary-500);
|
background-color: var(--c--theme--colors--primary-500);
|
||||||
color: var(--c--theme--colors--primary-text);
|
color: var(--c--theme--colors--primary-text);
|
||||||
|
|||||||
@@ -12,6 +12,24 @@ describe("<Button/>", () => {
|
|||||||
expect(button.classList.contains("c__button")).toBe(true);
|
expect(button.classList.contains("c__button")).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("renders with custom class when using left icon", () => {
|
||||||
|
render(<Button icon={<div>Icon</div>}>Test button</Button>);
|
||||||
|
const button = screen.getByText("Test button");
|
||||||
|
expect(button.classList.contains("c__button")).toBe(true);
|
||||||
|
expect(button.classList.contains("c__button--with-icon--left")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders with custom class when using right icon", () => {
|
||||||
|
render(
|
||||||
|
<Button icon={<div>Icon</div>} iconPosition="right">
|
||||||
|
Test button
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
const button = screen.getByText("Test button");
|
||||||
|
expect(button.classList.contains("c__button")).toBe(true);
|
||||||
|
expect(button.classList.contains("c__button--with-icon--right")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
it("call onClick when click occurs", async () => {
|
it("call onClick when click occurs", async () => {
|
||||||
const user = userEvent.setup();
|
const user = userEvent.setup();
|
||||||
const handleClick = vi.fn();
|
const handleClick = vi.fn();
|
||||||
|
|||||||
@@ -22,6 +22,19 @@ The Cunningham Button behaves the same as the native html `<button>` element, bu
|
|||||||
code={`import { Button } from "@openfun/cunningham-react";`}
|
code={`import { Button } from "@openfun/cunningham-react";`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
## Icons
|
||||||
|
|
||||||
|
You can use icons within the button by passing the icon name as a prop.
|
||||||
|
|
||||||
|
> Use the attribute `iconPosition` to position the icon on the left or right side of the button. The default is `left`.
|
||||||
|
|
||||||
|
<Canvas withSource="open">
|
||||||
|
<Story id="button--icon-left"/>
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
|
<Canvas withSource="open">
|
||||||
|
<Story id="button--icon-right"/>
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
## Disabled
|
## Disabled
|
||||||
|
|
||||||
|
|||||||
@@ -33,3 +33,54 @@ Disabled.args = {
|
|||||||
color: "primary",
|
color: "primary",
|
||||||
disabled: true,
|
disabled: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const Danger = Template.bind({});
|
||||||
|
Danger.args = {
|
||||||
|
children: "Danger",
|
||||||
|
color: "danger",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const IconLeft = Template.bind({});
|
||||||
|
IconLeft.args = {
|
||||||
|
children: "Icon",
|
||||||
|
icon: (
|
||||||
|
<svg
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
fillRule="evenodd"
|
||||||
|
clipRule="evenodd"
|
||||||
|
d="M17.8724 10.0166H13.248L16.6251 4.07749C16.9258 3.54846 16.2447 3.01176 15.8005 3.42755L6.57343 12.0655C6.22192 12.3946 6.45489 12.9838 6.93615 12.9838H11.5606L8.18353 18.9229C7.88275 19.4519 8.56335 19.9886 9.00746 19.5728L18.2352 10.9349C18.5867 10.6058 18.3537 10.0166 17.8724 10.0166Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
color: "primary",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const IconRight = Template.bind({});
|
||||||
|
IconRight.args = {
|
||||||
|
children: "Icon",
|
||||||
|
iconPosition: "right",
|
||||||
|
icon: (
|
||||||
|
<svg
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
fillRule="evenodd"
|
||||||
|
clipRule="evenodd"
|
||||||
|
d="M17.8724 10.0166H13.248L16.6251 4.07749C16.9258 3.54846 16.2447 3.01176 15.8005 3.42755L6.57343 12.0655C6.22192 12.3946 6.45489 12.9838 6.93615 12.9838H11.5606L8.18353 18.9229C7.88275 19.4519 8.56335 19.9886 9.00746 19.5728L18.2352 10.9349C18.5867 10.6058 18.3537 10.0166 17.8724 10.0166Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
color: "primary",
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,13 +1,27 @@
|
|||||||
import React, { ButtonHTMLAttributes } from "react";
|
import React, { ButtonHTMLAttributes, ReactNode } from "react";
|
||||||
|
|
||||||
interface Props extends ButtonHTMLAttributes<HTMLButtonElement> {
|
interface Props extends ButtonHTMLAttributes<HTMLButtonElement> {
|
||||||
color?: "primary" | "secondary" | "tertiary";
|
color?: "primary" | "secondary" | "tertiary";
|
||||||
|
icon?: ReactNode;
|
||||||
|
iconPosition?: "left" | "right";
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Button = ({ children, color = "primary", ...props }: Props) => {
|
export const Button = ({
|
||||||
|
children,
|
||||||
|
color = "primary",
|
||||||
|
iconPosition = "left",
|
||||||
|
icon,
|
||||||
|
...props
|
||||||
|
}: Props) => {
|
||||||
|
const classes = ["c__button", "c__button--" + color];
|
||||||
|
if (icon) {
|
||||||
|
classes.push("c__button--with-icon--" + iconPosition);
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<button className={"c__button c__button--" + color} {...props}>
|
<button className={classes.join(" ")} {...props}>
|
||||||
|
{!!icon && iconPosition === "left" && icon}
|
||||||
{children}
|
{children}
|
||||||
|
{!!icon && iconPosition === "right" && icon}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user