Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(a11y): connect labels to inputs #1542

Merged
merged 15 commits into from
Jan 31, 2025
Merged
Show file tree
Hide file tree
Changes from 9 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
11 changes: 11 additions & 0 deletions ui/.storybook/withControlGroup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';
import ControlGroup from '@splunk/react-ui/ControlGroup';
import { Decorator } from '@storybook/react';

export const withControlGroup: Decorator = (StoryFn, { name }) => {
return (
<ControlGroup label={name} labelWidth={260}>
{StoryFn()}
</ControlGroup>
);
};
15 changes: 7 additions & 8 deletions ui/src/components/BaseFormView/BaseFormViewGrups.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ it('should modify correctly all properties of field in groups', async () => {
handleFormSubmit={handleFormSubmit}
/>
);
await screen.findByText('Text 1 Group 2');
await screen.findByRole('textbox', { name: 'Text 1 Group 2' });

const getAndValidateGroupFieldLabels = (
fieldId: string,
Expand All @@ -46,14 +46,13 @@ it('should modify correctly all properties of field in groups', async () => {
return modifiedFieldSameGroup;
};

const modifiedFieldSameGroup = getAndValidateGroupFieldLabels(
'text_field_2_group_1',
'help after mods 2-1',
'label after mods 2-1',
'markdown message after mods 2-1'
);
const modifiedFieldSameGroup = screen.getByRole('textbox', {
name: 'label after mods 2-1',
description: 'markdown message after mods 2-1 help after mods 2-1',
});

expect(within(modifiedFieldSameGroup).queryByText('*')).toBeInTheDocument();
expect(modifiedFieldSameGroup).toBeInTheDocument();
expect(modifiedFieldSameGroup).toHaveAttribute('required');

const modifiedFieldDiffGroup = getAndValidateGroupFieldLabels(
'text_field_2_group_2',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ it('should render base form correctly with name and File fields', async () => {
/>
);

const nameField = document.querySelector('[data-name="name"]');
expect(nameField).toBeInTheDocument();
screen.getByRole('textbox', { name: 'Name' });

const fileField = document.querySelector('[data-name="name"]');
expect(fileField).toBeInTheDocument();
Expand Down
11 changes: 7 additions & 4 deletions ui/src/components/CheckBoxComponent/CheckBoxComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import React from 'react';
import Switch from '@splunk/react-ui/Switch';
import { isFalse } from '../../util/considerFalseAndTruthy';

import { excludeControlWrapperProps } from '../ControlWrapper/utils';

export interface CheckBoxComponentProps {
value: 0 | 1 | boolean;
handleChange: (field: string, value: 0 | 1) => void;
Expand All @@ -19,13 +21,14 @@ class CheckBoxComponent extends React.Component<CheckBoxComponentProps> {
};

render() {
const { field, value, ...restProps } = this.props;
const restSuiProps = excludeControlWrapperProps(restProps);
return (
<Switch
key={this.props.field}
value={this.props.field}
{...restSuiProps}
value={field}
onClick={this.handleChange}
disabled={this.props.disabled}
selected={!(this.props.value ? isFalse(this.props.value) : true)}
selected={!(value ? isFalse(value) : true)}
appearance="checkbox"
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import type { Meta, StoryObj } from '@storybook/react';
import React, { useState } from 'react';
import { fn } from '@storybook/test';
import CheckBoxComponent from '../CheckBoxComponent';
import { withControlGroup } from '../../../../.storybook/withControlGroup';

const meta = {
component: CheckBoxComponent,
title: 'CheckBoxComponent',
decorators: [withControlGroup],
render: (props) => {
// due to stories incompatibility, eslint rule is off
// React Hook "useState" is called in function "render" that is neither a React function component
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 9 additions & 5 deletions ui/src/components/CheckboxGroup/CheckboxGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react';
import ColumnLayout from '@splunk/react-ui/ColumnLayout';
import Button from '@splunk/react-ui/Button';
import { StyledColumnLayout } from './StyledComponent';
import styled from 'styled-components';
import {
CheckboxGroupProps,
getDefaultValues,
Expand All @@ -16,6 +16,10 @@ import CheckboxRowWrapper from './CheckboxRowWrapper';
import { useValidation } from './checkboxGroupValidation';
import { MODE_CREATE } from '../../constants/modes';

const FullWidth = styled.div`
width: 100%;
`;

function CheckboxGroup(props: CheckboxGroupProps) {
const { field, handleChange, controlOptions, addCustomValidator, disabled } = props;
const flattenedRowsWithGroups = getFlattenRowsWithGroups(controlOptions);
Expand Down Expand Up @@ -60,8 +64,8 @@ function CheckboxGroup(props: CheckboxGroupProps) {
};

return (
<>
<StyledColumnLayout gutter={5}>
<FullWidth>
<ColumnLayout gutter={5}>
{flattenedRowsWithGroups.map((row) => {
if (isGroupWithRows(row)) {
// labels are unique across groups
Expand All @@ -88,7 +92,7 @@ function CheckboxGroup(props: CheckboxGroupProps) {
);
})}
<ColumnLayout.Row />
</StyledColumnLayout>
</ColumnLayout>
<div>
<Button
label="Select All"
Expand All @@ -101,7 +105,7 @@ function CheckboxGroup(props: CheckboxGroupProps) {
onClick={() => handleCheckboxToggleAll(false)}
/>
</div>
</>
</FullWidth>
);
}

Expand Down
3 changes: 1 addition & 2 deletions ui/src/components/CheckboxGroup/CheckboxRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import React, { useEffect, useState } from 'react';
import NumberComponent, { NumberChangeHandler } from '@splunk/react-ui/Number';
import styled from 'styled-components';
import Switch from '@splunk/react-ui/Switch';
import { FixedCheckboxRowWidth } from './StyledComponent';

const StyledSwitch = styled(Switch)`
padding: 0 3px;
Expand All @@ -16,7 +15,7 @@ const StyledRow = styled.div`
display: flex;
align-items: baseline;
justify-content: space-between;
${FixedCheckboxRowWidth}
width: 100%;
`;

interface CheckboxRowProps {
Expand Down
9 changes: 0 additions & 9 deletions ui/src/components/CheckboxGroup/StyledComponent.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import type { Meta, StoryObj } from '@storybook/react';
import { fn } from '@storybook/test';
import CheckboxGroup from '../CheckboxGroup';
import { MODE_CREATE, MODE_EDIT } from '../../../constants/modes';
import { withControlGroup } from '../../../../.storybook/withControlGroup';

const meta = {
component: CheckboxGroup,
title: 'CheckboxGroup/Component',
decorators: [withControlGroup],
} satisfies Meta<typeof CheckboxGroup>;

export default meta;
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 9 additions & 5 deletions ui/src/components/CheckboxTree/CheckboxTree.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useEffect, useState, useCallback, useMemo } from 'react';
import ColumnLayout from '@splunk/react-ui/ColumnLayout';
import Button from '@splunk/react-ui/Button';
import { StyledColumnLayout } from './StyledComponent';
import styled from 'styled-components';
import {
getDefaultValues,
getFlattenRowsWithGroups,
Expand All @@ -14,6 +14,10 @@ import { MODE_CREATE } from '../../constants/modes';
import { CheckboxTreeProps, ValueByField } from './types';
import { packValue, parseValue } from './utils';

const FullWidth = styled.div`
width: 100%;
`;

function CheckboxTree(props: CheckboxTreeProps) {
const { field, handleChange, controlOptions, disabled } = props;

Expand Down Expand Up @@ -94,8 +98,8 @@ function CheckboxTree(props: CheckboxTreeProps) {
);

return (
<>
<StyledColumnLayout gutter={5}>
<FullWidth>
<ColumnLayout gutter={5}>
{flattenedRowsWithGroups.map((row) =>
row && isGroupWithRows(row) ? (
<ColumnLayout.Row key={`group_${row.label}`}>
Expand All @@ -121,7 +125,7 @@ function CheckboxTree(props: CheckboxTreeProps) {
)
)}
<ColumnLayout.Row />
</StyledColumnLayout>
</ColumnLayout>
<div>
<Button
label="Select All"
Expand All @@ -134,7 +138,7 @@ function CheckboxTree(props: CheckboxTreeProps) {
onClick={() => handleCheckboxToggleAll(false)}
/>
</div>
</>
</FullWidth>
);
}

Expand Down
9 changes: 0 additions & 9 deletions ui/src/components/CheckboxTree/StyledComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,15 @@
import styled, { css } from 'styled-components';
import ColumnLayout from '@splunk/react-ui/ColumnLayout';
import CollapsiblePanel from '@splunk/react-ui/CollapsiblePanel';
import { pick, variables } from '@splunk/themes';
import Switch from '@splunk/react-ui/Switch';

const FixedCheckboxRowWidth = css`
width: 320px;
`;

const CheckboxInHeader = css`
align-self: center;
background-color: ${pick({
enterprise: variables.neutral100,
})};
`;

export const StyledColumnLayout = styled(ColumnLayout)`
${FixedCheckboxRowWidth}
`;

export const CheckboxContainer = styled.div`
display: flex;
flex-direction: column;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import type { Meta, StoryObj } from '@storybook/react';
import { fn } from '@storybook/test';
import CheckboxTree from '../CheckboxTree';
import { MODE_CREATE, MODE_EDIT } from '../../../constants/modes';
import { withControlGroup } from '../../../../.storybook/withControlGroup';

const meta = {
component: CheckboxTree,
title: 'CheckboxTree/Component',
decorators: [withControlGroup],
} satisfies Meta<typeof CheckboxTree>;

export default meta;
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 3 additions & 11 deletions ui/src/components/ControlWrapper/ControlWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,14 @@ import { AcceptableFormValueOrNullish } from '../../types/components/shareableTy
import CustomControl from '../CustomControl/CustomControl';
import { Mode } from '../../constants/modes';

const CustomElement = styled.div``;

const ControlGroupWrapper = styled(ControlGroup).attrs((props: { dataName: string }) => ({
'data-name': props.dataName,
}))`
max-width: 100%;

// label width + control width
width: calc(260px + 320px);
span[class*='ControlGroupStyles__StyledAsterisk-'] {
color: red;
}

> * {
&:nth-child(3) {
width: 320px;
}
}
`;

export interface ControlWrapperProps {
Expand Down Expand Up @@ -152,7 +144,7 @@ class ControlWrapper extends React.PureComponent<ControlWrapperProps> {
required={isFieldRequired}
label={label}
>
<CustomElement>{rowView}</CustomElement>
{rowView}
</ControlGroupWrapper>
)
);
Expand Down
Loading
Loading