Skip to content

Commit 4815ed8

Browse files
devongovettMichael Jordan
andauthored
Majornista issue 1281 hex color field a11y (#1495)
* fix(#1281): HexColorField accessibility updates * fix(#1281): Color: remove WCAG compliance utility method * fix(#1285): remove unused Color APIs * Remove popover example Co-authored-by: Michael Jordan <[email protected]>
1 parent d2e5afe commit 4815ed8

File tree

4 files changed

+27
-56
lines changed

4 files changed

+27
-56
lines changed

packages/@react-aria/color/src/useHexColorField.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export function useHexColorField(
3636
isReadOnly,
3737
isRequired
3838
} = props;
39-
39+
4040
let {
4141
colorValue,
4242
inputValue,
@@ -88,6 +88,11 @@ export function useHexColorField(
8888
return {
8989
labelProps,
9090
inputFieldProps: mergeProps(inputProps, spinButtonProps, {
91+
role: 'textbox',
92+
'aria-valuemax': null,
93+
'aria-valuemin': null,
94+
'aria-valuenow': null,
95+
'aria-valuetext': null,
9196
autoCorrect: 'off',
9297
onBlur: commitInputValue,
9398
onWheel

packages/@react-aria/color/test/useHexColorField.test.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ describe('useHexColorField', function () {
3636
expect(inputFieldProps.autoComplete).toBe('off');
3737
expect(inputFieldProps.autoCorrect).toBe('off');
3838
expect(inputFieldProps.id).toBeTruthy();
39-
expect(inputFieldProps.role).toBe('spinbutton');
39+
expect(inputFieldProps.role).toBe('textbox');
4040
expect(inputFieldProps['aria-valuenow']).toBeNull();
41-
expect(inputFieldProps['aria-valuetext']).toBe('Empty');
42-
expect(inputFieldProps['aria-valuemin']).toBe(0x000000);
43-
expect(inputFieldProps['aria-valuemax']).toBe(0xFFFFFF);
41+
expect(inputFieldProps['aria-valuetext']).toBeNull();
42+
expect(inputFieldProps['aria-valuemin']).toBeNull();
43+
expect(inputFieldProps['aria-valuemax']).toBeNull();
4444
expect(inputFieldProps['aria-required']).toBeNull();
4545
expect(inputFieldProps['aria-disabled']).toBeNull();
4646
expect(inputFieldProps['aria-readonly']).toBeNull();
@@ -51,9 +51,10 @@ describe('useHexColorField', function () {
5151

5252
it('should return props for colorValue provided', function () {
5353
let colorValue = parseColor('#ff88a0');
54-
let {inputFieldProps} = renderHexColorFieldHook({}, {colorValue});
55-
expect(inputFieldProps['aria-valuenow']).toBe(colorValue.toHexInt());
56-
expect(inputFieldProps['aria-valuetext']).toBe('#FF88A0');
54+
let {inputFieldProps} = renderHexColorFieldHook({}, {colorValue, inputValue: colorValue.toString('hex')});
55+
expect(inputFieldProps['aria-valuenow']).toBeNull();
56+
expect(inputFieldProps['aria-valuetext']).toBeNull();
57+
expect(inputFieldProps['value']).toBe('#FF88A0');
5758
});
5859

5960
it('should return props for label', function () {

packages/@react-spectrum/color/stories/HexColorField.stories.tsx

Lines changed: 11 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@
1111
*/
1212

1313
import {action} from '@storybook/addon-actions';
14-
import {ActionButton} from '@react-spectrum/button';
1514
import {Color} from '@react-types/color';
16-
import {Dialog, DialogTrigger} from '@react-spectrum/dialog';
1715
import {Flex} from '@react-spectrum/layout';
1816
import {HexColorField} from '../';
1917
import React, {useState} from 'react';
2018
import {storiesOf} from '@storybook/react';
19+
import {useId} from '@react-aria/utils';
2120
import {View} from '@react-spectrum/view';
21+
import {VisuallyHidden} from '@react-aria/visually-hidden';
2222

2323
storiesOf('HexColorField', module)
2424
.add(
@@ -64,50 +64,7 @@ storiesOf('HexColorField', module)
6464
value="#FF00AA"
6565
onChange={action('change')} />
6666
)
67-
)
68-
.add(
69-
'as a popover',
70-
() => (
71-
<HexColorFieldPopover
72-
label="Choose a color"
73-
value="#ff0000"
74-
step={255}
75-
onChange={action('change')} />
76-
)
77-
)
78-
.add(
79-
'as a popover, defaults only',
80-
() => <HexColorFieldPopover onChange={action('change')} />
81-
);
82-
83-
function HexColorFieldPopover(props: any = {}) {
84-
let [color, setColor] = useState(props.value || null);
85-
let colorString = color ? color.toString('hex') : '';
86-
return (
87-
<DialogTrigger type="popover">
88-
<ActionButton
89-
width="size-1600"
90-
height="size-1600"
91-
UNSAFE_style={{
92-
background: colorString
93-
}} >{colorString}</ActionButton>
94-
<Dialog
95-
width="size-3600"
96-
height="size-1600" >
97-
<View padding="size-300">
98-
{render({
99-
...props,
100-
value: color,
101-
onChange: (newColor: Color) => {
102-
setColor(newColor);
103-
if (props.onChange) { props.onChange(newColor); }
104-
}
105-
})}
106-
</View>
107-
</Dialog>
108-
</DialogTrigger>
10967
);
110-
}
11168

11269
function ControlledHexColorField(props: any = {}) {
11370
let [color, setColor] = useState(props.value || null);
@@ -116,13 +73,21 @@ function ControlledHexColorField(props: any = {}) {
11673
if (props.onChange) { props.onChange(color); }
11774
};
11875
let style = color ? {backgroundColor: color.toString('rgb')} : {};
76+
let id = useId();
11977
return (
12078
<Flex direction="row" gap="size-100" alignItems="end">
12179
<HexColorField
80+
id={id}
12281
label="Primary Color"
12382
onChange={onChange}
12483
value={color} />
125-
<View width="size-400" height="size-400" UNSAFE_style={style} />
84+
<View width="size-400" height="size-400" UNSAFE_style={style}>
85+
<VisuallyHidden>
86+
<output htmlFor={id} aria-live="off">
87+
{color ? color.toString('hex') : ''}
88+
</output>
89+
</VisuallyHidden>
90+
</View>
12691
</Flex>
12792
);
12893
}

packages/@react-spectrum/color/test/HexColorField.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ describe('HexColorField', function () {
4040
let hexColorField = getByLabelText('Primary Color');
4141
let label = getByText('Primary Color');
4242
expect(hexColorField).toBeInTheDocument();
43-
expect(getByRole('spinbutton')).toBe(hexColorField);
43+
expect(getByRole('textbox')).toBe(hexColorField);
4444
expect(hexColorField).toHaveAttribute('type', 'text');
4545
expect(hexColorField).toHaveAttribute('autocomplete', 'off');
4646
expect(hexColorField).toHaveAttribute('autocorrect', 'off');
@@ -64,7 +64,7 @@ describe('HexColorField', function () {
6464

6565
it('should allow placeholder', function () {
6666
let {getByPlaceholderText, getByRole} = renderComponent({placeholder: 'Enter a color'});
67-
expect(getByRole('spinbutton')).toBe(getByPlaceholderText('Enter a color'));
67+
expect(getByRole('textbox')).toBe(getByPlaceholderText('Enter a color'));
6868
});
6969

7070
it('should show valid validation state', function () {

0 commit comments

Comments
 (0)