(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-size: var(--c--components--button--font-size);
font-weight: var(--c--components--button--font-weight); 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 { &--with-icon--left, &--with-icon--right {
gap: var(--c--theme--spacings--t); gap: var(--c--theme--spacings--t);
} }

View File

@@ -9,14 +9,25 @@ describe("<Button/>", () => {
it("renders", () => { it("renders", () => {
render(<Button>Test button</Button>); render(<Button>Test button</Button>);
const button = screen.getByRole("button", { name: "Test 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", () => { it("renders with custom class when using left icon", () => {
render(<Button icon={<div>Icon</div>}>Test button</Button>); render(<Button icon={<div>Icon</div>}>Test button</Button>);
const button = screen.getByText("Test button"); const button = screen.getByText("Test button");
expect(button.classList.contains("c__button")).toBe(true); const classes = Array.from(button.classList);
expect(button.classList.contains("c__button--with-icon--left")).toBe(true); 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", () => { it("renders with custom class when using right icon", () => {
@@ -26,8 +37,9 @@ describe("<Button/>", () => {
</Button> </Button>
); );
const button = screen.getByText("Test button"); const button = screen.getByText("Test button");
expect(button.classList.contains("c__button")).toBe(true); const classes = Array.from(button.classList);
expect(button.classList.contains("c__button--with-icon--right")).toBe(true); expect(classes).toContain("c__button");
expect(classes).toContain("c__button--with-icon--right");
}); });
it("call onClick when click occurs", async () => { 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"/> <Story id="components-button--icon-right"/>
</Canvas> </Canvas>
You can also use button with only an icon.
<Canvas withSource="open">
<Story id="components-button--icon-only"/>
</Canvas>
## Disabled ## Disabled
The button can be disabled. The disabled button will render the same no matter what color is used. 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", 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
}: Props) => { }: Props) => {
const classes = ["c__button", "c__button--" + color]; const classes = ["c__button", "c__button--" + color];
if (icon) { if (icon && children) {
classes.push("c__button--with-icon--" + iconPosition); classes.push("c__button--with-icon--" + iconPosition);
} }
if (icon && !children) {
classes.push("c__button--icon-only");
}
return ( return (
<button className={classes.join(" ")} {...props}> <button className={classes.join(" ")} {...props}>
{!!icon && iconPosition === "left" && icon} {!!icon && iconPosition === "left" && icon}