Feature Proposal: Form Control
See original GitHub issueProposal: Form Control
Summary
The Form control enables layout, alignment, and grouping of form elements. Form elements are different control types associated with data input.
Rationale
Creating a form is a very common scenario for Enterprise and LOB applications. Easily creating a form that is evenly spaced, appropriately sized, semantically grouped, accessible, and contains the needed actions is a manual process using Grid (or other layout controls). While this is not difficult, it can be time consuming and cumbersome.
When creating a form using any of the layout panels provided today, Narrator support is only provided at the control level. No context is provided to user. Example: if the field is required, how many, which section, etc. by creating a Form layout control this can be provided to user for free and allow developers to focus on functionality and not layout.
Note: Data/Input validation will be tracked in a separate issue.
Functional Requirements
# | Feature | Priority |
---|---|---|
1 | Able to create sections with headers | Must |
2 | Able to support multiple columns | Must |
3 | Able to define actions (Submit, Cancel, etc) | Must |
4 | Able to group controls on one line | Must |
5 | Able to override padding and margin per section or overall form | Must |
6 | Support Compact density spacing rules | Must |
7 | Support expand/collapse behavior for Form Sections | Should |
8 | Wrap sections based on window size | Should |
9 | Use inline actions or command bar actions | Should |
10 | Able to add items to form dynamical | Should |
11 | Support for data binding | Should |
12 | Draw a line under each section | Should |
13 | Dedicated area for grouped validation errors | Could |
14 | Support inline actions next to input fields | Could |
Usage Examples
Create a single column form with inline actions
At default the control will create a single column form respecting spacing rules with actions at the bottom.
Create a multi-column form with sections and groups
By providing a few properties the Form control can easily adapt to more complex data input scenarios. Without the need to define row and column definitions. The spacing rules are built into the Form control.
Detailed Feature Design
Visual Anatomy of a Form
The Form control contains a three different components.
- FormSection: Collection of controls relative to each other in layout equally spaced across specified columns.
- FormGroup: Collection of controls within a section relative to each other in layout. Spaced based on parameters given.
- FormActions: Collection of commands associated with the overall Form control.
Default Spacing
The Forms control will provide default spacing rules but these can be overwritten in markup.
- Forms maintain a 24px margin on all sides
- Spacing between forms sections and headers is 24px
- Spacing between a forms section header and sub title is 12px
- Spacing between forms sections is 24px
- Spacing between controls in a form or form section is 12px
- Spacing between the actions associated with a form is 12px
- Spacing between forms in the same row is 12px
Creating a Complex Form
The example below used FormSection and FormGroup to build a Form for a new patient.
<Form Name="NewPatient">
<FormSection Header="Name" Columns="2">
<TextBox Header="First name"/>
<TextBox Header="Last name"/>
<FormGroup Columns="Auto, *">
<TextBox Header="M.I." Width="40"/>
<ComboBox Header="Suffix" PlaceholderText="Select" HorizontalAlignment="Stretch"/>
</FormGroup>
<TextBox Header="Last name"/>
</FormSection>
<FormSection Header="Basic info" Columns="2">
<TextBox Header="Pharmacy ID"/>
<ComboBox Header="Emergency priorty level" PlaceholderText="Select" HorizontalAlignment="Stretch"/>
<FormGroup>
<CalendarDatePicker Header="Date of birth" HorizontalAlignment="Stretch"/>
<TextBox Header="SSN"/>
</FormGroup>
<TextBox Header="Citizenship"/>
<TextBox Header="Place of birth"/>
<ComboBox Header="Birth state (US only)" PlaceholderText="Select" HorizontalAlignment="Stretch"/>
<FormGroup>
<ComboBox Header="Gender" PlaceholderText="Select" HorizontalAlignment="Stretch"/>
<ComboBox Header="Ethnicity" PlaceholderText="Select" HorizontalAlignment="Stretch"/>
</FormGroup>
<FormGroup>
<ComboBox Header="Martial Status" PlaceholderText="Select" HorizontalAlignment="Stretch"/>
<ComboBox Header="Religion" PlaceholderText="Select" HorizontalAlignment="Stretch"/>
</FormGroup>
<ComboBox Header="Primary language" PlaceholderText="Select" HorizontalAlignment="Stretch"/>
<ComboBox Header="Secondary language" PlaceholderText="Select" HorizontalAlignment="Stretch"/>
</FormSection>
<FormSection Header="Contact" Columns="2">
<TextBox Header="Address 1"/>
<TextBox Header="Address 2"/>
<TextBox Header="City"/>
<FormGroup>
<ComboBox Header="State" PlaceholderText="Select" HorizontalAlignment="Stretch"/>
<FormGroup Columns="*,Auto">
<TextBox Header="Zip"/>
<Button Margin="0,28,0,0" Content="..."/>
</FormGroup>
</FormGroup>
<FormGroup Columns="*,Auto">
<TextBox Header="Facility"/>
<Button Margin="0,28,0,0" Content="..."/>
</FormGroup>
<FormGroup>
<TextBox Header="Room"/>
<TextBox Header="Community"/>
</FormGroup>
<FormGroup>
<ComboBox Header="Aware Dx" PlaceholderText="Select" HorizontalAlignment="Stretch"/>
<ComboBox Header="Aware Px" PlaceholderText="Select" HorizontalAlignment="Stretch"/>
</FormGroup>
<TextBox Header="Mapsco #"/>
<TextBox Header="Primary phone" PlaceholderText="123-456-7890"/>
<TextBox Header="Email"/>
</FormSection>
</Form>
Rendered version of markup
Accessibility
State | Action | Narrator |
---|---|---|
User has tabbed to the first field in the form | Focus is set on the first field | Form ‘name’ section ‘headervalue’, section 1 of n textbox, field 1 of n, narrator begins to read the control as it does today |
Form is tabbed through | Tab Button: will advance to next control. Up/Down Arrow: scroll the page up and down |
standard control behavior |
User tabbed to the first control in the following section | Focus is set on the first field of the control | Form ‘name’ section ‘headervalue’ section 2 of n, field 1 of n, narrator begins to read the control as it does today |
Focus is set on action button | Button is focused | Form ‘name’ action 1 of n, narrator reads the control as it does today |
Open Questions
- If we have a Form control, we could then use a data object to generate the markup. Is this something of interest?
- Currently control headers are rendered on the top of the control. Are there scenarios where the control header should render on the side or possibly inline?
- Is a Form control something of interest or would it be best focus our efforts into making Grid more flexible (#see issue 54)?
Issue Analytics
- State:
- Created 5 years ago
- Reactions:22
- Comments:18 (7 by maintainers)
Love this proposal!
One small comment: how would we deal with inconsistent spacing between controls?
Example
In this example, all input controls (ToggleSwitch / NumberBox / ToggleSwitch) have the same Margin: 0, 12, 0, 0.
As you can see this results in a consistency, as a ToggleSwitch and CheckBox make use of additional whitepace. within their controls.
The Figma file for WinUI 2.6 has no guidance for the laying out of Forms or the best practice that is being implemented in the new Settings and Store apps.
I still think this control needs to happen, but it would be a good idea for the design teams to document best practices and redlines for spacing and positioning of these elements.