From 1f9edc2f1e06f8db921889ce61dad8bddb577849 Mon Sep 17 00:00:00 2001 From: Michael Winter <36558508+mcwinter07@users.noreply.github.com> Date: Thu, 19 Dec 2024 15:06:28 +1100 Subject: [PATCH] Create LinkButton component (#5298) * create LinkButton component and stories and update button exports * update button references to LinkButton * add missing isDisabled props to LinkButton * add stickersheets for LinkButton * add docs section and story on links that open in a new tab * update docs content on native nav, children, press events and tabs * update style import from button to resolve build compile issue * update next.js config guidance for client side routing * update LinkButton external links and add usage guidelines * update overview on spec and guidance page * update stickersheet to new grid structure * update shared Button and LinkButton type name * update docs imports and minor errors * fix lint issues and update stories * update docs position and reversed storydocs * move LinkButton to rc component folder and update import paths * add LinkButton to v3 actions exports * move LinkButton to root components folder and update import paths --- .changeset/hip-queens-divide.md | 7 + .../src/LinkButton/LinkButton.module.css | 4 + .../components/src/LinkButton/LinkButton.tsx | 71 +++++ .../_docs/LinkButton--api-specification.mdx | 281 ++++++++++++++++++ .../_docs/LinkButton--usage-guidelines.mdx | 29 ++ .../_docs/LinkButton.doc.stories.tsx | 136 +++++++++ .../_docs/LinkButton.spec.stories.tsx | 80 +++++ .../_docs/LinkButton.stickersheet.stories.tsx | 130 ++++++++ packages/components/src/LinkButton/index.ts | 1 + .../components/src/__rc__/Button/Button.tsx | 12 +- .../_docs/Button--api-specification.mdx | 10 +- .../Button/_docs/Button--usage-guidelines.mdx | 7 +- packages/components/src/index.ts | 3 +- 13 files changed, 755 insertions(+), 16 deletions(-) create mode 100644 .changeset/hip-queens-divide.md create mode 100644 packages/components/src/LinkButton/LinkButton.module.css create mode 100644 packages/components/src/LinkButton/LinkButton.tsx create mode 100644 packages/components/src/LinkButton/_docs/LinkButton--api-specification.mdx create mode 100644 packages/components/src/LinkButton/_docs/LinkButton--usage-guidelines.mdx create mode 100644 packages/components/src/LinkButton/_docs/LinkButton.doc.stories.tsx create mode 100644 packages/components/src/LinkButton/_docs/LinkButton.spec.stories.tsx create mode 100644 packages/components/src/LinkButton/_docs/LinkButton.stickersheet.stories.tsx create mode 100644 packages/components/src/LinkButton/index.ts diff --git a/.changeset/hip-queens-divide.md b/.changeset/hip-queens-divide.md new file mode 100644 index 00000000000..8852b3688fe --- /dev/null +++ b/.changeset/hip-queens-divide.md @@ -0,0 +1,7 @@ +--- +'@kaizen/components': minor +--- + +Add LinkButton component + +- Adds LinkButton component, stories and documentation to actions group diff --git a/packages/components/src/LinkButton/LinkButton.module.css b/packages/components/src/LinkButton/LinkButton.module.css new file mode 100644 index 00000000000..3fbad5c386a --- /dev/null +++ b/packages/components/src/LinkButton/LinkButton.module.css @@ -0,0 +1,4 @@ +.linkButton { + /* Reset */ + text-decoration: inherit; +} diff --git a/packages/components/src/LinkButton/LinkButton.tsx b/packages/components/src/LinkButton/LinkButton.tsx new file mode 100644 index 00000000000..25e2af42317 --- /dev/null +++ b/packages/components/src/LinkButton/LinkButton.tsx @@ -0,0 +1,71 @@ +import React, { forwardRef } from 'react' +import { Link as RACLink, type LinkProps as RACLinkProps } from 'react-aria-components' +import { type ButtonUIProps } from '~components/__rc__/Button' +import buttonStyles from '~components/__rc__/Button/Button.module.css' +import { ButtonContent } from '~components/__rc__/Button/subcomponents' +import { useReversedColors } from '~components/__utilities__/v3' +import { mergeClassNames } from '~components/utils/mergeClassNames' +import styles from './LinkButton.module.css' + +export type LinkButtonProps = ButtonUIProps & + Omit & { + /** Used as the label for the LinkButton. */ + children: RACLinkProps['children'] + } + +export const LinkButton = forwardRef( + ( + { + children, + variant = 'primary', + size = 'medium', + icon, + iconPosition = 'start', + hasHiddenLabel = false, + isFullWidth = false, + isDisabled, + className, + isReversed, + ...otherProps + }: LinkButtonProps, + ref: React.ForwardedRef, + ) => { + const shouldUseReverse = useReversedColors() + const isReversedVariant = isReversed ?? shouldUseReverse + + return ( + + {(racStateProps) => { + const childIsFunction = typeof children === 'function' + + return ( + + {childIsFunction ? children(racStateProps) : children} + + ) + }} + + ) + }, +) + +LinkButton.displayName = 'LinkButton' diff --git a/packages/components/src/LinkButton/_docs/LinkButton--api-specification.mdx b/packages/components/src/LinkButton/_docs/LinkButton--api-specification.mdx new file mode 100644 index 00000000000..caa54c5e586 --- /dev/null +++ b/packages/components/src/LinkButton/_docs/LinkButton--api-specification.mdx @@ -0,0 +1,281 @@ +import { Canvas, Meta, Controls, ArgTypes, DocsStory } from '@storybook/blocks' +import { ResourceLinks, KAIOInstallation, LinkTo } from '~storybook/components' +import * as exampleStories from './LinkButton.doc.stories' + + + +# LinkButton API Specification + +Updated Dec 18, 2024 + + + + + +## Overview + +`LinkButton` allows users to navigate to another page or resource. It shares the same visual styles and interaction states as the Button component, but is intended for navigational purposes and downloading documents. + +The following example and table showcases the essential props that enable the core functionality of `LinkButton`. For the remaining suite of API options refer to [this section](#additional-api-options). + + + + + +## API + +This is built on top of [React Aria's Link component](https://react-spectrum.adobe.com/react-aria/Link.html) and is the counterpart to the Kaizen Button, handling icons, variants and sizes in the same way. It provides a semantic wrapper for navigational buttons and allows for native `href` navigation and client side routing with [additional configuration](#client-side-routing). + +### Navigation and native anchor attributes + +Out of the box, the `LinkButton` offers majority of the native behavior and functionality on the `anchor` tag. `href` will trigger new page loads, `download` will download the referenced document, and `target` can be used to open links in new tabs or windows. + + + +While client side routing is possible, the `LinkButton` is agnostic to the routing technology chosen. Refer to our general set up guide to get started with [client side routing](#client-side-routing). + +#### Opening new tabs and accessibility considerations + +The general recommendation is to limit the number of links that open a new tab or window on a single page. While there are valid scenarios that can help avoid loss of data and or progress, as with links in forms, opening new tabs can be disorienting for users - especially for those who have difficulty perceiving visual content. + +In order to provide advance warning to all users, it is recommended that links using `target="_blank"` be accompanied by a visual indicator and audible warning. As shown in the following example, additional context can be provided via a visually hidden element within the `children` of the component. + + + +For more context on this recommendation, we recommend taking a look at the [W3C page on the G200 success criteria](https://www.w3.org/TR/WCAG20-TECHS/G200.html). + +### Variants + +`LinkButton` supports the following variants: `primary`, `secondary` and `tertiary`. If the `variant` prop is not specified, the default will be `primary`. + + + +Reversed variants are handled via the `ReversedColors` Provider. + + + +To enable the reversed theme, you will need to wrap the component or application in the `ReversedColors` provider, ie: + +```tsx +import { RouterProvider } from 'react-aria-components' +import { Button } from '@kaizen/components/v3/actions' +import { ReversedColors } from '@kaizen/components/v3/utilities' +// application code + +return ( + + + +) +``` + +### Sizes + +LinkButton supports the following sizes: `small`, `medium` and `large`. If the `size` prop is not specified, the default will be `medium`. + + + +### `onPress` + +As with Button, `LinkButton`'s API uses React Aria's `onPress` instead of `onClick`. Functionally this does not change the way we pass click events to a `LinkButton`. Consumers can safely replace `onClick` with `onPress` without any additional changes, ie: + +```tsx +