Skip to content

Commit

Permalink
Added EuiFormFieldset and EuiFormLegend components (#2706)
Browse files Browse the repository at this point in the history
* Moved form label font styles to a mixin
* Added `EuiFormFieldset` and `EuiFormLegend` components
* Remove unecessary omit and update tests to include children
  • Loading branch information
cchaos committed Jan 3, 2020
1 parent 9126176 commit b7cca07
Show file tree
Hide file tree
Showing 17 changed files with 289 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Converted `EuiSuggest` to Typescript ([#2692](https://github.com/elastic/eui/pull/2692))
- Converted `EuiErrorBoundary` to Typescript ([#2690](https://github.com/elastic/eui/pull/2690))
- Updated `EuiNavDrawer` to accept React fragments ([#2710](https://github.com/elastic/eui/pull/2710))
- Added `EuiFormFieldset` and `EuiFormLegend` components ([#2706](https://github.com/elastic/eui/pull/2706))

**Bug fixes**

Expand Down
13 changes: 13 additions & 0 deletions src-docs/src/views/form_controls/fieldset.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';

import { EuiFormFieldset } from '../../../../src/components/form/form_fieldset';
import { EuiSwitch } from '../../../../src/components/form/switch';
import { EuiSpacer } from '../../../../src/components/spacer';

export default () => (
<EuiFormFieldset legend={{ children: 'Enable these objects' }}>
<EuiSwitch label="Object 1" onChange={() => {}} checked={false} />
<EuiSpacer size="s" />
<EuiSwitch label="Object 2" onChange={() => {}} checked={true} />
</EuiFormFieldset>
);
62 changes: 62 additions & 0 deletions src-docs/src/views/form_controls/form_controls_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import {
EuiFieldSearch,
EuiFieldText,
EuiFilePicker,
EuiFormFieldset,
EuiFormLegend,
EuiFormControlLayout,
EuiFormControlLayoutDelimited,
EuiLink,
Expand All @@ -25,6 +27,7 @@ import {
EuiSelect,
EuiSwitch,
EuiTextArea,
EuiSpacer,
} from '../../../../src/components';

import FieldSearch from './field_search';
Expand Down Expand Up @@ -79,6 +82,10 @@ import PrependAppend from './prepend_append';
const PrependAppendSource = require('!!raw-loader!./prepend_append');
const PrependAppendHtml = renderToHtml(PrependAppend);

import Fieldset from './fieldset';
const fieldsetSource = require('!!raw-loader!./fieldset');
const fieldsetHtml = renderToHtml(Fieldset);

import FormControlLayout from './form_control_layout';
const formControlLayoutSource = require('!!raw-loader!./form_control_layout');
const formControlLayoutHtml = renderToHtml(FormControlLayout);
Expand Down Expand Up @@ -319,6 +326,61 @@ export const FormControlsExample = {
},
demo: <Switch />,
},
{
title: 'Fieldset and legend',
source: [
{
type: GuideSectionTypes.JS,
code: fieldsetSource,
},
{
type: GuideSectionTypes.HTML,
code: fieldsetHtml,
},
],
text: (
<Fragment>
<EuiCallOut
color="warning"
iconType="accessibility"
size="s"
title={
<span>
&quot;[Use a fieldset and legend] for groups of related controls
where the individual labels for each control do not provide a
sufficient description, and an additional group level
description is needed.&quot;{' '}
<EuiLink
external
href="https://www.w3.org/WAI/WCAG21/Techniques/html/H71">
WCAG Spec
</EuiLink>
</span>
}
/>
<EuiSpacer />
<p>
<EuiCode>EuiFieldset</EuiCode> simply wraps its children in a{' '}
<EuiCode>&lt;fieldset&gt;</EuiCode> with the option to add a{' '}
<EuiCode>&lt;legend&gt;</EuiCode> via the <EuiCode>legend</EuiCode>{' '}
object prop.
</p>
</Fragment>
),
props: {
EuiFormFieldset,
EuiFormLegend,
},
demo: <Fieldset />,
snippet: [
`<EuiFormFieldset legend={{ children: 'Legend' }}>
/* Controls */
</EuiFormFieldset>`,
`<EuiFormFieldset legend={{ children: 'Hidden legend', display: 'hidden' }}>
/* Controls */
</EuiFormFieldset>`,
],
},
{
title: 'Prepend and Append',
text: (
Expand Down
1 change: 1 addition & 0 deletions src/components/form/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
@import 'form';
@import 'form_control_layout/index';
@import 'form_error_text/index';
@import 'form_fieldset/index';
@import 'form_help_text/index';
@import 'form_label/index';
@import 'form_row/index';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`EuiFormFieldset is rendered 1`] = `
<fieldset
aria-label="aria-label"
class="testClass1 testClass2"
data-test-subj="test subject string"
>
<input />
</fieldset>
`;

exports[`EuiFormFieldset props legend is rendered 1`] = `
<fieldset>
<legend
class="euiFormLegend"
>
Legend
</legend>
<input />
</fieldset>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`EuiFormLegend is rendered 1`] = `
<legend
aria-label="aria-label"
class="euiFormLegend testClass1 testClass2"
data-test-subj="test subject string"
>
Legend
</legend>
`;

exports[`EuiFormLegend props compressed is rendered 1`] = `
<legend
class="euiFormLegend euiFormLegend--compressed"
>
Legend
</legend>
`;

exports[`EuiFormLegend props hidden is rendered 1`] = `
<legend
class="euiFormLegend euiFormLegend-isHidden"
>
<span
class="euiScreenReaderOnly"
>
Legend
</span>
</legend>
`;
11 changes: 11 additions & 0 deletions src/components/form/form_fieldset/_form_legend.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.euiFormLegend {
@include euiFormLabel;

&:not(.euiFormLegend-isHidden) {
margin-bottom: $euiSizeS;

&.euiFormLegend--compressed {
margin-bottom: $euiSizeXS;
}
}
}
1 change: 1 addition & 0 deletions src/components/form/form_fieldset/_index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@import 'form_legend';
29 changes: 29 additions & 0 deletions src/components/form/form_fieldset/form_fieldset.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import { render } from 'enzyme';
import { requiredProps } from '../../../test/required_props';

import { EuiFormFieldset } from './form_fieldset';

describe('EuiFormFieldset', () => {
test('is rendered', () => {
const component = render(
<EuiFormFieldset {...requiredProps}>
<input />
</EuiFormFieldset>
);

expect(component).toMatchSnapshot();
});

describe('props', () => {
test('legend is rendered', () => {
const component = render(
<EuiFormFieldset legend={{ children: 'Legend' }}>
<input />
</EuiFormFieldset>
);

expect(component).toMatchSnapshot();
});
});
});
28 changes: 28 additions & 0 deletions src/components/form/form_fieldset/form_fieldset.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React, { HTMLAttributes, FunctionComponent } from 'react';
import { CommonProps } from '../../common';
import { EuiFormLegendProps, EuiFormLegend } from './form_legend';

export interface EuiFormFieldsetProps
extends CommonProps,
HTMLAttributes<HTMLFieldSetElement> {
/**
* Adds an EuiFormLegend element as the first child
*/
legend?: EuiFormLegendProps;
}

export const EuiFormFieldset: FunctionComponent<EuiFormFieldsetProps> = ({
children,
className,
legend,
...rest
}) => {
const legendDisplay = !!legend && <EuiFormLegend {...legend} />;

return (
<fieldset className={className} {...rest}>
{legendDisplay}
{children}
</fieldset>
);
};
33 changes: 33 additions & 0 deletions src/components/form/form_fieldset/form_legend.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from 'react';
import { render } from 'enzyme';
import { requiredProps } from '../../../test/required_props';

import { EuiFormLegend } from './form_legend';

describe('EuiFormLegend', () => {
test('is rendered', () => {
const component = render(
<EuiFormLegend {...requiredProps}>Legend</EuiFormLegend>
);

expect(component).toMatchSnapshot();
});

describe('props', () => {
test('hidden is rendered', () => {
const component = render(
<EuiFormLegend display="hidden">Legend</EuiFormLegend>
);

expect(component).toMatchSnapshot();
});

test('compressed is rendered', () => {
const component = render(
<EuiFormLegend compressed>Legend</EuiFormLegend>
);

expect(component).toMatchSnapshot();
});
});
});
44 changes: 44 additions & 0 deletions src/components/form/form_fieldset/form_legend.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React, { HTMLAttributes, FunctionComponent, ReactNode } from 'react';
import { CommonProps } from '../../common';
import classNames from 'classnames';
import { EuiScreenReaderOnly } from '../../accessibility';

export type EuiFormLegendProps = HTMLAttributes<HTMLLegendElement> &
CommonProps & {
children: ReactNode;
/**
* For a hidden legend that is still visible to the screen reader, set to 'hidden'
*/
display?: 'hidden' | 'visible';
compressed?: boolean;
};

export const EuiFormLegend: FunctionComponent<EuiFormLegendProps> = ({
children,
className,
display = 'visible',
compressed,
...rest
}) => {
const isLegendHidden = display === 'hidden';
const classes = classNames(
'euiFormLegend',
{
'euiFormLegend-isHidden': isLegendHidden,
'euiFormLegend--compressed': compressed,
},
className
);

return (
<legend className={classes} {...rest}>
{isLegendHidden ? (
<EuiScreenReaderOnly>
<span>{children}</span>
</EuiScreenReaderOnly>
) : (
children
)}
</legend>
);
};
2 changes: 2 additions & 0 deletions src/components/form/form_fieldset/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { EuiFormFieldset, EuiFormFieldsetProps } from './form_fieldset';
export { EuiFormLegend, EuiFormLegendProps } from './form_legend';
4 changes: 1 addition & 3 deletions src/components/form/form_label/_form_label.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@
* 1. Focused state overrides invalid state.
*/
.euiFormLabel {
@include euiFontSizeXS;
@include euiFormLabel;
display: inline-block;
transition: all $euiAnimSpeedFast $euiAnimSlightResistance;
color: $euiTitleColor;
font-weight: $euiFontWeightSemiBold;

&.euiFormLabel-isInvalid {
color: $euiColorDanger; /* 1 */
Expand Down
1 change: 1 addition & 0 deletions src/components/form/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export {
EuiFormControlLayoutDelimited,
} from './form_control_layout';
export { EuiFormErrorText } from './form_error_text';
export { EuiFormFieldset, EuiFormLegend } from './form_fieldset';
export { EuiFormHelpText } from './form_help_text';
export { EuiFormLabel } from './form_label';
export { EuiFormRow } from './form_row';
Expand Down
2 changes: 2 additions & 0 deletions src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,10 @@ export {
EuiFormControlLayout,
EuiFormControlLayoutDelimited,
EuiFormErrorText,
EuiFormFieldset,
EuiFormHelpText,
EuiFormLabel,
EuiFormLegend,
EuiFormRow,
EuiRadio,
EuiRadioGroup,
Expand Down
7 changes: 7 additions & 0 deletions src/global_styling/mixins/_form.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
// Labels
@mixin euiFormLabel {
@include euiFontSizeXS;
color: $euiTitleColor;
font-weight: $euiFontWeightSemiBold;
}

@mixin euiFormControlLayoutPadding($numOfIcons, $side: 'right', $compressed: false) {
$firstIconSize: $euiFormControlPadding + $euiSize + $euiFormControlPadding;
$secondIconSize: $euiFormControlPadding + $euiSize;
Expand Down

0 comments on commit b7cca07

Please sign in to comment.