Skip to content

Commit

Permalink
fix(StepVerticalProgress): set correct required props
Browse files Browse the repository at this point in the history
  • Loading branch information
filiptammergard committed Apr 5, 2023
1 parent 8449616 commit fb407fb
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 30 deletions.
5 changes: 5 additions & 0 deletions .changeset/short-tigers-whisper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@einride/ui": patch
---

StepVerticalProgress: set correct required props.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ export const Basic = {
"aria-label": "Electrification potential",
completedSteps: 2,
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement)
const gauge = canvas.getByRole("progressbar", { name: Basic.args["aria-label"] })
await expect(gauge).toHaveAttribute("aria-valuemin", "0")
await expect(gauge).toHaveAttribute("aria-valuemax", DEFAULT_STEPS.toString())
await expect(gauge).toHaveAttribute("aria-valuenow", Basic.args.completedSteps.toString())
},
} satisfies Story

/** The amount of steps can be customized with the `steps` prop. */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import {
Meta,
Primary,
Description,
Source,
Title,
ArgTypes,
Subtitle,
Controls,
Story,
Canvas,
Stories,
Markdown,
} from "@storybook/blocks"
import * as StepVerticalProgress from "./StepVerticalProgress.stories.tsx"

<Meta of={StepVerticalProgress} />

<Title />

<Description of={StepVerticalProgress} />

```tsx
import { StepVerticalProgress } from "@einride/ui"
```

## Basic

<Description of={StepVerticalProgress.Basic} />

<Canvas of={StepVerticalProgress.Basic} />

<Controls of={StepVerticalProgress.Basic} />

## Custom steps

<Description of={StepVerticalProgress.CustomSteps} />

<Canvas of={StepVerticalProgress.CustomSteps} />

<Controls of={StepVerticalProgress.CustomSteps} include={["completedSteps", "steps"]} />

## Custom color

<Description of={StepVerticalProgress.CustomColor} />

<Canvas of={StepVerticalProgress.CustomColor} />

<Controls of={StepVerticalProgress.CustomColor} include="color" />

## Accessibility

Adding a descriptive `aria-label` is required to convey what the gauge is displaynig.
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { expect } from "@storybook/jest"
import { Meta, StoryObj } from "@storybook/react"
import { within } from "@storybook/testing-library"
import { SnapshotWrapper } from "../../../lib/storybook/SnapshotWrapper"
import { StepVerticalProgress } from "./StepVerticalProgress"
import { DEFAULT_STEPS, StepVerticalProgress } from "./StepVerticalProgress"

const meta = {
component: StepVerticalProgress,
Expand All @@ -9,17 +11,55 @@ const meta = {
export default meta
type Story = StoryObj<typeof meta>

export const Default = {
export const Basic = {
args: {
"aria-label": "Deliveries completed",
completedSteps: 2,
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement)
const gauge = canvas.getByRole("progressbar", { name: Basic.args["aria-label"] })
await expect(gauge).toHaveAttribute("aria-valuemin", "0")
await expect(gauge).toHaveAttribute("aria-valuemax", DEFAULT_STEPS.toString())
await expect(gauge).toHaveAttribute("aria-valuenow", Basic.args.completedSteps.toString())
},
} satisfies Story

/** The amount of steps can be customized with the `steps` prop. */
export const CustomSteps = {
args: {
...Basic.args,
steps: 10,
completedSteps: 4,
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement)
const gauge = canvas.getByRole("progressbar", { name: CustomSteps.args["aria-label"] })
await expect(gauge).toHaveAttribute("aria-valuemin", "0")
await expect(gauge).toHaveAttribute("aria-valuemax", CustomSteps.args.steps.toString())
await expect(gauge).toHaveAttribute("aria-valuenow", CustomSteps.args.completedSteps.toString())
},
} satisfies Story

/** Change the color of the progress bar with the `color` prop. */
export const CustomColor = {
args: {
...Basic.args,
color: "negative",
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement)
const gauge = canvas.getByRole("progressbar", { name: CustomColor.args["aria-label"] })
await expect(gauge).toHaveAttribute("aria-valuemin", "0")
await expect(gauge).toHaveAttribute("aria-valuemax", DEFAULT_STEPS.toString())
await expect(gauge).toHaveAttribute("aria-valuenow", CustomColor.args.completedSteps.toString())
},
} satisfies Story

export const Snapshot = {
render: () => (
<SnapshotWrapper>
{[Default].map((Story, index) => (
{[Basic, CustomSteps, CustomColor].map((Story, index) => (
// eslint-disable-next-line react/no-array-index-key
<StepVerticalProgress key={index} {...Story.args} />
))}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import styled from "@emotion/styled"
import { forwardRef, HTMLAttributes } from "react"
import { ContentColor } from "../../../lib/theme/types"
import { ComponentPropsWithoutRef, forwardRef } from "react"
import { getColor } from "../../../lib/theme/prop-system"
import { Color } from "../../../lib/theme/props"
import { Box } from "../../layout/Box/Box"

export interface StepVerticalProgressProps extends Omit<ComponentPropsWithoutRef<"div">, "color"> {
/** Accessible name. Describes what information the progress is conveying. */
"aria-label": string

interface StepVerticalProgressBaseProps extends HTMLAttributes<HTMLDivElement> {
/** Color of the completed steps. Default is `positive`. */
color?: ContentColor
color?: Color

/** Number of completed steps. */
completedSteps: number
Expand All @@ -13,23 +18,15 @@ interface StepVerticalProgressBaseProps extends HTMLAttributes<HTMLDivElement> {
steps?: number | undefined
}

export type StepVerticalProgressProps = (
| {
/** Accessible name. */
"aria-label": string
}
| {
/** Accessible name. */
"aria-labelledby": string
}
) &
StepVerticalProgressBaseProps

/** Either `aria-label` or `aria-labelledby` is required for accessibility. */
export const StepVerticalProgress = forwardRef<HTMLDivElement, StepVerticalProgressProps>(
({ color = "positive", completedSteps, steps = 5, ...props }, ref) => {
({ color = "positive", completedSteps, steps = DEFAULT_STEPS, ...props }, ref) => {
return (
<Wrapper
<Box
display="flex"
flexDirection="column-reverse"
gap="xs"
inlineSize="sm"
role="progressbar"
aria-valuemax={steps}
aria-valuemin={0}
Expand All @@ -42,26 +39,21 @@ export const StepVerticalProgress = forwardRef<HTMLDivElement, StepVerticalProgr
// eslint-disable-next-line react/no-array-index-key
<Step key={index} completed={index < completedSteps} textColor={color} />
))}
</Wrapper>
</Box>
)
},
)

const Wrapper = styled.div`
display: flex;
flex-direction: column-reverse;
gap: ${({ theme }) => theme.spacingBase}rem;
inline-size: ${({ theme }) => 2 * theme.spacingBase}rem;
`
export const DEFAULT_STEPS = 5

interface StepProps {
completed: boolean
textColor: ContentColor
textColor: Color
}

const Step = styled.div<StepProps>`
background: ${({ completed, textColor, theme }) =>
completed ? theme.colors.content[textColor] : theme.colors.background.tertiary};
completed ? getColor(textColor, theme) : theme.colors.background.tertiary};
block-size: ${({ theme }) => 0.8 * theme.spacingBase}rem;
border-radius: ${({ theme }) => theme.borderRadii.sm};
transition-property: background;
Expand Down

0 comments on commit fb407fb

Please sign in to comment.