├── .gitbook
└── assets
│ ├── image (1).png
│ ├── image (10).png
│ ├── image (11).png
│ ├── image (2).png
│ ├── image (3).png
│ ├── image (4).png
│ ├── image (5).png
│ ├── image (6).png
│ ├── image (7).png
│ ├── image (8).png
│ ├── image (9).png
│ └── image.png
├── README.md
├── SUMMARY.md
├── complex-components
├── accordions.md
├── datepickers.md
└── tabs.md
├── faqs.md
├── form-components
├── checkboxes
│ ├── README.md
│ ├── anti-patterns-checkboxes.md
│ └── styling-checkboxes.md
├── input
│ ├── README.md
│ ├── antipatterns-text-fields.md
│ └── styling-input-fields.md
├── radio-buttons
│ ├── README.md
│ ├── antipatterns-radio-buttons.md
│ └── styling-radio-buttons.md
├── select-element.md
└── typeahead.md
├── general-considerations
├── considering-forms.md
└── use-of-aria-live.md
├── global-components
├── buttons
│ ├── README.md
│ └── antipatterns-buttons.md
└── images.md
├── messaging
├── alerts.md
└── modals.md
└── navigation
├── breadcrumbs.md
├── navbar
├── README.md
└── antipatterns-navbars.md
└── pagination
├── README.md
└── styling-pagination.md
/.gitbook/assets/image (1).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MelSumner/ember-component-patterns/c2306d556b58adf77b569f7680513caec0007a6d/.gitbook/assets/image (1).png
--------------------------------------------------------------------------------
/.gitbook/assets/image (10).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MelSumner/ember-component-patterns/c2306d556b58adf77b569f7680513caec0007a6d/.gitbook/assets/image (10).png
--------------------------------------------------------------------------------
/.gitbook/assets/image (11).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MelSumner/ember-component-patterns/c2306d556b58adf77b569f7680513caec0007a6d/.gitbook/assets/image (11).png
--------------------------------------------------------------------------------
/.gitbook/assets/image (2).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MelSumner/ember-component-patterns/c2306d556b58adf77b569f7680513caec0007a6d/.gitbook/assets/image (2).png
--------------------------------------------------------------------------------
/.gitbook/assets/image (3).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MelSumner/ember-component-patterns/c2306d556b58adf77b569f7680513caec0007a6d/.gitbook/assets/image (3).png
--------------------------------------------------------------------------------
/.gitbook/assets/image (4).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MelSumner/ember-component-patterns/c2306d556b58adf77b569f7680513caec0007a6d/.gitbook/assets/image (4).png
--------------------------------------------------------------------------------
/.gitbook/assets/image (5).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MelSumner/ember-component-patterns/c2306d556b58adf77b569f7680513caec0007a6d/.gitbook/assets/image (5).png
--------------------------------------------------------------------------------
/.gitbook/assets/image (6).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MelSumner/ember-component-patterns/c2306d556b58adf77b569f7680513caec0007a6d/.gitbook/assets/image (6).png
--------------------------------------------------------------------------------
/.gitbook/assets/image (7).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MelSumner/ember-component-patterns/c2306d556b58adf77b569f7680513caec0007a6d/.gitbook/assets/image (7).png
--------------------------------------------------------------------------------
/.gitbook/assets/image (8).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MelSumner/ember-component-patterns/c2306d556b58adf77b569f7680513caec0007a6d/.gitbook/assets/image (8).png
--------------------------------------------------------------------------------
/.gitbook/assets/image (9).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MelSumner/ember-component-patterns/c2306d556b58adf77b569f7680513caec0007a6d/.gitbook/assets/image (9).png
--------------------------------------------------------------------------------
/.gitbook/assets/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MelSumner/ember-component-patterns/c2306d556b58adf77b569f7680513caec0007a6d/.gitbook/assets/image.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: >-
3 | This guide intends to be aligned with the idioms and syntax of the Octane
4 | edition of Ember.
5 | ---
6 |
7 | # Ember Component Patterns
8 |
9 | The goal of this guide is to cultivate a set of patterns that are practical and can reasonably be used by any Ember developer in their application. It is intended to be made publicly available with the [preview release of Ember Octane](https://emberjs.com/editions/octane/).
10 |
11 | The component patterns here will, at least initially, be without CSS styling. This is to help clearly delineate form and function. "First, make it useful; then make it beautiful" as the saying goes. When necessary to demonstrate the validity of the approach, however, a sub-section on styling may be added to the pattern if it helps to demonstrate what might otherwise be thought of as impossible.
12 |
13 | As this project matures, the [anti-patterns](https://en.wikipedia.org/wiki/Anti-pattern) will be explored by adding more prose and explains to demonstrate why other options were not chosen, providing both a well-lit path for success and a knowledge base for the shadows.
14 |
15 | What one can obtain from this collection of patterns depends on the reader; however a few potential types of readers, and possible goals, have been kept in mind. Some examples:
16 |
17 | ## For Developers
18 |
19 | * write more technically accurate code
20 | * worry a little bit less about writing code that is not accessible
21 | * have easy-to-reference base requirements for common component patterns
22 | * have confidence in the code you produce
23 |
24 | ## For Designers
25 |
26 | * understand what components really need to have from a functional perspective
27 | * ensure that designs will include the necessary functionality and accessibility
28 | * focus on design within clear technical constraints
29 |
30 | ## For BAs & TPMs
31 |
32 | * reference to help you more accurately know base requirements for the new feature\(s\) you want to add to your project
33 | * confidently plan out projects more accurately by reducing "unknown unknowns"
34 |
35 | {% hint style="info" %}
36 | Feedback is welcome! Visit the [GitHub repository for this project](https://github.com/MelSumner/ember-component-patterns) to raise an issue.
37 | {% endhint %}
38 |
39 |
--------------------------------------------------------------------------------
/SUMMARY.md:
--------------------------------------------------------------------------------
1 | # Table of contents
2 |
3 | * [Ember Component Patterns](README.md)
4 | * [FAQs](faqs.md)
5 |
6 | ## General Considerations
7 |
8 | * [Considering Forms](general-considerations/considering-forms.md)
9 | * [Use of aria-live](general-considerations/use-of-aria-live.md)
10 |
11 | ## Global Components
12 |
13 | * [Buttons](global-components/buttons/README.md)
14 | * [Anti-patterns: Buttons](global-components/buttons/antipatterns-buttons.md)
15 | * [Images](global-components/images.md)
16 |
17 | ## Form Components
18 |
19 | * [Checkboxes](form-components/checkboxes/README.md)
20 | * [Anti-patterns: Checkboxes](form-components/checkboxes/anti-patterns-checkboxes.md)
21 | * [Styling: Checkboxes](form-components/checkboxes/styling-checkboxes.md)
22 | * [Text Fields](form-components/input/README.md)
23 | * [Anti-patterns: Text Fields](form-components/input/antipatterns-text-fields.md)
24 | * [Styling: Text Fields](form-components/input/styling-input-fields.md)
25 | * [Radio Buttons](form-components/radio-buttons/README.md)
26 | * [Anti-patterns: Radio Buttons](form-components/radio-buttons/antipatterns-radio-buttons.md)
27 | * [Styling: Radio Buttons](form-components/radio-buttons/styling-radio-buttons.md)
28 | * [Select Element](form-components/select-element.md)
29 | * [Typeahead/Combobox](form-components/typeahead.md)
30 |
31 | ## Navigation
32 |
33 | * [Navbar](navigation/navbar/README.md)
34 | * [Anti-patterns: Navbar](navigation/navbar/antipatterns-navbars.md)
35 | * [Breadcrumbs](navigation/breadcrumbs.md)
36 | * [Pagination](navigation/pagination/README.md)
37 | * [Styling: Pagination](navigation/pagination/styling-pagination.md)
38 |
39 | ## Messaging
40 |
41 | * [Modal](messaging/modals.md)
42 | * [Alerts](messaging/alerts.md)
43 |
44 | ## Complex Components
45 |
46 | * [Tabs](complex-components/tabs.md)
47 | * [Accordions](complex-components/accordions.md)
48 | * [Datepickers](complex-components/datepickers.md)
49 |
50 |
--------------------------------------------------------------------------------
/complex-components/accordions.md:
--------------------------------------------------------------------------------
1 | # Accordions
2 |
3 | Coming Soon!
4 |
5 |
--------------------------------------------------------------------------------
/complex-components/datepickers.md:
--------------------------------------------------------------------------------
1 | # Datepickers
2 |
3 | Coming Soon!
4 |
5 |
--------------------------------------------------------------------------------
/complex-components/tabs.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: Coming Soon!
3 | ---
4 |
5 | # Tabs
6 |
7 |
--------------------------------------------------------------------------------
/faqs.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: >-
3 | As this project identifies FAQs, they will be posted here. If you have a
4 | question that is not answered here, please ask in the #topic-a11y channel in
5 | the Ember Community Discord chat.
6 | ---
7 |
8 | # FAQs
9 |
10 | ## Why don't you make this into an addon?
11 |
12 | This is not an addon because each app will have different needs and requirements. Instead, this guide is intended to demonstrate best practices so teams can build the components that are right for their project. Additionally, an addon requires maintenance, which is a non-negligible set of work on its own.
13 |
14 | ## Why isn't \(insert component name here\) in this guide?
15 |
16 | It's likely that your favorite component pattern isn't here yet because it hasn't been added yet. Or it's a carousel and those will never be here because they should never be used.
17 |
18 | ## You made a mistake! How do I tell you about it?
19 |
20 | Thanks for catching it! Please file an issue here: [https://github.com/MelSumner/ember-component-patterns/issues](https://github.com/MelSumner/ember-component-patterns/issues).
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/form-components/checkboxes/README.md:
--------------------------------------------------------------------------------
1 | # Checkboxes
2 |
3 | ## Introduction
4 |
5 | Checkboxes are a useful input element when it is desirable to allow users to select more than one option from a short list of options. Checkboxes can have three states: checked, not checked, and indeterminate.
6 |
7 | ### User Expectations
8 |
9 | Users expect the following to be true:
10 |
11 | * it should be possible to navigate via keyboard
12 | * animations should not be linked to functionality; if the user has disabled animations via system preferences, the checkbox should still be usable
13 | * there should be a clear indicator of focus
14 | * clicking on the label for the checkbox should also activate the checkbox itself \(this is done through properly [associating the label](../../general-considerations/considering-forms.md#labels) with the checkbox\)
15 |
16 | ## Part One: Considering Markup
17 |
18 | Sometimes, a single checkbox is desirable. In these cases, a checkbox input only requires an associated label for the input:
19 |
20 | ```markup
21 |
22 |
23 | I confirm that I have read the terms and conditions
24 |
25 | ```
26 |
27 | If the user should be able to select more than one option, a checkbox group should be used. To ensure that all of the checkboxes are associated with the single group, the `name` attribute value should be the same, and the checkbox group should be wrapped with the `` element:
28 |
29 | ```markup
30 |
31 | What kind of jobs are you interested in (select all that apply)?
32 |
33 |
34 | Database Engineer
35 |
36 |
37 |
38 | CSS Engineer
39 |
40 |
41 |
42 | Accessibility Engineer
43 |
44 |
45 |
46 | Platform Engineer
47 |
48 |
49 | ```
50 |
51 | ### Keyboard Support
52 |
53 | | Key | Function |
54 | | :--- | :--- |
55 |
56 |
57 |
58 |
59 |
60 | TAB
61 |
62 |
63 |
64 | Moves keyboard focus among the checkboxes
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | SPACE
76 |
77 |
78 |
79 | Cycles the tri-state checkbox among unchecked, mixed, and checked states.
80 | When the tri-state checkbox is unchecked, all the controlled checkboxes
81 | are unchecked.
82 | When the tri-state checkbox is mixed, the controlled checkboxes return
83 | to the last combination of states they had when the tri-state checkbox
84 | was last mixed or to the default combination of states they had when the
85 | page loaded.
86 | When the tri-state checkbox is checked, all the controlled checkboxes
87 | are checked.
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 | Ember has a checkbox input helper- [https://guides.emberjs.com/release/templates/input-helpers/\#toc\_checkboxes](https://guides.emberjs.com/release/templates/input-helpers/#toc_checkboxes) - but it should not be used in the place of common sense. Use this helper if it is sensible to do so.
96 |
97 | \(More explicit guidance and additional scenarios coming soon\)
98 |
99 | ## Part Three: Abstracting for reuse
100 |
101 | Coming soon!
102 |
103 | ## References
104 |
105 | * [https://www.w3.org/TR/wai-aria-practices-1.1/\#checkbox](https://www.w3.org/TR/wai-aria-practices-1.1/#checkbox)
106 | * [https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox)
107 | * [https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/checkbox\_role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/checkbox_role)
108 | * [https://codepen.io/jensimmons/pen/KKPzxJa](https://codepen.io/jensimmons/pen/KKPzxJa)
109 |
110 | {% hint style="info" %}
111 | Feedback is welcome! Visit the [GitHub repository for this project](https://github.com/MelSumner/ember-component-patterns) to raise an issue.
112 | {% endhint %}
113 |
114 |
--------------------------------------------------------------------------------
/form-components/checkboxes/anti-patterns-checkboxes.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: >-
3 | Anti-patterns produce outcomes that are ineffective because they are not
4 | complete solutions, and as such are counterproductive. Developers are advised
5 | to be aware of anti-patterns and avoid their use.
6 | ---
7 |
8 | # Anti-patterns: Checkboxes
9 |
10 | ## Anti-pattern \#1: heading as checkbox group label
11 |
12 | The use of the header element with a wrapper div around a group of checkboxes may be a tempting approach at first sight.
13 |
14 | Consider this:
15 |
16 | ```markup
17 |
32 | ```
33 |
34 | At first glance, all might seem fine. However, as assistive technology such as a screen reader will not associate the title and the options correctly, this approach should be considered an anti-pattern and should be avoided.
35 |
36 | Instead, use the `` with a `` to successfully contain and associate the checkbox group. It should be remembered that the default styling for these elements can be overridden and should not be considered a blocker for their use.
37 |
38 |
--------------------------------------------------------------------------------
/form-components/checkboxes/styling-checkboxes.md:
--------------------------------------------------------------------------------
1 | # Styling: Checkboxes
2 |
3 | ## Preventing Text Selection
4 |
5 | Occasionally, when a checkbox is activated or deactivated, the input's label text appears selected. If this is bothersome, a little CSS can help:
6 |
7 | ```css
8 | label {
9 | user-select: none;
10 | }
11 | ```
12 |
13 |
--------------------------------------------------------------------------------
/form-components/input/README.md:
--------------------------------------------------------------------------------
1 | # Text Fields
2 |
3 | ## Introduction
4 |
5 | It seems as though most of the practical web is all about input fields. To create a form is simple, some might say; but to create it well requires a depth of knowledge about many different areas of this thing we call web design and development.
6 |
7 | ## Part One: Considering Markup
8 |
9 | {% hint style="danger" %}
10 | The examples in this section have been truncated to focus on accessibility. Simply copying and pasting these code samples will not produce a _complete_ result- some necessary attributes will have been left out.
11 | {% endhint %}
12 |
13 | ### Specification Considerations
14 |
15 | * An input field must have associated `` element. To do this, add the `for` attribute to the`` element. The value of the `for` attribute must be the same as the value for the ` ` element's `id` attribute value.
16 | * When the input field fails to validate, an associated error message should be shown. To do this, add the `aria-describedby` attribute to the ` ` element. The value of the `aria-describedby` attribute must be the same as the value for the `id` of the element that shows the error message \(typically a `` element\).
17 |
18 | ### Input Types
19 |
20 | The `type` attribute value is the most important attribute for the ` ` element. While it is `text` by default, here are some other common input types:
21 |
22 | * email
23 | * file
24 | * number
25 | * password
26 | * search
27 | * tel \(telephone\)
28 | * url
29 |
30 | Other valid type values are `checkbox` and `radiobutton` , but covered in separate topics in this guide. There are other input types that are still valid but are no longer recommended for use, as they have been replaced with better support \(i.e., `input type="submit"` should now be `button type="submit"`\).
31 |
32 | {% hint style="info" %}
33 | Fun Alert! See [https://codepen.io/melsumner/pen/ExYwqxZ](https://codepen.io/melsumner/pen/ExYwqxZ) for valid native HTML input types and some native client-side form validation in action- it may contain a few surprises!
34 | {% endhint %}
35 |
36 | ### Text Input with a label
37 |
38 | ```markup
39 | First Name
40 |
41 | ```
42 |
43 | ### Input Attributes
44 |
45 | Some attributes are required to make the ` ` element work properly. The `name` and `value` attributes both contain data that is submitted to the server when the form submits. It can also be useful in some cases to pre-fill the `value` attribute.
46 |
47 | There are also useful attributes available for use with the ` ` element that developers should be aware of, as this prevents unnecessary JavaScript. Some of these attributes provide useful client-side form validation.
48 |
49 | {% hint style="danger" %}
50 | Warning: client-side validation should _never_ be considered an appropriate substitution for server-side validation. Client-side validation can quickly and easily provide user feedback. Server-side validation is more intrusive and dependent on factors that can affect performance, and as such it is recommended to use both to obtain balance. Server-side validation should _always_ be used to protect the application against those with malicious intent.
51 | {% endhint %}
52 |
53 | `required`
54 | The presence of the `required` attribute will indicate that the input must be filled out by the user. It should be noted that only the attribute itself is necessary. To indicate that it is not necessary, remove the attribute completely.
55 | Example:
56 |
57 | ```markup
58 | First Name
59 |
60 | ```
61 |
62 | `disabled`
63 | The presence of the `disabled` attribute will prevent the user from interacting with this element, and the `value` of this field will not be submitted to the server with the rest of the form data. This is useful in cases where it has been determined that the specific end user does not meet the criteria to fill out this specific form field. Disabled elements are also not required to pass [color contrast standards](https://www.w3.org/WAI/WCAG21/quickref/?showtechniques=143#contrast-minimum) as related to WCAG success criteria. Finally, it should be noted that only the presence of the attribute is required.
64 |
65 | ```markup
66 | First Name
67 |
68 | ```
69 |
70 | 
71 |
72 | It should be noted that browsers will apply default styles to input fields marked as `disabled`; however this can be overridden with custom CSS if desired.
73 |
74 | `readonly`
75 | The presence of the `readonly` attribute will allow the user to view the current value, but will not allow the user to change it. This is different from `disabled` in that the value for the input field marked with `readonly` will be sent to the server when the form is submitted. Again, it should be noted that only the presence of the attribute is required. Example:
76 |
77 | ```markup
78 | First Name
79 |
80 | ```
81 |
82 | 
83 |
84 | It should be noted that browsers will apply default styles to input fields marked as `readonly`; however this can be overridden with custom CSS if desired.
85 |
86 | `autocomplete`
87 | Input fields are set to `autocomplete="true"` by default. This will allow some browsers \(that provide the option\) to automatically fill in information saved by the user to the browser itself. In instances where this is not desired behavior, setting `autocomplete="false"` will turn this option off.
88 |
89 | It is an elevated experience for users with assistive technology to include this attribute in form fields, especially where the type of questions being asked in a form are atypical of the type of autocomplete data \(such as name and address\) that a user's browser may have stored. Example:
90 |
91 | ```markup
92 | Where is your favorite place to camp?
93 |
94 | ```
95 |
96 | `pattern`
97 | Setting the pattern attribute value will provide client-side form validation for the user. The `pattern` attribute expects a Regular Expression as its value. Example:
98 |
99 | ```markup
100 | Do you prefer sunny weather or cloudy weather?
101 |
102 | ```
103 |
104 | Using the `:invalid` and `:valid` pseudo selectors in CSS can indicate that the element is invalid:
105 |
106 | 
107 |
108 | {% hint style="info" %}
109 | Note: the `email` and `url` input types do not require a `pattern` attribute, because they already provide their own form of pattern validation. Additionally, `pattern` is ignored if the input type is `number` AND the browser supports the type. For browsers that do not support the `number` type, the `pattern` attribute can be used to provide a graceful fallback.
110 | {% endhint %}
111 |
112 | `min-length` and `max-length`
113 | When it is useful to control the number of characters put into the field, `min-length` and `max-length` attributes can be used. Some traditional databases have a maximum character length that they can accept, so it is prudent to be aware of the limitations of where the form data is heading.
114 |
115 | It is also appropriate to be aware that non-traditional data may exist, and plan for those use cases. For more reading on this subject, search for "_names that break websites_", or read [People's Names that Break Websites](https://css-tricks.com/peoples-names-break-websites/).
116 |
117 | `placeholder`
118 | Sometimes it is useful to show the user what kind of formatting is expected. In these cases, the `placeholder` attribute can be useful. Example:
119 |
120 | ```markup
121 | First Name
122 |
123 | ```
124 |
125 | 
126 |
127 | {% hint style="danger" %}
128 | Warning! It is not acceptable to use a `placeholder` instead of an associated `` element. Machine-readable code requires a `` element to be associated with each input field. See the styling sub-section for ideas on styling.
129 | {% endhint %}
130 |
131 | There are some other attributes that exist but are not commonly used today, such as `size` and `width` as these things are more appropriately managed with CSS.
132 |
133 | ### Input with associated error message
134 |
135 | If additional guidance is desired, an error message that is associated with the input field can be added.
136 | This is what the simplified markup for an input with an associated error message could look like:
137 |
138 | ```markup
139 | Email
140 |
142 |
143 | Please enter a valid email address.
144 |
145 | ```
146 |
147 | Note the `aria-describedby` attribute on the `input` field, whose value matches the `id` of the element that contains the error message.
148 |
149 | ## Part Two: Creating the Ember Component\(s\)
150 |
151 | First, the appropriate requirements should be gathered.
152 |
153 | Next, the component should be generated:
154 |
155 | ```bash
156 | ember generate component input-text -gc
157 | ```
158 |
159 | This will create three files and put them in the correct location:
160 |
161 | * app/components/input-text.hbs
162 | * app/components/input-text.js
163 | * tests/integration/components/input-text-test.js
164 |
165 | In **app/components/input-text.hbs**, the component markup can be set up and the places where dynamic functionality is needed can be indicated.
166 |
167 | So this markup:
168 |
169 | ```markup
170 |
171 | Label Text
172 |
177 |
178 | ```
179 |
180 | Becomes this component template:
181 |
182 | ```markup
183 |
184 | {{@inputLabelText}}
185 |
190 |
191 | ```
192 |
193 | In **app/components/input-text.js**, the input `id` will need to be generated so the label element can access it. While there are a few different ways to accomplish this, the existing `guidFor` function will serve nicely:
194 |
195 | ```javascript
196 | import Component from '@glimmer/component';
197 | import { guidFor } from '@ember/object/internals';
198 |
199 | export default class InputTextComponent extends Component {
200 | inputId = 'textInput-' + guidFor(this);
201 | }
202 | ```
203 |
204 | Then, the component can be used in the view or page template:
205 |
206 | ```markup
207 |
208 | ```
209 |
210 | ### Considering Attributes
211 |
212 | Any form input planning should include considerations for which attributes should be supported. At the bare minimum, `required`, `disabled`, and `readonly` should be considered.
213 |
214 | Updated app/components/input-text.hbs to include these attributes:
215 |
216 | ```markup
217 |
218 | {{@inputLabelText}}
219 |
227 |
228 | ```
229 |
230 | Then they can be added or removed from the view/page template when the component is used. For example, if the disabled state was desired for an input field:
231 |
232 | ```markup
233 |
234 | ```
235 |
236 | Note that if the attribute needs a false state, it cannot merely change to `@isDisabled="false"` \(that will still rendered the `disabled` attribute\) - it must be removed completely:
237 |
238 | ```markup
239 |
240 | ```
241 |
242 | ### Ember's Input Helper
243 |
244 | For smaller applications, it may be more desirable to use Ember's input helper instead of creating a component. In these cases, can be written directly to the view/page template:
245 |
246 | ```markup
247 |
248 | Email
249 |
250 |
251 | ```
252 |
253 | The `label` element \(and the `for` attribute\) has to be manually applied, and the `id` attribute added to the Input helper component. To read more about Ember's Input helper, visit the official Ember.js guides: [https://guides.emberjs.com/release/templates/input-helpers/](https://guides.emberjs.com/release/templates/input-helpers/).
254 |
255 | ### Conclusion
256 |
257 | In these Ember Component examples, the components have been closely scoped for a specific type of text input and closely related use cases. Further customization could be desired, so it is recommended to consider the balance of use cases. By providing separate components for different input types, it can lower the developer's cognitive burden as there will be fewer options to remember within one specific component.
258 |
259 | On the other hand, some teams may find it more useful to have a "kitchen sink" style of input component, that accepts many different types. It is strongly recommended to have a team discussion in order to determine which is the right approach for the specific project.
260 |
261 | ## Part Three: Abstractions for Reuse
262 |
263 | coming soon!
264 |
265 | ## References
266 |
267 | * [https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label)
268 | * [https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input)
269 | * [https://api.emberjs.com/ember/release/functions/@ember%2Fobject%2Finternals/guidFor](https://api.emberjs.com/ember/release/functions/@ember%2Fobject%2Finternals/guidFor)
270 |
271 | {% hint style="info" %}
272 | Feedback is welcome! Visit the [GitHub repository for this project](https://github.com/MelSumner/ember-component-patterns) to raise an issue.
273 | {% endhint %}
274 |
275 |
--------------------------------------------------------------------------------
/form-components/input/antipatterns-text-fields.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: >-
3 | Anti-patterns produce outcomes that are ineffective because they are not
4 | complete solutions, and as such are counterproductive. Developers are advised
5 | to be aware of anti-patterns and avoid their use.
6 | ---
7 |
8 | # Anti-patterns: Text Fields
9 |
10 | ## Anti-pattern \#1: Placeholder as a label substitute
11 |
12 | It is common for developers who are fully sighted to forget that many different kinds of people use the internet- including people with no vision. It is vital that all input fields have associated label elements.
13 |
14 | Anti-pattern example to **avoid**:
15 |
16 | ```markup
17 |
18 |
19 |
20 | ```
21 |
22 | ## Anti-pattern \#2: Input fields that automatically do...anything.
23 |
24 | ### Automatically submitting an input/form
25 |
26 | To avoid surprising the user \(in a not good way\), input fields should only submit information when the "submit" button has been pressed/clicked on by the user.
27 |
28 | ### Automatically update information in other places
29 |
30 | Any page updates should come only as a result of an explicit interaction from the user, and any information on the page that will receive this updated data should be marked with aria-live. See the [aria-live guide](../../general-considerations/use-of-aria-live.md) for information on how to use this attribute.
31 |
32 |
--------------------------------------------------------------------------------
/form-components/input/styling-input-fields.md:
--------------------------------------------------------------------------------
1 | # Styling: Text Fields
2 |
3 | ## Visually Hidden Labels
4 |
5 | This is the most common need for `` elements- how to make it available to other machines \(such as screen readers\) but visually hidden for design purposes. While it should be noted that a label helps to provide clarity for all users, there are some ways to make this happen.
6 |
7 | The most common approach was popularized by markup frameworks like [Bootstrap](https://getbootstrap.com/), and uses .sr-only \(screen-reader only\) and .sr-only-focusable \(screen-reader only, focusable elements\).
8 |
9 | `.sr-only`
10 | Content which should be visually hidden, but remain accessible to assistive technologies such as screen readers, can be styled using classes such as the popular `.sr-only` class. This can be useful in situations where additional visual information or cues \(such as meaning denoted through the use of color\) need to also be conveyed to non-visual users.
11 |
12 | CSS:
13 |
14 | ```css
15 | .sr-only {
16 | position: absolute;
17 | width: 1px;
18 | height: 1px;
19 | padding: 0;
20 | overflow: hidden;
21 | clip: rect(0, 0, 0, 0);
22 | white-space: nowrap;
23 | border: 0;
24 | }
25 | ```
26 |
27 | `.sr-only-focusable`
28 | For visually hidden interactive controls, such as traditional “skip” links, `.sr-only` can be combined with the `.sr-only-focusable` class. This will ensure that the control becomes visible once focused.
29 |
30 | SCSS:
31 |
32 | ```css
33 | .sr-only-focusable {
34 | &:active,
35 | &:focus {
36 | position: static;
37 | width: auto;
38 | height: auto;
39 | overflow: visible;
40 | clip: auto;
41 | white-space: normal;
42 | }
43 | }
44 | ```
45 |
46 |
--------------------------------------------------------------------------------
/form-components/radio-buttons/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: The radio button input. To be used with Ember 3.13+
3 | ---
4 |
5 | # Radio Buttons
6 |
7 | ## Introduction
8 |
9 | Although the radio button input is a simple component, it is one that is very easily constructed in a way that is detrimental to not only an application's performance but also the experience for users with assistive technology. This guide will examine successful patterns for development, and where possible, illuminate pitfalls that authors should avoid in order to successfully deliver a performant and accessible component.
10 |
11 | It should **not** be assumed that a component pattern that _appears_ polished is technically sound. For example, consider the radio button offered by Material Design:
12 |
13 | ```markup
14 | // don't do this
15 |
26 | Chicago
27 | ```
28 |
29 | Just to make this **one** radio button in Material Design, the following would be needed:
30 |
31 | | HTML | CSS | JavaScript |
32 | | :--- | :--- | :--- |
33 | | 6 elements | 66 selectors | 2,374 lines \(unminified\) |
34 | | 9 attributes | 141 properties | 30k minified |
35 | | DOM depth of 3 | 10k minified | |
36 |
37 | Since any app will likely need more than just one radio button, and the above is far too obtuse for use in modern applications, considerations should be made for how the appropriate markup can be achieved in a much more efficient way.
38 |
39 | For additional patterns to avoid, see the [anti-patterns page](antipatterns-radio-buttons.md).
40 |
41 | ## Part One: Considering Markup
42 |
43 | Now consider this markup which uses semantic HTML to obtain the same effect:
44 |
45 | ```markup
46 |
47 |
52 | Chicago
53 |
54 | ```
55 |
56 | This is all that is needed.
57 |
58 | 1. the class on the wrapping div will be the styling hook
59 | 2. the ` ` element requires the `type` of `radio` to render a radio button
60 | 3. the `id` is required to be associated with the `` element \(essential for machine-readable code\)
61 | 4. the `name` is required to group radio buttons together \(allowing for browser defaults like arrow key navigation
62 | 5. the `value` is necessary to indicate the information that should be returned to the database
63 | 6. the `label` requires the `for` attribute that is the value of the ` ` element's `id` attribute \(see \#3\)
64 |
65 | If extra styling on the radio button is desired, the [pseudo elements in CSS](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements), rather than extra markup in the DOM, should be used. To see examples of how this could be done, visit the [Styling: Radio Buttons page](styling-radio-buttons.md).
66 |
67 | Of course, there are more options that will need to be build into this pattern, so consideration for those should be planned for next, as it is advised to plan out the component before building it.
68 |
69 | ### Considering Attributes & Properties
70 |
71 | First, consider the HTML attributes that might need to be added to this component \(in addition to the ones that were already indicated in the markup sample\). It should be observed that the boolean attributes in HTML work a little differently than they do in JS. For these attributes, they must be omitted all together to indicate a `false` value. If `true`, the attribute name is only present. Consider these examples for a disabled radio button:
72 |
73 | Correct:
74 |
75 | ```markup
76 |
77 | ```
78 |
79 | Incorrect:
80 |
81 | ```markup
82 |
83 | ```
84 |
85 | Additionally, consideration for the difference between `disabled` and `readonly` is important- when a form is submitted, information marked as `readonly` **will** be sent to the server upon submit, whereas information marked `disabled` **will not**.
86 |
87 | ### Radio Group
88 |
89 | A radio button is, by nature, not going to be used alone \(in those instances, a checkbox is the correct choice\). It is reasonable, then, to consider how all the parts would work together in the whole. Here is an example that could be used to give a user an opportunity to indicate contact method preference:
90 |
91 | ```markup
92 |
93 | Preferred Location
94 |
95 |
100 | Austin
101 |
102 |
103 |
108 | Boston
109 |
110 |
111 |
116 | Portland
117 |
118 |
119 | ```
120 |
121 | The power of CSS makes it possible to use completely semantic markup and maintaining a separation of concerns where design is concerned- this means markup is not needed to implement the desired styling.
122 |
123 | {% hint style="info" %}
124 | Note: it is common to have an option pre-selected for users. An agreeable default selection can lower the amount of time the user spends filling out a form, which is always a bonus! To increase user happiness, a plan should be devised to revisit details \(such as default selection\) once an appropriate amount of data has been gathered. Observe which option users tend to choose the most and make that the default option, for extra delight!
125 | {% endhint %}
126 |
127 | Now that well-crafted markup exists, it can be converted into an Ember Component.
128 |
129 | ## Part Two: Creating the Ember Component
130 |
131 | Generate the component:
132 |
133 | ```bash
134 | $ ember generate component radio-group -gc
135 | ```
136 |
137 | In the generated `radio-group.hbs` file, add this markup:
138 |
139 | ```markup
140 |
141 | {{@title}}
142 | {{#each this.cityNames as |cityName|}}
143 |
144 |
151 | {{cityName}}
152 |
153 | {{/each}}
154 |
155 | ```
156 |
157 | It is possible that the `value` attribute's value may be different from the `` element's contents, but in most cases, it's better that it match. If slight adjustments are needed \(i.e., capitalization\), a helper should be used.
158 |
159 | For the purpose of this example, the assumption is made that `cityNames` is defined in the `radio-group.js` file:
160 |
161 | ```javascript
162 | import Component from '@glimmer/component';
163 |
164 | export default class RadioGroupComponent extends Component {
165 | cityNames = [
166 | { city: 'austin' },
167 | { city: 'boston' },
168 | { city: 'portland' }
169 | ];
170 | }
171 | ```
172 |
173 | The component can then be added to the page template:
174 |
175 | ```markup
176 |
181 | ```
182 |
183 | ## Part Three: Abstractions for reuse
184 |
185 | Coming Soon
186 |
187 | ### Additional Considerations
188 |
189 | If it is desirable to allow some attributes to be changed when the component is placed into the template, the specific placement of `...attributes` will allow the author to indicate which attributes can be changed and which cannot. To learn more about this, visit [https://octane-guides-preview.emberjs.com/release/upgrading/editions/\#toc\_attributes](https://octane-guides-preview.emberjs.com/release/upgrading/editions/#toc_attributes).
190 |
191 | ## References
192 |
193 | 1. [Excessive DOM Size](https://developers.google.com/web/tools/lighthouse/audits/dom-size) \(Audit reference, performance\)
194 | 2. [MDN Reference: Radio Buttons](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/radio)
195 | 3. Talk: [The Intersection of Performance and Accessibility](https://noti.st/ericwbailey/Yfyaxa)
196 | 4. [HTML Standard: Boolean Attributes](https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#boolean-attributes)
197 | 5. [Pseudo Elements in CSS](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements)
198 | 6. [Styling: Radio Buttons](styling-radio-buttons.md)
199 |
200 | {% hint style="info" %}
201 | Feedback is welcome! Visit the [GitHub repository for this project](https://github.com/MelSumner/ember-component-patterns) to raise an issue.
202 | {% endhint %}
203 |
204 |
--------------------------------------------------------------------------------
/form-components/radio-buttons/antipatterns-radio-buttons.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: >-
3 | Anti-patterns produce outcomes that are ineffective because they are not
4 | complete solutions, and as such are counterproductive. Developers are advised
5 | to be aware of anti-patterns and avoid their use.
6 | ---
7 |
8 | # Anti-patterns: Radio Buttons
9 |
10 | When considering how to craft a useful radio button group component, it is also necessary to consider what _not_ to do. If any Ember addon is evaluated for use, it is not only the Ember code itself that needs to be evaluated, but the output to the browser itself that should be evaluated.
11 |
12 | ## Anti-pattern \#1: divs and spans
13 |
14 | Consider this markup:
15 |
16 | ```markup
17 |
31 | ```
32 |
33 | This should be considered unacceptable for the following reasons:
34 |
35 | 1. there is no `` element associated with the ` ` element
36 | 2. the radio buttons are not associated as a group with the use of the `name` attribute.
37 |
38 | ## Anti-pattern \#2 - label first
39 |
40 | Consider this markup:
41 |
42 | ```markup
43 | True
44 |
45 | ```
46 |
47 | This would put the label first, and the radio button second. This should be considered an anti-pattern because it is not placing the radio button where the user has been trained to expect it, i.e., to the left of the label.
48 |
49 | {% hint style="info" %}
50 | Have an anti-pattern to submit? Open an issue \(and include the sample code\) on this project's [GitHub repository](https://github.com/MelSumner/ember-component-patterns).
51 | {% endhint %}
52 |
53 |
--------------------------------------------------------------------------------
/form-components/radio-buttons/styling-radio-buttons.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: >-
3 | Using the semantic markup as described in primary pattern page, here is how
4 | more customized styles can be achieved without adding additional undesired
5 | elements to the HTML.
6 | ---
7 |
8 | # Styling: Radio Buttons
9 |
10 | To style the label of the default selected radio button:
11 |
12 | ```css
13 | input[type="radio"]:default + label {
14 | /* styles here */
15 | }
16 | ```
17 |
18 | To style the label of the currently selected radio button:
19 |
20 | ```css
21 | input[type="radio"]:checked + label {
22 | /* styles here */
23 | }
24 | ```
25 |
26 | Sometimes a custom style is desired. To achieve this while ensuring that the radio button markup remains appropriately available to screen readers, the radio button should be visually hidden while set up to be positioned over the styled radio button replacement.
27 |
28 | The `label` element's `:before` and `:after` pseudo elements can be used to produce the custom styling that may be desired. In this instance, the `:before` pseudo element will act as the outer border of the radio button; the `:after` pseudo element as the visual indicator for the `checked` state.
29 |
30 | ```css
31 | .radio-button {
32 | position: relative;
33 | }
34 |
35 | .radio-button > input[type="radio"] {
36 | -moz-appearance: none;
37 | -webkit-appearance: none;
38 | appearance: none;
39 | background: none;
40 | opacity: .00001;
41 | z-index: 2;
42 | }
43 |
44 | .radio-button > label {
45 | display: inline-block;
46 | /* set padding as desired */
47 | }
48 |
49 |
50 | .radio-button > input[type="radio"],
51 | .radio-button > label:before,
52 | .radio-button > label:after {
53 | position: absolute;
54 | /* set other properties as desired */
55 | }
56 |
57 | .radio-button > input[type="radio"],
58 | .radio-button > label:before,
59 | .radio-button > label:after {
60 | border-radius: 100%;
61 | content: " ";
62 | }
63 |
64 | .radio-button > label:after {
65 | /* set properties (such as border-color) as desired */
66 | }
67 |
68 | .radio-button > label:before {
69 | border-color: transparent;
70 | /* set other properties (such as box-shadow) as desired */
71 | }
72 |
73 | .radio-button > input:checked ~ label:before {
74 | border-color: transparent;
75 | /* set other properties (such as box-shadow) as desired */
76 | }
77 |
78 | .radio-button > input:focus ~ label:before {
79 | border-color: transparent;
80 | }
81 |
82 | .radio-button > input:checked ~ label:after {
83 | /* set properties (such as border-color/width & box-shadow) as desired */
84 | }
85 |
86 | ```
87 |
88 | Finally, it is important to consider high-contrast settings. Here is a media query \(and sample code\) that could be used for that purpose:
89 |
90 | ```css
91 | @media screen and (-ms-high-contrast: active) {
92 | .radio-button > input:checked ~ label:before {
93 | background: window;
94 | border: 6px solid buttonface;
95 | box-shadow: none;
96 | }
97 | }
98 | ```
99 |
100 | To see some opinionated styles in action, visit the [CodePen sample](https://codepen.io/melsumner/pen/9333b9017df850d9fbdd0dd8f805741a) specifically created for this purpose. Here's a sneak peek:
101 |
102 | 
103 |
104 |
--------------------------------------------------------------------------------
/form-components/select-element.md:
--------------------------------------------------------------------------------
1 | # Select Element
2 |
3 | ## Introduction
4 |
5 | As a general rule, the `` element should be used \(instead of radio buttons\) if any of the following cases are true:
6 |
7 | 1. there are more than 5-7 choices
8 | 2. there are a large number of _familiar_ options available \(there is no need to be able to compare the options\)
9 | 3. the default choice is the recommended choice
10 |
11 | It is a common misconception that the select element is not enough for web development. While there are some constraints on styling, the select element serves a specific purpose and should be used in those cases. It is ill-advised to disregard the select component entirely simply because it does not support more complex use cases out of the box. Instead, additional components should be created for complex functionality.
12 |
13 | ## Part One: Considering Markup
14 |
15 | The select element markup is rather straight-forward- all of the options are grouped together in one list, or option groups are indicated.
16 |
17 | ```markup
18 |
19 | Select your preferred color:
20 |
21 | Red
22 | Orange
23 | Yellow
24 | Green
25 | Blue
26 | Indigo
27 | Violet
28 |
29 |
30 | ```
31 |
32 | Benefits provided by the semantic html element:
33 |
34 | * if a user clicks on the label, the focus will automatically go to the select element
35 | * keyboard navigation is built in:
36 | * the `ENTER` key will toggle the dropdown open/closed
37 | * the arrow keys will navigate up and down the list
38 | * the `ESC` key will close the dropdown
39 | * assistive technology \(like screen readers\) will already understand what this code is meant to do
40 |
41 | If grouping is desired, the `` markup can be used:
42 |
43 | ```markup
44 |
45 | Select your preferred activity:
46 |
47 |
48 | Sewing
49 | Painting
50 | Baking
51 |
52 |
53 | Climbing
54 | Hiking
55 | Horseback Riding
56 |
57 |
58 |
59 | ```
60 |
61 | While multiple selections can be allowed through the use of the `multiple` attribute -- most browsers will show a scrolling list box instead of a single line dropdown -- it should be noted that use of the `multiple` attribute is not generally advised, as it can be a confusing interface for users.
62 |
63 | ## Part Two: Creating the Ember Component
64 |
65 | The component should be generated \(via ember-cli\):
66 |
67 | ```bash
68 | ember generate component input-select -gc
69 | ```
70 |
71 | This will create three files and put them in the correct location:
72 |
73 | * app/components/input-select.hbs
74 | * app/components/input-select.js
75 | * tests/integration/components/input-select-test.js
76 |
77 | In **app/components/input-select.hbs**, the component markup can be set up and the places where dynamic functionality is needed can be indicated.
78 |
79 | So this markup:
80 |
81 | ```markup
82 |
83 | Label Text
84 |
85 | Option One
86 | Option Two
87 | Option Three
88 |
89 |
90 | ```
91 |
92 | Becomes this component template:
93 |
94 | ```markup
95 |
96 | {{this.selectLabelText}}
97 |
98 | {{#each this.selectOptions as |selectOption|}}
99 | {{selectOption}}
100 | {{/each}}
101 |
102 |
103 | ```
104 |
105 | In **app/components/input-select.js**, the select `id` will need to be generated so the label element can access it. While there are a few different ways to accomplish this, the existing `guidFor` function will serve nicely:
106 |
107 | ```javascript
108 | import Component from '@glimmer/component';
109 | import { guidFor } from '@ember/object/internals';
110 |
111 | export default class InputSelectComponent extends Component {
112 | selectId = 'select-' + guidFor(this);
113 | selectedOptions = ['optionOne', 'optionTwo', 'optionThree'];
114 | selectLabelText = 'Option List';
115 | selectName = 'optionList';
116 | }
117 | ```
118 |
119 | Then, the component can be used in the view or page template:
120 |
121 | ```markup
122 |
123 | ```
124 |
125 | ### Considering Attributes
126 |
127 | Any form input planning should include considerations for which attributes should be supported. At the bare minimum, `required`, `disabled`, and `readonly` should be considered.
128 |
129 | ## Part Three: Abstracting for Reuse
130 |
131 | To create something more flexible, allow for definition upon invocation:
132 |
133 | ### Template
134 |
135 | ```markup
136 |
137 | {{@selectLabelText}}
138 |
139 | {{#each @selectOptions as |selectOption|}}
140 | {{selectOption}}
141 | {{/each}}
142 |
143 |
144 | ```
145 |
146 | ### Component
147 |
148 | ```javascript
149 | import Component from '@glimmer/component';
150 | import { guidFor } from '@ember/object/internals';
151 |
152 | export default class InputSelectComponent extends Component {
153 | selectId = 'select-' + guidFor(this);
154 | }
155 | ```
156 |
157 | ### Invocation
158 |
159 | ```markup
160 |
165 | ```
166 |
167 | ## References
168 |
169 | * [https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement)
170 | * [https://blog.prototypr.io/7-rules-of-using-radio-buttons-vs-drop-down-menus-fddf50d312d1](https://blog.prototypr.io/7-rules-of-using-radio-buttons-vs-drop-down-menus-fddf50d312d1)
171 | * Listbox Keyboard Interaction: [https://www.w3.org/TR/wai-aria-practices/\#listbox\_kbd\_interaction](https://www.w3.org/TR/wai-aria-practices/#listbox_kbd_interaction)
172 | * Styled Single Selects: [https://scottaohara.github.io/a11y\_styled\_form\_controls/src/select/](https://scottaohara.github.io/a11y_styled_form_controls/src/select/)
173 |
174 | {% hint style="info" %}
175 | Feedback is welcome! Visit the [GitHub repository for this project](https://github.com/MelSumner/ember-component-patterns) to raise an issue.
176 | {% endhint %}
177 |
178 |
--------------------------------------------------------------------------------
/form-components/typeahead.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: WIP
3 | ---
4 |
5 | # Typeahead/Combobox
6 |
7 | ## Introduction
8 |
9 | The typeahead or combobox component is usually similar to a textbox where users can type ahead to select an option, or sometimes even type arbitrary text as a new item to add to the list.
10 |
11 | It is a combination of a single line input field with a popup, typically a listbox.
12 |
13 | Because this field is editable and is typically used for autocomplete behavior \(to help the user find things more quickly\), the `aria-autocomplete` attribute should be used.
14 |
15 | There are four forms of autocomplete that are acceptable:
16 |
17 | 1. **no autocomplete**: the suggested values that appear are the same, no matter what the user has typed in the textbox.
18 | 2. **list autocomplete with manual selection**: the suggested values that appear contain values that complete or otherwise logically correspond with the characters that the user has typed into the textbox. However, the characters that the user has typed will be the value of the textbox unless the user manually selects a value displayed in the popup.
19 | 3. **list autocomplete with automatic selection**: the suggested values that appear, contain values that complete \(or otherwise logically correspond with\) the characters that the user has typed into the textbox, and the first suggestion is automatically highlighted as selected. The automatically selected suggestion becomes the value of the textbox when the combobox loses focus, unless the user manually chooses a different suggestion.
20 | 4. **list with inline autocomplete**: after the user types a certain number of characters, suggestions display inline after the input cursor in the textbox \(known as a completion string\). The suggested completion string should update as the user types additional characters.
21 |
22 | ## Part One: Considering Markup
23 |
24 | ```markup
25 |
39 | ```
40 |
41 | ### Keyboard Interactions
42 |
43 | | Key | Action |
44 | | :--- | :--- |
45 | | arrow keys | cycle through the auto-suggestions and input field |
46 | | `ESC` | close the listbox \(if open\) |
47 | | `ENTER` | select the currently focused auto-suggestion item and close the listbox |
48 | | `TAB` | select the currently focused auto-suggestion, close the menu, and move focus to the next focusable element |
49 |
50 | The keyboard interactions are important here, because there is definitely the risk of introducing serious keyboard navigation flaws -- the focus could escape the listbox and continue down the page, or conversely, the focus could get trapped inside of the listbox and never allow the user to escape out of the list.
51 |
52 | ## Part Two: Creating the Ember Component
53 |
54 | ### Generate the component
55 |
56 | ```text
57 | ember generate component typeahead -gc
58 | ```
59 |
60 | Three files will be created:
61 |
62 | * app/components/typeahead.js
63 | * app/components/typeahead.hbs
64 | * tests/integration/components/typeahead-test.js
65 |
66 | A few styles will need to be added, but the method to do so will depend on the overall CSS approach for the application.
67 |
68 | ### Add template code
69 |
70 | In the `typeahead.hbs` file, the template code can be added:
71 |
72 | ```markup
73 |
100 | ```
101 |
102 | //TODO abstract/add show/hide
103 |
104 | ### Component JS
105 |
106 | From the template code above, it is clear that there are multiple associations happening for accessibility reasons. Using the same approach as for other form components, unique IDs can be generated:
107 |
108 | ```javascript
109 | import Component from '@glimmer/component';
110 | import { guidFor } from '@ember/object/internals';
111 |
112 | export default class TypeaheadComponent extends Component {
113 | inputId = 'typeaheadInput-' + guidFor(this);
114 | comboboxId = 'combobox-' + guidFor(this);
115 | listboxId = 'listbox-' + guidFor(this);
116 | labelId = 'label-' + guidFor(this);
117 |
118 | listboxOptions = [
119 | // options here
120 | ];
121 | }
122 | ```
123 |
124 | //TODO add keyboard support
125 |
126 | ### Using the Component
127 |
128 | The component is now ready to be used in the page or form template file:
129 |
130 | ```markup
131 |
132 | ```
133 |
134 | ## Part Three: Abstracting for Reuse
135 |
136 | coming soon!
137 |
138 | ## References
139 |
140 | * WAI-ARIA Authoring Practices 1.1 - Combo Box - [https://www.w3.org/TR/wai-aria-practices/\#combobox](https://www.w3.org/TR/wai-aria-practices/#combobox)
141 |
142 | {% hint style="info" %}
143 | Feedback is welcome! Visit the [GitHub repository for this project](https://github.com/MelSumner/ember-component-patterns) to raise an issue.
144 | {% endhint %}
145 |
146 |
--------------------------------------------------------------------------------
/general-considerations/considering-forms.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: >-
3 | This page contains some general knowledge that may be helpful to review before
4 | looking at the form component guides.
5 | ---
6 |
7 | # Considering Forms
8 |
9 | ## Labels
10 |
11 | All form inputs are required to have an associated `` element. The `` element should not be used in any other context.
12 |
13 | To associate a form input and a label, the value of the `for` attribute in the <label> element should match the value of the input's `id` attribute. See this truncated example:
14 |
15 | ```markup
16 | Label Text
17 |
18 | ```
19 |
20 | It should then be considered how to generate such a thing, since IDs must be unique. There are two approaches for Ember applications:
21 |
22 | ### UUID
23 |
24 | One approach is to create a [`uuid`](https://en.wikipedia.org/wiki/Universally_unique_identifier) as a variable within the component, and increment the value as needed. If this approach is used, care must be taken to ensure that the values generated are valid values as per the HTML specification:
25 |
26 | * _**must**_ begin with a letter \(\[A-Za-z\]\)
27 | * may be followed by any number of letters, digits \(\[0-9\]\), hyphens \("-"\), underscores \("\_"\), colons \(":"\), and periods \("."\)
28 |
29 | ### GUIDFOR
30 |
31 | Ember has [`guidFor`](https://api.emberjs.com/ember/release/functions/@ember%2Fobject%2Finternals/guidFor) which returns a unique ID for the object. If the object does not yet have a guid, one will be assigned to it, and it can be called on any object, including DOM element objects.
32 |
33 | {% hint style="info" %}
34 | While it is also valid to wrap the input in a `` element and avoid using the `for` attribute entirely, this approach is not advised because it limits the designs that can be used. When considering how the code is written, it is essential to consider flexibility for styling as an integral part of the approach. Set your future up for success!
35 | {% endhint %}
36 |
37 |
--------------------------------------------------------------------------------
/general-considerations/use-of-aria-live.md:
--------------------------------------------------------------------------------
1 | # Use of aria-live
2 |
3 | The `aria-live` attribute should be used with _**extreme**_ caution, as it can provide an incredibly poor user experience for users with assistive technology.
4 |
5 | Because the `aria-live` attribute can be used on any HTML element, and effects _all_ child elements of the element marked with the attribute, a thorough understanding of how this role works and when to use it is especially necessary for competent software engineers who build web-based solutions.
6 |
7 | The `aria-live` attribute can have a few different values \(`POLITENESS_SETTING`\): `off`, `polite`, and `assertive`.
8 |
9 | ## Politeness Setting: Off
10 |
11 | > Assistive technologies should not announce updates unless the assistive technology is currently focused on that region.
12 |
13 | Regions which contain information that will receive updates but are not critical for users to know about immediately can be marked with `aria-live="off"`. Once that region has \(user-driven\) focus, the updates will be made known.
14 |
15 | ## Politeness Setting: Polite
16 |
17 | > Assistive technologies should announce updates at the next graceful opportunity \(e.g., end of the current sentence\).
18 |
19 | Regions that contain warning notifications that users _may_ need to know can be marked with `aria-live="polite"`.
20 |
21 | ## Politeness Setting: Assertive
22 |
23 | > Assistive technologies should announce updates immediately.
24 |
25 | Regions that contain urgent alerts or notifications \(such as error alerts\) that are imperative for users to know immediately should use `aria-live=assertive`.
26 |
27 | ## Pitfalls
28 |
29 | The aria-live attribute should not be used for dynamic content that is non-critical. Of course, what constitutes critical should be driven only by determining if the content is important to the specific purpose of the page.
30 |
31 | The purpose of the page should be clearly indicated by the `` element in the page ``. Another clue should be the `` of the page, which should also clearly indicate the purpose of that page.
32 |
33 | It is a common practice to asynchronously load other page content like sidebar widgets or tabular data. In both of these instances, the areas should be marked with `aria-live=off` so they can indicate the updated information only once the user focuses on those elements.
34 |
35 |
--------------------------------------------------------------------------------
/global-components/buttons/README.md:
--------------------------------------------------------------------------------
1 | # Buttons
2 |
3 | Ahh, the simple button. Possibly the simplest component of them all, yet still somehow one that has been the subject of continual confusion in web and application development.
4 |
5 | {% hint style="info" %}
6 | Did you know that placement of the button matters? Read more about it here: [Where to put buttons in forms](https://adamsilver.io/articles/where-to-put-buttons-in-forms/) by Adam Silver.
7 | {% endhint %}
8 |
9 | ## Introduction
10 |
11 | There are benefits to using the `` element - semantic HTML is machine-readable code, and there are pre-existing browser defaults for interaction, such as using the `ENTER` or `SPACE` key to activate the button's `click` and `keydown` events.
12 |
13 | ## Part One: Considering Markup
14 |
15 | {% hint style="warning" %}
16 | Link or Button? The rule of thumb is this: if it takes the user to a URL, use a link. Otherwise, use a button!
17 | {% endhint %}
18 |
19 | ### Standard buttons
20 |
21 | This is the most common markup associated with the `` element:
22 |
23 | ```markup
24 | text
25 | ```
26 |
27 | ### Icon buttons
28 |
29 | Special care should be given when deciding to include a button with only an icon in it. In order to be machine-readable, information should be added depending on your icon approach.
30 |
31 | Whether the icon is an image file, an emoji\(not advised\), or an SVG file, the `aria-label` attribute should be added to the `` element. It should also be explicitly ensured that the image is not available to other machines, which can be achieved by adding the `aria-hidden` attribute.
32 |
33 | Example:
34 |
35 | ```markup
36 |
37 | 🗑
38 |
39 | ```
40 |
41 | This markup will return the following accessibility tree:
42 |
43 | 
44 |
45 | {% hint style="info" %}
46 | For an improved user experience, consider adding text along with the icon. _**All**_ users will benefit from the added clarity, especially since the meaning of icons can differ from country to country!
47 | {% endhint %}
48 |
49 | ### Toggle buttons
50 |
51 | Toggle buttons can be a little tricky because they have multiple small details that must be included in order to be appropriately effective.
52 |
53 | While a toggle button can visually present in many different ways, the use of pseudo elements can still allow semantic markup to achieve the desired outcomes.
54 |
55 | ```markup
56 |
57 | Option Text
58 |
59 |
60 |
61 | ```
62 |
63 | Which can, with appropriate styling, produce a toggle that would appear like this:
64 |
65 | 
66 |
67 | To see how the styling would work in this case, a [CodePen](https://codepen.io/melsumner/pen/wVErBw) has been created as a demonstration.
68 |
69 | Assistive technology interprets the existence of the `aria-pressed` attribute as a signal that this is a toggle button. Typically, a screen reader should read out "\(Option Text\) toggle button" when `aria-pressed` is false. When `aria-pressed` is set to true, "\(Option Text\) toggle button pressed" will be heard instead.
70 |
71 | ### Buttons in forms
72 |
73 | While using ` ` \(or `type="button"`, or `type="reset"`\) is still technically valid HTML, it is also an _outdated_ approach, and it is recommended to avoid use. Additionally, `` elements are considerably easier to style than ` ` elements.
74 |
75 | When inside of the `