Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ const SelectableColorList: React.FC<ColorListProps> = props => {

export const Default: Story = {
args: {
customColorProps: { enabled: true }
getColorLabel: color => `Color ${color}`,
customColorProps: { enabled: true, 'aria-label': 'Custom color' }
},
render: args => (
<Box
Expand Down
64 changes: 64 additions & 0 deletions packages/twake-mui/src/components/ColorList/ColorList.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// @vitest-environment jsdom
import { ThemeProvider } from '@mui/material'
import { cleanup, fireEvent, render, screen } from '@testing-library/react'
import React from 'react'
import { afterEach, describe, expect, it, vi } from 'vitest'

import ColorList, { ColorListProps } from './index'
import { theme } from '../../lib/theme'

afterEach(cleanup)

const setup = (props: ColorListProps): void => {
render(
<ThemeProvider theme={theme}>
<ColorList {...props} />
</ThemeProvider>
)
}

describe('ColorList', () => {
it('lets a keyboard reach and pick a color', () => {
const onClick = vi.fn()
setup({ onClick })

const color = screen.getByRole('button', { name: '#273891' })
expect(color.tabIndex).toBe(0)
fireEvent.keyDown(color, { key: 'Enter' })
expect(onClick).toHaveBeenCalledWith('#273891')
})

it('names its colors and tells the selected one, whatever its case', () => {
setup({
selectedColor: '#7e57e3',
getColorLabel: color => (color === '#7E57E3' ? 'Purple' : color)
})

expect(
screen
.getByRole('button', { name: 'Purple' })
.getAttribute('aria-pressed')
).toBe('true')
expect(
screen
.getByRole('button', { name: '#273891' })
.getAttribute('aria-pressed')
).toBe('false')
})

it('passes its props to the custom color button', () => {
const onClick = vi.fn()
setup({
customColorProps: {
enabled: true,
onClick,
'aria-label': 'Custom color',
'data-testid': 'custom'
}
})

fireEvent.click(screen.getByRole('button', { name: 'Custom color' }))
expect(onClick).toHaveBeenCalledTimes(1)
expect(screen.queryByTestId('custom')).not.toBe(null)
})
})
14 changes: 12 additions & 2 deletions packages/twake-mui/src/components/ColorList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,28 @@ export interface ColorListProps extends Omit<
/** Defaults to `medium` on mobile and `small` otherwise */
size?: ColorListSize
selectedColor?: string
/** Accessible name of a color. Defaults to its hexadecimal code */
getColorLabel?: (color: string) => string
customColorProps?: {
enabled?: boolean
onClick?: React.MouseEventHandler<HTMLButtonElement>
'aria-label'?: string
'aria-pressed'?: boolean
'data-testid'?: string
}
onClick?: (color: string) => void
}

const ColorList: React.FC<ColorListProps> = ({
size,
selectedColor,
getColorLabel,
customColorProps,
onClick,
...props
}) => {
const { enabled: isCustomEnabled, ...customButtonProps } =
customColorProps ?? {}
const { isMobile } = useBreakpoints()
const { avatar, icon, cols, gap } =
sizes[size ?? (isMobile ? 'medium' : 'small')]
Expand All @@ -58,6 +66,8 @@ const ColorList: React.FC<ColorListProps> = ({
<ButtonBase
component="div"
className="u-bdrs-circle"
aria-label={getColorLabel?.(color) ?? color}
aria-pressed={selectedColor?.toUpperCase() === color}
onClick={() => onClick?.(color)}
>
<Avatar color={color} size={avatar}>
Expand All @@ -70,9 +80,10 @@ const ColorList: React.FC<ColorListProps> = ({
</ButtonBase>
</ImageListItem>
))}
{customColorProps?.enabled && (
{isCustomEnabled && (
<ImageListItem>
<ButtonBase
{...customButtonProps}
sx={{
width: avatar,
height: avatar,
Expand All @@ -83,7 +94,6 @@ const ColorList: React.FC<ColorListProps> = ({
backgroundOrigin: 'border-box',
backgroundClip: 'padding-box, border-box'
}}
onClick={customColorProps.onClick}
>
<Icon icon={Palette} size={icon} color="#000" />
</ButtonBase>
Expand Down
Loading