Skip to content

Commit

Permalink
wip: Link exploration
Browse files Browse the repository at this point in the history
  • Loading branch information
mcwinter07 committed Sep 2, 2024
1 parent 20d2498 commit 8b2caf3
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,35 @@ If it needs to navigate somewhere and can be opened in a new tab, use a link ins
<Canvas of={ButtonStories.Playground} />
<Controls of={ButtonStories.Playground} />

bloop

<Controls of={ButtonStories.Playground} includes={[
"label",
"id",
"href",
"newTabAndIUnderstandTheAccessibilityImplications",
"className",
"disabled",
"iconButton",
"onClick",
"onMouseDown",
"onFocus",
"onBlur",
"aria-label",
"tabIndex",
"badge",
"working",
"workingLabelHidden",
"workingLabel",
"directionalLink",
"paginationLink",
"isActive",
"isPaginationLinkActive",
"classNameOverride"

]} />


## API

### Variants
Expand Down
Empty file.
162 changes: 162 additions & 0 deletions packages/components/src/__actions__/Link/v3/LinkButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import React from "react"
import { Link as RACLink } from "react-aria-components"
import { LoadingSpinner } from "~components/Loading"
import { useReversedColors } from "~components/__utilities__/v3"
import { mergeClassNames } from "~components/utils/mergeClassNames"
import styles from "./Button.module.scss"

export type ButtonVariants = "primary" | "secondary" | "tertiary"
export type ButtonSizes = "small" | "medium" | "large"

// type ButtonPendingProps = {
// isPending?: false
// /** Rendered as the child while `pendingLabel` is `true` */
// pendingLabel?: string
// /** Hides the `pendingLabel` and renders only the loading spinner if `isPending` is `true`. This will still be used as the accessible label.
// * @default false
// */
// isPendingLabelVisible?: boolean
// }

// type ButtonContentProps = {
// /** The visual label of Button. */
// label?: string
// icon?: JSX.Element
// /** `iconPosition` will only control icons passed in as a prop
// * @default "start"
// */
// iconPosition?: "start" | "end"
// /** The visual size of the button. `medium` was formerly `regular`
// * @default "primary"
// */
// children?: never
// } & ButtonPendingProps

// type ButtonContentWithChildrenProps = {
// children: RACButtonProps["children"]
// label?: never
// icon?: never
// iconPosition?: never
// } & ButtonPendingProps

export type ButtonBaseProps = {
/** The visual label of Button. */
label?: string
icon?: JSX.Element
/** `iconPosition` will only control icons passed in as a prop
* @default "start"
*/
iconPosition?: "start" | "end"
/** The visual size of the button. `medium` was formerly `regular`
* @default "primary"
*/
variant?: ButtonVariants
/** The visual size of the button. `medium` was formerly `regular`
* @default "medium"
*/
size?: ButtonSizes
/** Determines if the button should fill the width of its container
* @default false
*/
isFullWidth?: boolean
/** Triggers a pending state and stops additional press events while waiting for a server response
* @default false
*/
isPending?: false
/** Rendered as the child while `pendingLabel` is `true` */
pendingLabel?: string
/** Hides the `pendingLabel` and renders only the loading spinner if `isPending` is `true`. This will still be used as the accessible label.
* @default false
*/
isPendingLabelVisible?: boolean
} & Omit<RACButtonProps, "children">

export type ButtonWithoutChildren = ButtonBaseProps & {
label: string
children?: never
}

export type ButtonWithChildren = ButtonBaseProps & {
label?: never
children: RACButtonProps["children"]
}

export type ButtonProps = ButtonWithoutChildren | ButtonWithChildren

export type PendingButtonProps = Omit<
ButtonProps,
"isPending" | "pendingLabel"
> & {
/** Triggers a pending state and stops additional press events while waiting for a server response */
isPending: true
/** Rendered as the child of the button during pending state */
pendingLabel: string
/** Hides the `pendingLabel` and renders only the loading spinner if `isPending` is `true`. This will still be used as the accessible label.
* @default false
*/
isPendingLabelVisible?: boolean
}

// TODO: the content width based on the total size of the button content
const PendingContent = ({

Check failure on line 101 in packages/components/src/__actions__/Link/v3/LinkButton.tsx

View workflow job for this annotation

GitHub Actions / eslint

'PendingContent' is assigned a value but never used. Allowed unused vars must match /^_/u
pendingLabel,
isPendingLabelVisible,
}: PendingButtonProps): JSX.Element => {
if (isPendingLabelVisible) {
return (
<>
{pendingLabel}
<LoadingSpinner size="md" accessibilityLabel="" />
</>
)
}

return (
<>
{/* TODO: the loading spinner will need to take size */}
<LoadingSpinner size="md" accessibilityLabel={pendingLabel} />
</>
)
}

const ButtonContent = (props: ButtonProps): JSX.Element => {
const hasChildren = "children" in props

return hasChildren ? (
<>{props.children}</>
) : (
<>
{props.iconPosition !== "end" && props.icon}
{props.label}
{props.iconPosition === "end" && props.icon}
</>
)
}

export const Button = ({
variant = "primary",
className,
size = "medium",
isFullWidth,
// isPending,
...otherProps
}: ButtonProps): JSX.Element => {
const isReversed = useReversedColors()

return (
<RACLink
aria-live={"pendingLabel" in otherProps ? "polite" : undefined}
className={mergeClassNames(
styles.button,
styles[variant],
styles[size],
isFullWidth && styles.fullWidth,
isReversed && styles.reversed,
className
)}
{...otherProps}
>
<ButtonContent {...otherProps} />
</RACLink>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from "react"
import { action } from "@storybook/addon-actions"
import { Meta, StoryObj } from "@storybook/react"
import { validate } from "uuid"

Check failure on line 4 in packages/components/src/__actions__/Link/v3/_docs/LinkButton.stories.tsx

View workflow job for this annotation

GitHub Actions / eslint

'validate' is defined but never used. Allowed unused vars must match /^_/u
import { AddIcon, TrashIcon, ChevronUpIcon } from "~components/Icon"

Check failure on line 5 in packages/components/src/__actions__/Link/v3/_docs/LinkButton.stories.tsx

View workflow job for this annotation

GitHub Actions / eslint

'AddIcon' is defined but never used. Allowed unused vars must match /^_/u

Check failure on line 5 in packages/components/src/__actions__/Link/v3/_docs/LinkButton.stories.tsx

View workflow job for this annotation

GitHub Actions / eslint

'TrashIcon' is defined but never used. Allowed unused vars must match /^_/u
import { VisuallyHidden } from "~components/VisuallyHidden"
import { LinkButton } from "../index"

const meta = {
title: "Actions/Button/Button (v3)",
component: LinkButton,
args: {
label: "Label",
onPress: action("Button onPress event"),
},
} satisfies Meta<typeof LinkButton>

export default meta

type Story = StoryObj<typeof meta>

export const Playground: Story = {
render: args => <LinkButton {...args}></LinkButton>,
}
1 change: 1 addition & 0 deletions packages/components/src/__actions__/Link/v3/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./LinkButton"

0 comments on commit 8b2caf3

Please sign in to comment.