Skip to content

Commit f3c5b48

Browse files
Ayesha Mazumdarbrandonferrua
authored andcommitted
fix(form-legend): Add styling for compound form with a tooltip icon next to the legend (#3151)
* fix(form-legend): Add example in compound form for a tooltip icon next to the legend * fix(form-legend): export compoundForm for future use * fix(form-legend): Add tests * fix(form-legend): Attach styling to new class instead of utility * fix(form-legend-icon): Remove example * fix(form-legend-icon): Update docs to include form layout info and legend icon blockquote * fix(form-legend-icon): remove form-layout from the components list * fix(form-legend-icon): Add inline help as example in input * fix(form-legend-icon): Remove inline class * fix(form-legend): Skip test for now * Update tests
1 parent 9ed087a commit f3c5b48

12 files changed

+314
-49
lines changed

ui/components/form-element/base/example.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const inputLabel = 'Form Element Label';
1414
const inputId = 'input-unique-id';
1515
const errorId = 'error-message-unique-id';
1616

17-
export let FormElement = props => {
17+
export const FormElement = props => {
1818
const {
1919
className,
2020
formControlClassName,

ui/components/form-element/docs.mdx

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,19 @@ import Example from '../../../shared/components/Example';
44
import Blockquote from '../../../shared/components/Blockquote';
55
import ButtonIcon from '../button-icons/';
66
import {FormElement} from './base/example';
7-
import {Input} from '../input/base/example';
8-
import {Checkbox} from '../checkbox/base/example';
9-
import {Textarea} from '../textarea/base/example';
10-
import {Avatar} from '../avatar/base/example';
7+
import { Input } from '../input/base/example';
8+
import { Checkbox } from '../checkbox/base/example';
9+
import { Textarea } from '../textarea/base/example';
10+
import { Avatar } from '../avatar/base/example';
11+
import { Form } from '../form-layout/base/example';
12+
import { CompoundForm } from '../form-layout/compound/example';
1113

1214
<div className="lead doc">
1315
An HTML form element contains a HTML label and element
1416
</div>
1517

18+
There are many types of form elements, including [inputs](/input), [text areas](/textarea), [checkboxes](/checkbox), and [radio buttons](/radio-group). Visit the individual component pages for in-depth details of specific states and visuals.
19+
1620
## Structuring a form element
1721

1822
To create a form element, a `<div>` element with the class `slds-form-element` is required.
@@ -32,7 +36,7 @@ A form element is made up of three primary elements, the label (`slds-form-eleme
3236
A form label should use the `<label>` element with the class `slds-form-element__label`.
3337

3438
<Blockquote type="a11y" header="Accessibility requirement">
35-
It is required to have the <code className="doc">for</code> attr applied the the label that points to the ID of the form element, <code className="doc"><input id="unique-id"></code>.
39+
Labels must have the <code className="doc">for</code> attribute applied, and its value must match the ID of the associated form element, like <code className="doc"><input id="unique-id-of-input"></code>. This association ensures that assistive technology informs users about what information to enter where.
3640
</Blockquote>
3741

3842
<CodeBlock toggleCode={false}>
@@ -110,11 +114,13 @@ By default, the overall form element takes up 54px of vertical space. If you req
110114

111115
### Feedback
112116

113-
A form element provides two types of feedback, a required form element and a form element with an error.
117+
A form element can have various methods of feedback, such as a required denotation or an inline error message.
114118

115119
#### Required
116120

117-
When a form element is required, an `<abbr>` should be injected before the `<input>` with the class `slds-required`.
121+
When a form element is required, an `<abbr>` should be injected before the `<input>` and within the `<label>` and have the class `slds-required`.
122+
123+
The `<input>` element should also have the HTML attribute required or required="". Similarily, if it is disabled, it should have the disabled or disabled="" attribute. Do not use true/false values inside the required or disabled because the mere presence of these attributes signifies the field is required or disabled.
118124

119125
<Example title="Form Element - Required">
120126

@@ -128,10 +134,10 @@ When a form element is required, an `<abbr>` should be injected before the `<inp
128134

129135
#### Error
130136

131-
If an error has occured while submitting a form, the form element with an error should provide feedback.
137+
If an error has occured while submitting a form, the form element with an error should provide feedback. The `slds-has-error` class is placed on the `<div class="slds-form-element">`. Then, the error message for the user is placed in a `<span>` with the `slds-form-element__help` class.
132138

133139
<Blockquote type="a11y" header="Accessibility requirement">
134-
When a form element displayed feedback notifying the user of an error, the error string should be linked to the element by adding <code className="doc">aria-describedby</code> attribute to the <code className="doc"><input></code> and point to the error message ID.
140+
When a form element displays feedback notifying the user of an error, the error string should be linked to the element by adding the <code className="doc">aria-describedby</code> attribute to the <code className="doc"><input></code>. The `aria-describedby` attribute must reference the id of the error message. This configuration allows screen readers to read the associated error message when the invalid field is focused.
135141
</Blockquote>
136142

137143
<Example title="Form Element - Error">
@@ -140,17 +146,53 @@ If an error has occured while submitting a form, the form element with an error
140146
<FormElement
141147
className="slds-has-error"
142148
label="Form Label"
143-
inputId="form-element-04"
149+
inputId="form-element-05"
144150
errorId="form-error-01"
145151
required
146152
message="This field is required"
147153
>
148-
<Input id="form-element-04" required aria-describedby="form-error-01" />
154+
<Input id="form-element-05" required aria-describedby="form-error-01" />
149155
</FormElement>
150156
</CodeView>
151157

152158
</Example>
153159

160+
## Layout
161+
162+
Layout helper classes are available through the following class names: `slds-form_stacked` and `slds-form_horizontal`. For optimal spacing and layout, ensure the `slds-form-element` class is present on each element within the form.
163+
164+
### Stacked
165+
166+
To vertically stack `<label>` and `<input>` pairs, place `slds-form--stacked` on the wrapper of the form for optimal spacing.
167+
168+
<Example title="Form Layout - Stacked">
169+
<CodeView>
170+
<Form/>
171+
</CodeView>
172+
</Example>
173+
174+
### Horizontal
175+
176+
To horizontally align a `<label>` and `<input>`, use the `slds-form--horizontal` class on the wrapper around the form. A `slds-form-element__label` takes up 33% of the width, and the `slds-form-element__control` uses the remaining 66%.
177+
178+
<Example title="Form Layout - Horizontal">
179+
<CodeView>
180+
<Form className="slds-form_horizontal"/>
181+
</CodeView>
182+
</Example>
183+
184+
### Compound
185+
186+
<Blockquote type="note" header="Implementation Note">
187+
To use field level help with a `<legend>` (as opposed to a `<label>`), the `<legend>` and the `<div>` with the help icon must be siblings. Additionally, you'll need to add the class `slds-form-element__legend_has-tooltip` to the `<legend>`. Only add this class when your `<legend>` has adjacent field level help, otherwise you'll experience unexpected layouts.
188+
</Blockquote>
189+
190+
<Example title="Form Layout - Compound">
191+
<CodeView>
192+
<CompoundForm/>
193+
</CodeView>
194+
</Example>
195+
154196
## Usage Examples
155197

156198
### Record Detail

ui/components/form-layout/__tests__/__snapshots__/Form_Layout_renders_a_base_form_layout.json

Lines changed: 43 additions & 0 deletions
Large diffs are not rendered by default.

ui/components/form-layout/__tests__/__snapshots__/Form_Layout_renders_a_base_form_layout_horizontally.json

Lines changed: 43 additions & 0 deletions
Large diffs are not rendered by default.

ui/components/form-layout/__tests__/__snapshots__/Form_Layout_renders_a_compound_form_layout.json

Lines changed: 38 additions & 0 deletions
Large diffs are not rendered by default.

ui/components/form-layout/__tests__/__snapshots__/Form_Layout_renders_a_compound_form_layout_with_a_tooltip.json

Lines changed: 45 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright (c) 2015-present, salesforce.com, inc. All rights reserved
2+
// Licensed under BSD 3-Clause - see LICENSE.txt or git.io/sfdc-license
3+
/* eslint-env jest */
4+
5+
import React from 'react';
6+
import createHelpers from '../../../../jest.helpers';
7+
import { Form } from '../base/example';
8+
import { CompoundForm } from '../compound/example';
9+
10+
const { matchesMarkupAndStyle } = createHelpers(__dirname);
11+
12+
describe('Form Layout', () => {
13+
xit('renders a base form layout', () => matchesMarkupAndStyle(<Form />));
14+
15+
it('renders a base form layout horizontally', () =>
16+
matchesMarkupAndStyle(<Form className="slds-form_horizontal" />));
17+
18+
it('renders a compound form layout', () =>
19+
matchesMarkupAndStyle(<CompoundForm />));
20+
21+
it('renders a compound form layout with a tooltip', () =>
22+
matchesMarkupAndStyle(<CompoundForm tooltip />));
23+
});

ui/components/form-layout/_doc.scss

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,2 @@
11
// Copyright (c) 2015-present, salesforce.com, inc. All rights reserved
22
// Licensed under BSD 3-Clause - see LICENSE.txt or git.io/sfdc-license
3-
4-
/**
5-
* To vertically stack `<label>` and `<input>` pairs, place `.slds-form--stacked` on the wrapper of the form for optimal spacing.
6-
*
7-
* To horizontally align a `<label>` and `<input>`, use the `.slds-form--horizontal` class on the wrapper around the form. A `.slds-form-element__label` takes up 33% of the width, and the `.slds-form-element__control` uses the remaining 66%.
8-
*
9-
* For optimum spacing and layout, wrap each element in `.slds-form-element`. Layout helper classes are available through the following class names, `.slds-form--stacked`, `.slds-form--horizontal` and `.slds-form--inline`.
10-
*
11-
* The read-only state is for form elements that can’t be modified. It is used for small, non-editable form fields that sit next to inputs and allows the size and height to align. It is not meant for large paragraphs of text.
12-
*
13-
* Because the read-only field state has no `<input>`, don’t use a `<label>` to provide better accessibility for screen readers and keyboard navigators. Instead, use a `<span>` with the `.slds-form-element__label` class. Instead of an `<input>`, use the `.slds-form-element__static` class inside the `.slds-form-element__control` wrapper.
14-
*
15-
* Error states alert the user when content in the form is invalid. The `.slds-has-error` class is placed on the `<div class="slds-form-element">`. Place the error message for the user in a `<span>` with the `.slds-form-element__help` class.
16-
*
17-
* The native form elements, `<input>`, `<textarea>`, `<select>`, `<input type='checkbox'>`, and `<input type='radio'>`, receive validation styling for `disabled`, `checked`, and `checked disabled`, if applicable.
18-
*
19-
* #### Accessibility
20-
*
21-
* Every field requires an associated, non-empty `<label>` element. The label should have a `for` attribute that references the `id` of the field. For example, `<label for="emailAddress">Enter email address:</label>` and `<input id="emailAddress">`. This association ensures that assistive technology informs users what information to enter where.
22-
*
23-
* If the field is required, the `<input>` element should have the HTML attribute `required` or `required=""`. Similarily, if it is disabled, it should have the `disabled` or `disabled=""` attribute. Do not use true/false values inside the `required` or `disabled` because the mere presence of these attributes signifies the field is required or disabled.
24-
*
25-
* If the field is invalid and displays an error message, the `<input>` element should have an `aria-describedby` attribute that references the `id` of the error message. This configuration allows screen readers to read the associated error message when the invalid field is focused.
26-
*
27-
* @summary An HTML form contains interactive controls to submit information to a web server.
28-
*
29-
* @base
30-
* @name form-layout
31-
* @selector .slds-form
32-
* @support dev-ready
33-
* @category structure
34-
* @type layout
35-
* @layout responsive
36-
*/

ui/components/form-layout/base/_index.scss

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
*
8383
* @selector .slds-form_inline
8484
* @restrict .slds-form
85+
* @modifier
8586
*/
8687
.slds-form_inline,
8788
.slds-form--inline {
@@ -115,3 +116,13 @@
115116
}
116117
}
117118
}
119+
120+
/**
121+
* @summary Aligns the legend properly when there is an info tooltip
122+
*
123+
* @selector .slds-form-element__legend_has-tooltip
124+
* @restrict .slds-form-element__legend
125+
*/
126+
.slds-form-element__legend_has-tooltip {
127+
float: left;
128+
}

ui/components/form-layout/base/example.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const inputId01 = 'input-id-01';
1313
const inputId02 = 'input-id-02';
1414
const inputId03 = 'input-id-03';
1515

16-
let Form = props => (
16+
export const Form = props => (
1717
<div className={classNames('slds-form', props.className)}>
1818
<FormElement label="Text Input" inputId={inputId01}>
1919
<Input id={inputId01} />

0 commit comments

Comments
 (0)