(react) add button with icon only

Previously using Button with only an icon made it render with an
internal offset, that wasn't really nice-looking. Now we force the
button to be squared.
This commit is contained in:
Nathan Vasse
2023-02-13 12:07:38 +01:00
committed by NathanVss
parent 89138e0a5a
commit 722b66b3ae
6 changed files with 59 additions and 6 deletions

View File

@@ -0,0 +1,5 @@
---
"@openfun/cunningham-react": patch
---
Make Button handle icon only

View File

@@ -12,6 +12,12 @@
font-size: var(--c--components--button--font-size);
font-weight: var(--c--components--button--font-weight);
&--icon-only {
padding: 0;
width: var(--c--components--button--height);
justify-content: center;
}
&--with-icon--left, &--with-icon--right {
gap: var(--c--theme--spacings--t);
}

View File

@@ -9,14 +9,25 @@ describe("<Button/>", () => {
it("renders", () => {
render(<Button>Test button</Button>);
const button = screen.getByRole("button", { name: "Test button" });
expect(button.classList.contains("c__button")).toBe(true);
expect(Array.from(button.classList)).toContain("c__button");
});
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);
const classes = Array.from(button.classList);
expect(classes).toContain("c__button");
expect(classes).toContain("c__button--with-icon--left");
});
it("renders with modifier class --icon-only when only icon is defined", () => {
render(<Button icon={<div>Icon</div>} />);
const button = screen.getByRole("button");
const classes = Array.from(button.classList);
expect(classes).toContain("c__button");
expect(classes).toContain("c__button--icon-only");
expect(classes).not.toContain("c__button--with-icon--left");
expect(classes).not.toContain("c__button--with-icon--right");
});
it("renders with custom class when using right icon", () => {
@@ -26,8 +37,9 @@ describe("<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);
const classes = Array.from(button.classList);
expect(classes).toContain("c__button");
expect(classes).toContain("c__button--with-icon--right");
});
it("call onClick when click occurs", async () => {

View File

@@ -37,6 +37,12 @@ You can use icons within the button by passing the icon name as a prop.
<Story id="components-button--icon-right"/>
</Canvas>
You can also use button with only an icon.
<Canvas withSource="open">
<Story id="components-button--icon-only"/>
</Canvas>
## Disabled
The button can be disabled. The disabled button will render the same no matter what color is used.

View File

@@ -84,3 +84,24 @@ IconRight.args = {
),
color: "primary",
};
export const IconOnly = Template.bind({});
IconOnly.args = {
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",
};

View File

@@ -14,9 +14,12 @@ export const Button = ({
...props
}: Props) => {
const classes = ["c__button", "c__button--" + color];
if (icon) {
if (icon && children) {
classes.push("c__button--with-icon--" + iconPosition);
}
if (icon && !children) {
classes.push("c__button--icon-only");
}
return (
<button className={classes.join(" ")} {...props}>
{!!icon && iconPosition === "left" && icon}