aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/atoms/buttons/button/button.tsx
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2023-09-26 18:43:11 +0200
committerArmand Philippot <git@armandphilippot.com>2023-10-24 12:25:00 +0200
commit388e687857345c85ee550cd5da472675e05a6ff5 (patch)
tree0f035a3cad57a75959c028949a57227a83d480e2 /src/components/atoms/buttons/button/button.tsx
parent70efcfeaa0603415dd992cb662d8efb960e6e49a (diff)
refactor(components): rewrite Button and ButtonLink components
Both: * move styles to Sass placeholders Button: * add `isPressed` prop to Button * add `isLoading` prop to Button (to differentiate state from disabled) ButtonLink: * replace `external` prop with `isExternal` prop * replace `href` prop with `to` prop
Diffstat (limited to 'src/components/atoms/buttons/button/button.tsx')
-rw-r--r--src/components/atoms/buttons/button/button.tsx98
1 files changed, 98 insertions, 0 deletions
diff --git a/src/components/atoms/buttons/button/button.tsx b/src/components/atoms/buttons/button/button.tsx
new file mode 100644
index 0000000..8489b31
--- /dev/null
+++ b/src/components/atoms/buttons/button/button.tsx
@@ -0,0 +1,98 @@
+import {
+ type ButtonHTMLAttributes,
+ forwardRef,
+ type ForwardRefRenderFunction,
+ type ReactNode,
+} from 'react';
+import styles from './button.module.scss';
+
+export type ButtonProps = Omit<
+ ButtonHTMLAttributes<HTMLButtonElement>,
+ 'aria-busy' | 'aria-disabled' | 'aria-pressed' | 'aria-selected' | 'disabled'
+> & {
+ /**
+ * The button body.
+ */
+ children: ReactNode;
+ /**
+ * Should the button be disabled?
+ *
+ * @default undefined
+ */
+ isDisabled?: boolean;
+ /**
+ * Is the button already executing some action?
+ *
+ * @default undefined
+ */
+ isLoading?: boolean;
+ /**
+ * Is the button a toggle and is it currently pressed?
+ *
+ * @default undefined
+ */
+ isPressed?: boolean;
+ /**
+ * Button kind.
+ *
+ * @default 'secondary'
+ */
+ kind?: 'primary' | 'secondary' | 'tertiary' | 'neutral';
+ /**
+ * Button shape.
+ *
+ * @default 'rectangle'
+ */
+ shape?: 'circle' | 'rectangle' | 'square' | 'initial';
+ /**
+ * Button type attribute.
+ *
+ * @default 'button'
+ */
+ type?: 'button' | 'reset' | 'submit';
+};
+
+const ButtonWithRef: ForwardRefRenderFunction<
+ HTMLButtonElement,
+ ButtonProps
+> = (
+ {
+ className = '',
+ children,
+ isPressed,
+ isDisabled,
+ isLoading,
+ kind = 'secondary',
+ shape = 'rectangle',
+ type = 'button',
+ ...props
+ },
+ ref
+) => {
+ const kindClass = styles[`btn--${kind}`];
+ const shapeClass = styles[`btn--${shape}`];
+ const btnClass = `${styles.btn} ${kindClass} ${shapeClass} ${className}`;
+
+ return (
+ <button
+ {...props}
+ aria-busy={isLoading}
+ aria-disabled={isDisabled}
+ aria-pressed={isPressed}
+ className={btnClass}
+ disabled={isDisabled ?? isLoading}
+ ref={ref}
+ // eslint-disable-next-line react/button-has-type -- Default value is set.
+ type={type}
+ >
+ {children}
+ </button>
+ );
+};
+
+/**
+ * Button component
+ *
+ * Use a button as call to action.
+ */
+export const Button = forwardRef(ButtonWithRef);