From 58b2df0ac748d7f9bd949c3309867d4ffc66786b Mon Sep 17 00:00:00 2001 From: Arno V Date: Sun, 14 Apr 2024 13:29:07 -0400 Subject: [PATCH] fix: refactor Button and Anchor (#492) some breaking changes such as link renamed into href but since Anchor is in alpha mode, no bump in main version ## Summary by CodeRabbit - **New Features** - Updated anchor components across various files to use `href` attribute instead of `link`. - Introduced new properties like `target`, `className`, and `noTruncate` across different UI components for enhanced customization and functionality. - Added new story examples for `Anchor` and `Button` components in the documentation to showcase the usage of new properties. - **Bug Fixes** - Corrected the import paths and properties for `ButtonLink` and `Anchor` components to ensure proper functionality. - **Documentation** - Enhanced component stories in documentation with additional arguments and updated existing ones for better clarity and control. - **Refactor** - Removed unused properties like `onClick` and `type` from `Button` components to streamline component interfaces. - Adjusted utility functions to support new `noTruncate` property, improving button text handling. --- examples/with-vite/src/main.tsx | 8 +- examples/with-webpack/src/main.tsx | 8 +- .../src/Components/Anchor.stories.tsx | 71 ++++++++++----- .../src/Components/Button.stories.tsx | 89 +++++++++++++------ .../src/Components/Header.stories.tsx | 8 +- .../src/Styles/DarkMode.stories.tsx | 8 +- .../src/common/__tests__/utilities.test.tsx | 16 ---- .../ui-components/src/common/utilities.ts | 16 ---- .../src/components/Anchor/Anchor.tsx | 2 +- .../Anchor/__tests__/Anchor.test.tsx | 35 +++----- .../src/components/Button/Button.tsx | 8 +- .../src/components/Button/ButtonLink.tsx | 53 +++++++---- .../src/components/Button/ButtonTypes.d.ts | 26 +++--- .../Button/__tests__/ButtonLink.test.tsx | 43 +++------ .../src/components/Button/utilities.ts | 11 ++- .../ui-components/src/components/index.ts | 2 - 16 files changed, 205 insertions(+), 199 deletions(-) delete mode 100644 packages/ui-components/src/common/__tests__/utilities.test.tsx delete mode 100644 packages/ui-components/src/common/utilities.ts diff --git a/examples/with-vite/src/main.tsx b/examples/with-vite/src/main.tsx index 2cd62bcc..9ad9566d 100644 --- a/examples/with-vite/src/main.tsx +++ b/examples/with-vite/src/main.tsx @@ -92,14 +92,14 @@ module.exports = {
- Anchor as a button - + Anchor as a button + Anchor as a button lorem ipsum - + Anchor as a button lorem ipsum dolor - + Anchor as a button lorem ipsum dolor sit amet
diff --git a/examples/with-webpack/src/main.tsx b/examples/with-webpack/src/main.tsx index 864be663..9acfdc3d 100644 --- a/examples/with-webpack/src/main.tsx +++ b/examples/with-webpack/src/main.tsx @@ -92,14 +92,14 @@ module.exports = {
- Anchor as a button - + Anchor as a button + Anchor as a button lorem ipsum - + Anchor as a button lorem ipsum dolor - + Anchor as a button lorem ipsum dolor sit amet
diff --git a/packages/documentation/src/Components/Anchor.stories.tsx b/packages/documentation/src/Components/Anchor.stories.tsx index e41f5b88..e85f8739 100644 --- a/packages/documentation/src/Components/Anchor.stories.tsx +++ b/packages/documentation/src/Components/Anchor.stories.tsx @@ -6,10 +6,35 @@ export default { meta: { importName: "Anchor", }, + args: { + fullWidth: false, + mode: "system", + focusMode: "system", + raw: false, + href: "https://example.com", + noBorder: false, + size: "small", + noTruncate: false, + noNewWindowIcon: false, + }, + argTypes: { + mode: { + options: ["dark", "light", "system", "alt-system"], + control: { type: "radio" }, + }, + focusMode: { + options: ["dark", "light", "system", "alt-system"], + control: { type: "radio" }, + }, + size: { + options: ["small", "medium", "large"], + control: { type: "radio" }, + }, + }, }; export const Basic: Story = (args) => ( -
+
Anchor as a button Anchor as a button lorem ipsum Anchor as a button lorem ipsum dolor @@ -17,29 +42,27 @@ export const Basic: Story = (args) => (
); -Basic.args = { - fullWidth: false, - mode: "system", - focusMode: "system", - raw: false, - link: "https://www.google.com", - noBorder: false, - size: "small", - noTruncate: false, - spacing: { r: 2, b: 2 }, +export const NewWindow: Story = (args) => ( +
+ Anchor as a button + Anchor as a button lorem ipsum + Anchor as a button lorem ipsum dolor + Anchor as a button lorem ipsum dolor sit amet +
+); +NewWindow.args = { + target: "_blank", }; -Basic.argTypes = { - mode: { - options: ["dark", "light", "system", "alt-system"], - control: { type: "radio" }, - }, - focusMode: { - options: ["dark", "light", "system", "alt-system"], - control: { type: "radio" }, - }, - size: { - options: ["small", "medium", "large"], - control: { type: "radio" }, - }, +export const Truncate: Story = (args) => ( +
+ Anchor as a button + Anchor as a button lorem ipsum + Anchor as a button lorem ipsum dolor + Anchor as a button lorem ipsum dolor sit amet +
+); + +Truncate.args = { + className: "w-44 sm:w-52", }; diff --git a/packages/documentation/src/Components/Button.stories.tsx b/packages/documentation/src/Components/Button.stories.tsx index 2b1c5b37..062f1b52 100644 --- a/packages/documentation/src/Components/Button.stories.tsx +++ b/packages/documentation/src/Components/Button.stories.tsx @@ -6,15 +6,44 @@ export default { meta: { importName: "Button", }, + args: { + disabled: false, + fullWidth: false, + mode: "system", + focusMode: "system", + size: "medium", + raw: false, + noBorder: false, + variant: "primary", + noTruncate: false, + }, + argTypes: { + mode: { + options: ["dark", "light", "system", "alt-system"], + control: { type: "radio" }, + }, + focusMode: { + options: ["dark", "light", "system", "alt-system"], + control: { type: "radio" }, + }, + size: { + options: ["small", "medium", "large"], + control: { type: "radio" }, + }, + variant: { + options: ["primary", "secondary", "danger"], + control: { type: "radio" }, + }, + }, }; export const Basic: Story = (args) => { return ( <>
- - - + + +

@@ -35,31 +64,33 @@ export const Basic: Story = (args) => { ); }; -Basic.args = { - disabled: false, - fullWidth: false, - mode: "system", - focusMode: "system", - size: "medium", - raw: false, - noBorder: false, - variant: "primary", +export const Truncate: Story = (args) => { + return ( + <> +

+ + + +
+ +

+ The following row is having the variant prop hard-coded: +

+
+ + + +
+ + ); }; -Basic.argTypes = { - mode: { - options: ["dark", "light", "system", "alt-system"], - control: { type: "radio" }, - }, - focusMode: { - options: ["dark", "light", "system", "alt-system"], - control: { type: "radio" }, - }, - size: { - options: ["small", "medium", "large"], - control: { type: "radio" }, - }, - variant: { - options: ["primary", "secondary", "danger"], - control: { type: "radio" }, - }, + +Truncate.args = { + className: "w-44 sm:w-52", }; diff --git a/packages/documentation/src/Components/Header.stories.tsx b/packages/documentation/src/Components/Header.stories.tsx index e614b662..165329f6 100644 --- a/packages/documentation/src/Components/Header.stories.tsx +++ b/packages/documentation/src/Components/Header.stories.tsx @@ -131,14 +131,14 @@ const CommonTemplate = () => {
- Anchor as a button - + Anchor as a button + Anchor as a button lorem ipsum - + Anchor as a button lorem ipsum dolor - + Anchor as a button lorem ipsum dolor sit amet
diff --git a/packages/documentation/src/Styles/DarkMode.stories.tsx b/packages/documentation/src/Styles/DarkMode.stories.tsx index 95c7d54d..17145313 100644 --- a/packages/documentation/src/Styles/DarkMode.stories.tsx +++ b/packages/documentation/src/Styles/DarkMode.stories.tsx @@ -113,14 +113,14 @@ const CommonTemplate = () => {
- Anchor as a button - + Anchor as a button + Anchor as a button lorem ipsum - + Anchor as a button lorem ipsum dolor - + Anchor as a button lorem ipsum dolor sit amet
diff --git a/packages/ui-components/src/common/__tests__/utilities.test.tsx b/packages/ui-components/src/common/__tests__/utilities.test.tsx deleted file mode 100644 index f31a73c4..00000000 --- a/packages/ui-components/src/common/__tests__/utilities.test.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { describe, expect, it } from "vitest"; - -import { truncate } from "../utilities"; - -describe("Non-DOM tests", () => { - describe("truncate", () => { - it("should truncate according to plan", () => { - const STR = "hello world"; - expect(truncate(STR, 5).truncatedString).toBe("he..."); - expect(truncate(STR, 7).truncatedString).toBe("hell..."); - expect(truncate(STR, 10).truncatedString).toBe("hello w..."); - expect(truncate(STR, 11).truncatedString).toBe(STR); - expect(truncate(STR, 12).truncatedString).toBe(STR); - }); - }); -}); diff --git a/packages/ui-components/src/common/utilities.ts b/packages/ui-components/src/common/utilities.ts deleted file mode 100644 index eacb03ee..00000000 --- a/packages/ui-components/src/common/utilities.ts +++ /dev/null @@ -1,16 +0,0 @@ -export const isProd = process.env.NODE_ENV === "production"; -export const isDev = !isProd; - -export const truncate = (fullString: string, maxLength: number) => { - const ELLIPSIS = "..."; - const ELLIPSIS_LENGTH = ELLIPSIS.length; - const truncatedString = - maxLength > ELLIPSIS_LENGTH && fullString.length > maxLength - ? fullString.substring(0, maxLength - ELLIPSIS_LENGTH) + ELLIPSIS - : fullString; - - return { - truncatedString, - fullString, - }; -}; diff --git a/packages/ui-components/src/components/Anchor/Anchor.tsx b/packages/ui-components/src/components/Anchor/Anchor.tsx index 1d9199a7..d9617830 100644 --- a/packages/ui-components/src/components/Anchor/Anchor.tsx +++ b/packages/ui-components/src/components/Anchor/Anchor.tsx @@ -1,6 +1,6 @@ import React from "react"; -import { ButtonLink } from ".."; +import { ButtonLink } from "../Button/ButtonLink"; import type { AnchorProps } from "./AnchorTypes"; export const Anchor = React.forwardRef( diff --git a/packages/ui-components/src/components/Anchor/__tests__/Anchor.test.tsx b/packages/ui-components/src/components/Anchor/__tests__/Anchor.test.tsx index 98791d25..13cf6cdf 100644 --- a/packages/ui-components/src/components/Anchor/__tests__/Anchor.test.tsx +++ b/packages/ui-components/src/components/Anchor/__tests__/Anchor.test.tsx @@ -11,14 +11,14 @@ describe("Anchor (exceptions)", () => { describe("Anchor modifiers", () => { it("should render a default anchor", async () => { - render(hello); + render(hello); const button = await screen.findByRole("link"); expect(button.className).toContain("py-0"); }); it("should render a size small anchor", async () => { render( - + hello , ); @@ -28,7 +28,7 @@ describe("Anchor modifiers", () => { it("should render a size medium anchor", async () => { render( - + hello , ); @@ -38,7 +38,7 @@ describe("Anchor modifiers", () => { it("should render a size large anchor", async () => { render( - + hello , ); @@ -48,7 +48,7 @@ describe("Anchor modifiers", () => { it("should render a dark link", async () => { render( - + hello , ); @@ -60,7 +60,7 @@ describe("Anchor modifiers", () => { it("should render a light anchor", async () => { render( - + hello , ); @@ -72,7 +72,7 @@ describe("Anchor modifiers", () => { it("should render a fullWidth link", async () => { render( - + hello , ); @@ -82,19 +82,7 @@ describe("Anchor modifiers", () => { it("should render an anchor with truncated text", async () => { render( - - hello world - , - ); - const button = await screen.findByRole("link"); - expect(button.className).toContain("py-0"); - const label = await screen.findByText("hello..."); - expect(label).toBeDefined(); - }); - - it("should render an anchor with full text", async () => { - render( - + hello world , ); @@ -102,11 +90,12 @@ describe("Anchor modifiers", () => { expect(button.className).toContain("py-0"); const label = await screen.findByText("hello world"); expect(label).toBeDefined(); + expect(label.className).toContain("truncate"); }); it("should render an anchor element with a special rel value", async () => { render( - + Hello World , ); @@ -115,7 +104,7 @@ describe("Anchor modifiers", () => { }); it("should render an anchor with full text but with truncated class", async () => { - render(hello world); + render(hello world); const button = await screen.findByRole("link"); expect(button.className).toContain("py-0"); const label = await screen.findByText("hello world"); @@ -125,7 +114,7 @@ describe("Anchor modifiers", () => { it("should render an anchor with full text without a truncated class", async () => { render( - + hello world , ); diff --git a/packages/ui-components/src/components/Button/Button.tsx b/packages/ui-components/src/components/Button/Button.tsx index 891ec981..7270a7d6 100644 --- a/packages/ui-components/src/components/Button/Button.tsx +++ b/packages/ui-components/src/components/Button/Button.tsx @@ -7,19 +7,17 @@ export const Button = React.forwardRef( ( { children, - onClick, disabled = false, mode = "system", focusMode = "system", fullWidth = false, className, size = "medium", - type = "button", raw = false, noBorder = false, - "aria-label": ariaLabel, spacing, variant = "primary", + noTruncate = false, ...otherProps }, @@ -37,16 +35,14 @@ export const Button = React.forwardRef( noBorder, spacing, variant, + noTruncate, }); return (