From 01528b9377588b154874ad0aa8d621e51fe25702 Mon Sep 17 00:00:00 2001 From: Nathan Vasse Date: Wed, 18 Oct 2023 17:38:48 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8(react)=20render=20Button=20as=20link?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For a variety of reasons, such as accessibility or integration with external react-router deps style we needed to be able to provide the ability to render the Button component as link in order to be able to provide link-specific attribute for rendering such as href. --- .changeset/breezy-llamas-fail.md | 5 +++ .../react/src/components/Button/index.scss | 4 +- .../src/components/Button/index.spec.tsx | 15 +++++++ .../src/components/Button/index.stories.tsx | 11 +++++ .../react/src/components/Button/index.tsx | 43 +++++++++++++------ .../Forms/DatePicker/CalendarCell.tsx | 4 +- 6 files changed, 65 insertions(+), 17 deletions(-) create mode 100644 .changeset/breezy-llamas-fail.md diff --git a/.changeset/breezy-llamas-fail.md b/.changeset/breezy-llamas-fail.md new file mode 100644 index 0000000..193bb30 --- /dev/null +++ b/.changeset/breezy-llamas-fail.md @@ -0,0 +1,5 @@ +--- +"@openfun/cunningham-react": minor +--- + +render Button as link diff --git a/packages/react/src/components/Button/index.scss b/packages/react/src/components/Button/index.scss index 5feea48..accfbcc 100644 --- a/packages/react/src/components/Button/index.scss +++ b/packages/react/src/components/Button/index.scss @@ -4,7 +4,9 @@ border: thin solid transparent; box-sizing: border-box; cursor: pointer; - display: flex; + display: inline-flex; + // When button is rendered as link. + text-decoration: none; font-weight: var(--c--components--button--font-weight); font-family: var(--c--components--button--font-family); transition: all var(--c--theme--transitions--duration) var(--c--theme--transitions--ease-out); diff --git a/packages/react/src/components/Button/index.spec.tsx b/packages/react/src/components/Button/index.spec.tsx index 91f4981..1891254 100644 --- a/packages/react/src/components/Button/index.spec.tsx +++ b/packages/react/src/components/Button/index.spec.tsx @@ -65,6 +65,21 @@ describe(", + ); + const button = screen.getByRole("link", { name: "Open link" }); + expect(button).toHaveAttribute("target", "_blank"); + expect(button).toHaveAttribute("rel", "noopener noreferrer"); + }); + it("uses custom token", async () => { await buildTheme(); const tokens = await loadTokens(); diff --git a/packages/react/src/components/Button/index.stories.tsx b/packages/react/src/components/Button/index.stories.tsx index 235b1c4..81c5c1a 100644 --- a/packages/react/src/components/Button/index.stories.tsx +++ b/packages/react/src/components/Button/index.stories.tsx @@ -103,3 +103,14 @@ export const IconOnly: Story = { color: "primary", }, }; + +export const AsLink: Story = { + args: { + children: "Go to fun-mooc.fr", + icon: link, + color: "primary", + href: "https://www.fun-mooc.fr/", + target: "_blank", + rel: "noopener noreferrer", + }, +}; diff --git a/packages/react/src/components/Button/index.tsx b/packages/react/src/components/Button/index.tsx index 7ecf8dd..545c3fc 100644 --- a/packages/react/src/components/Button/index.tsx +++ b/packages/react/src/components/Button/index.tsx @@ -1,15 +1,24 @@ -import React, { ButtonHTMLAttributes, forwardRef, ReactNode } from "react"; +import React, { + AnchorHTMLAttributes, + ButtonHTMLAttributes, + createElement, + forwardRef, + ReactNode, +} from "react"; -export interface ButtonProps extends ButtonHTMLAttributes { - color?: "primary" | "secondary" | "tertiary" | "danger"; - size?: "medium" | "small" | "nano"; - icon?: ReactNode; - iconPosition?: "left" | "right"; - active?: boolean; - fullWidth?: boolean; -} +export type ButtonProps = ButtonHTMLAttributes & + AnchorHTMLAttributes & { + color?: "primary" | "secondary" | "tertiary" | "danger"; + size?: "medium" | "small" | "nano"; + icon?: ReactNode; + iconPosition?: "left" | "right"; + active?: boolean; + fullWidth?: boolean; + }; -export const Button = forwardRef( +export type ButtonElement = HTMLButtonElement & HTMLAnchorElement; + +export const Button = forwardRef( ( { children, @@ -43,13 +52,19 @@ export const Button = forwardRef( classes.push("c__button--full-width"); } const iconElement = {icon}; - // const iconElement = icon; - return ( - + , ); }, ); diff --git a/packages/react/src/components/Forms/DatePicker/CalendarCell.tsx b/packages/react/src/components/Forms/DatePicker/CalendarCell.tsx index fa3cc7c..a935317 100644 --- a/packages/react/src/components/Forms/DatePicker/CalendarCell.tsx +++ b/packages/react/src/components/Forms/DatePicker/CalendarCell.tsx @@ -8,7 +8,7 @@ import { isToday, } from "@internationalized/date"; import { CalendarState, RangeCalendarState } from "@react-stately/calendar"; -import { Button } from ":/components/Button"; +import { Button, ButtonElement } from ":/components/Button"; interface CalendarCellProps { state: CalendarState | RangeCalendarState; @@ -20,7 +20,7 @@ const isRangeCalendar = (object: any): object is RangeCalendarState => { }; export const CalendarCell = ({ state, date }: CalendarCellProps) => { - const ref = useRef(null); + const ref = useRef(null); const { cellProps, buttonProps,