Skip to content

Commit 6a2c9f2

Browse files
docs(fieldlabel/form): migrates docs to storybook (#3165)
* docs(fieldlabel): adds missing stories and cleans up test cases - adds missing stories and corresponding documentation - removes duplicate test case for right-aligned - adds customStyles to default test to match all other test styles * docs(form): adds missing stories, controls, test cases - adds missing stories and corresponding documentation - adds new test cases - adds fieldLabelAlignment control for left/right aligned field labels * chore(fieldlabel,form): pr edits - added documentation around the "necessity indicator" being text - included a required state for the wrapping/truncation test changes - set default args for form items
1 parent 6b60092 commit 6a2c9f2

File tree

5 files changed

+214
-63
lines changed

5 files changed

+214
-63
lines changed

components/fieldlabel/stories/fieldlabel.stories.js

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { disableDefaultModes } from "@spectrum-css/preview/modes";
22
import { isDisabled, isRequired, size } from "@spectrum-css/preview/types";
3+
import { Sizes } from "@spectrum-css/preview/decorators";
34
import pkgJson from "../package.json";
45
import { FieldLabelGroup } from "./fieldlabel.test.js";
6+
import { Template } from "./template.js";
57

68
/**
79
* The field label component is used along with inputs to display a label for that input.
@@ -39,15 +41,93 @@ export default {
3941
alignment: "left",
4042
isDisabled: false,
4143
isRequired: false,
44+
label: "Label",
4245
},
4346
parameters: {
4447
packageJson: pkgJson,
4548
},
4649
};
4750

51+
/**
52+
* By default, a field label has left-aligned text, and is a medium size. For field label text, use a short, catch-all description (1-3 words) of the information that a user needs to provide.
53+
*
54+
* The default position of a field label is above an input, but it can alternatively be positioned to the side. Visit the [form component](/docs/components-form--docs) to see examples of the field label with an input.
55+
56+
*/
4857
export const Default = FieldLabelGroup.bind({});
49-
Default.args = {
58+
Default.args = {};
59+
60+
// ********* DOCS ONLY ********* //
61+
/**
62+
* Field labels come in four different sizes: small, medium, large, and extra-large. The medium size is the default and most frequently used option with medium-sized inputs. Use the other sizes sparingly; they should be used to create a hierarchy of importance within the page.
63+
*
64+
* Both small and medium field labels have the same font size, but different paddings when used as side labels.
65+
*/
66+
export const Sizing = (args, context) => Sizes({
67+
Template,
68+
withBorder: false,
69+
withHeading: false,
70+
...args,
71+
}, context);
72+
Sizing.tags = ["!dev"];
73+
Sizing.parameters = {
74+
chromatic: { disableSnapshot: true },
75+
};
76+
77+
/**
78+
* To render right-aligned field label text, apply the `.spectrum-FieldLabel--right` class to the field label.
79+
*
80+
*/
81+
export const RightAligned = Template.bind({});
82+
RightAligned.args = {
5083
label: "Label",
84+
alignment: "right",
85+
customStyles: {
86+
width: "72px",
87+
},
88+
};
89+
RightAligned.tags = ["!dev"];
90+
RightAligned.parameters = {
91+
chromatic: { disableSnapshot: true },
92+
};
93+
RightAligned.storyName = "Right-aligned";
94+
95+
/**
96+
* Field labels for required inputs can be marked with an asterisk at the end of the label. Optional inputs would then be understood to not have the asterisk. If using the asterisk icon, do not leave any space between the label text and the start of the `<svg>` element in the markup. Extra space should not be added in addition to the inline margin.
97+
*
98+
* The field label for a required field can display either the text “(required)”, or an asterisk.
99+
*/
100+
export const Required = Template.bind({});
101+
Required.args = {
102+
isRequired: true,
103+
};
104+
Required.tags = ["!dev"];
105+
Required.parameters = {
106+
chromatic: { disableSnapshot: true },
107+
};
108+
109+
/**
110+
* When the field label is too long for the available horizontal space, it wraps to form another line.
111+
*/
112+
export const WrappingAndRequired = Template.bind({});
113+
WrappingAndRequired.args = {
114+
label: "Label example with longer text that will wrap to the next line. And with an asterisk that marks it as required.",
115+
isRequired: true,
116+
customStyles: { width: "200px" },
117+
};
118+
WrappingAndRequired.tags = ["!dev"];
119+
WrappingAndRequired.parameters = {
120+
chromatic: { disableSnapshot: true },
121+
};
122+
WrappingAndRequired.storyName = "Wrapping and required";
123+
124+
export const Disabled = Template.bind({});
125+
Disabled.args = {
126+
isDisabled: true,
127+
};
128+
Disabled.tags = ["!dev"];
129+
Disabled.parameters = {
130+
chromatic: { disableSnapshot: true },
51131
};
52132

53133
// ********* VRT ONLY ********* //

components/fieldlabel/stories/fieldlabel.test.js

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,7 @@ export const FieldLabelGroup = Variants({
55
Template,
66
testData: [
77
{
8-
testHeading: "Default"
9-
},
10-
{
11-
testHeading: "Right alignment",
12-
alignment: "right",
8+
testHeading: "Default",
139
customStyles: { width: "200px" },
1410
},
1511
{
@@ -19,14 +15,14 @@ export const FieldLabelGroup = Variants({
1915
},
2016
{
2117
testHeading: "Wrapped",
22-
withStates: false,
23-
label: "Label example with longer text that will wrap to the next line. And with an asterisk that marks it as required.",
18+
label: "Label example with longer text that will wrap to the next line. Sometimes there is an asterisk that marks it as required.",
2419
customStyles: { width: "200px" },
2520
},
2621
],
2722
stateData: [
2823
{
2924
testHeading: "Disabled",
25+
ignore: ["Wrapped"],
3026
isDisabled: true,
3127
customStyles: { width: "200px" },
3228
},

components/fieldlabel/stories/form.stories.js

Lines changed: 116 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,147 @@
1+
import { Template as Checkbox } from "@spectrum-css/checkbox/stories/template.js";
2+
import { Template as Fieldgroup } from "@spectrum-css/fieldgroup/stories/template.js";
13
import { Template as Picker } from "@spectrum-css/picker/stories/template.js";
24
import { disableDefaultModes } from "@spectrum-css/preview/modes";
35
import { Template as Stepper } from "@spectrum-css/stepper/stories/template.js";
46
import { Template as TextField } from "@spectrum-css/textfield/stories/template.js";
7+
import { Template } from "./form.template.js";
58
import pkgJson from "../package.json";
69
import { FormGroup } from "./form.test.js";
710

811
/**
9-
* The form component is used for aligning multiple inputs and field groups within a form.
12+
* The form component is used for aligning multiple inputs and field groups within a form. It provides structure and spacing for your form fields.
1013
*/
1114
export default {
1215
title: "Form",
1316
component: "Form",
1417
argTypes: {
15-
labelsAbove: {
16-
name: "Labels above",
17-
type: { name: "boolean" },
18+
labelPosition: {
19+
name: "Label position",
20+
description: "Position of the field label in relation to the input.",
21+
type: { name: "string" },
1822
table: {
19-
type: { summary: "boolean" },
23+
type: { summary: "string" },
2024
category: "Component",
2125
},
22-
control: "boolean",
26+
control: "select",
27+
options: ["top", "side"],
2328
},
29+
fieldLabelAlignment: {
30+
name: "Field label alignment",
31+
type: { name: "string" },
32+
table: {
33+
type: { summary: "string" },
34+
category: "Component",
35+
},
36+
control: "select",
37+
options: ["left", "right"],
38+
if: { arg: "labelPosition", eq: "side" },
39+
},
40+
items: { table: { disable: true } },
2441
},
2542
args: {
2643
rootClass: "spectrum-Form",
27-
labelsAbove: false,
44+
labelPosition: "top",
45+
items: [
46+
{
47+
label: "Company title",
48+
id: "form-example-company",
49+
content: [
50+
(passthroughs, context) => TextField({
51+
...passthroughs,
52+
multiline: true,
53+
name: "field",
54+
}, context),
55+
],
56+
}, {
57+
label: "Email address",
58+
id: "form-example-email",
59+
content: [
60+
(passthroughs, context) => TextField({
61+
...passthroughs,
62+
type: "email",
63+
name: "email",
64+
}, context),
65+
],
66+
}, {
67+
label: "Country",
68+
id: "form-example-country",
69+
content: [
70+
(passthroughs, context) => Picker({
71+
...passthroughs,
72+
placeholder: "Select a country",
73+
name: "country",
74+
}, context),
75+
],
76+
}, {
77+
label: "Interest",
78+
id: "form-example-interests",
79+
content: [
80+
(passthroughs, context) => Fieldgroup({
81+
layout: "horizontal",
82+
items: [
83+
Checkbox({
84+
...passthroughs,
85+
label: "Kittens",
86+
customClasses: ["spectrum-FieldGroup-item"],
87+
}, context),
88+
Checkbox({
89+
...passthroughs,
90+
label: "Puppies",
91+
customClasses: ["spectrum-FieldGroup-item"],
92+
}, context),]
93+
}),
94+
],
95+
},{
96+
label: "Age",
97+
id: "form-example-amount",
98+
content: [
99+
(passthroughs, context) => Stepper({
100+
...passthroughs,
101+
}, context),
102+
]
103+
}
104+
],
28105
},
29106
parameters: {
30107
packageJson: pkgJson,
31108
},
32109
};
33110

111+
/**
112+
* A stacked layout with the labels above the form fields. The class `.spectrum-Form--labelPosition` is applied to the form itself. You do not need to apply a specific class to the field label because `.spectrum-FieldLabel--left` is applied to each to each [field label](/docs/components-field-label--docs) by default.
113+
*/
34114
export const Default = FormGroup.bind({});
35-
Default.args = {
36-
items: [
37-
{
38-
label: "Company title",
39-
id: "form-example-company",
40-
content: [
41-
(passthroughs, context) => TextField({
42-
...passthroughs,
43-
multiline: true,
44-
name: "field",
45-
}, context),
46-
],
47-
}, {
48-
label: "Email address",
49-
id: "form-example-email",
50-
content: [
51-
(passthroughs, context) => TextField({
52-
...passthroughs,
53-
type: "email",
54-
name: "email",
55-
}, context),
56-
],
57-
}, {
58-
label: "Country",
59-
id: "form-example-country",
60-
content: [
61-
(passthroughs, context) => Picker({
62-
...passthroughs,
63-
placeholder: "Select a country",
64-
name: "country",
65-
}, context),
66-
],
67-
}, {
68-
label: "Amount",
69-
id: "form-example-amount",
70-
content: [
71-
(passthroughs, context) => Stepper({
72-
...passthroughs,
73-
}, context),
74-
]
75-
}
76-
],
115+
Default.args = {};
116+
117+
/**
118+
* A two column layout with left-aligned label text.
119+
*/
120+
export const LeftAlignedSideLabels = Template.bind({});
121+
LeftAlignedSideLabels.args = {
122+
...Default.args,
123+
labelPosition: "side",
124+
};
125+
LeftAlignedSideLabels.tags = ["!dev"];
126+
LeftAlignedSideLabels.parameters = {
127+
chromatic: { disableSnapshot: true },
128+
};
129+
LeftAlignedSideLabels.storyName = "Left-aligned side labels";
130+
131+
/**
132+
* A two column layout with right-aligned label text. `.spectrum-FieldLabel--right` is applied to each to each [field label](/docs/components-field-label--docs).
133+
*/
134+
export const RightAlignedSideLabels = Template.bind({});
135+
RightAlignedSideLabels.args = {
136+
...Default.args,
137+
labelPosition: "side",
138+
fieldLabelAlignment: "right",
139+
};
140+
RightAlignedSideLabels.tags = ["!dev"];
141+
RightAlignedSideLabels.parameters = {
142+
chromatic: { disableSnapshot: true },
77143
};
144+
RightAlignedSideLabels.storyName = "Right-aligned side labels";
78145

79146
// ********* VRT ONLY ********* //
80147
export const WithForcedColors = FormGroup.bind({});

components/fieldlabel/stories/form.template.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import "../index.css";
1111

1212
export const Template = ({
1313
rootClass = "spectrum-Form",
14-
labelsAbove = false,
14+
labelPosition = "top",
15+
fieldLabelAlignment = "left",
1516
customClasses = [],
1617
customStyles = {},
1718
id = getRandomId("form"),
@@ -20,7 +21,7 @@ export const Template = ({
2021
<form
2122
class=${classMap({
2223
[rootClass]: true,
23-
[`${rootClass}--labelsAbove`]: labelsAbove,
24+
[`${rootClass}--labelsAbove`]: labelPosition === "top",
2425
...customClasses.reduce((a, c) => ({ ...a, [c]: true }), {}),
2526
})}
2627
id=${ifDefined(id)}
@@ -36,7 +37,7 @@ export const Template = ({
3637
${when(label, () => FieldLabel({
3738
label,
3839
forInput: item.id,
39-
alignment: labelsAbove ? undefined : "left",
40+
alignment: labelPosition === "side" ? fieldLabelAlignment : undefined,
4041
}, context))}
4142
<div class=${classMap({
4243
[`${rootClass}-itemField`]: true,

components/fieldlabel/stories/form.test.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,17 @@ import { Template } from "./form.template";
44
export const FormGroup = Variants({
55
Template,
66
testData: [
7-
{},
87
{
9-
testHeading: "Labels above",
10-
labelsAbove: true,
8+
testHeading: "Default",
9+
},
10+
{
11+
testHeading: "Side labels with left-aligned text",
12+
labelPosition: "side",
13+
},
14+
{
15+
testHeading: "Side labels with right-aligned text",
16+
labelPosition: "side",
17+
fieldLabelAlignment: "right",
1118
}
1219
],
1320
});

0 commit comments

Comments
 (0)