11# Angular Material Coding Standards
22
3-
43## Code style
54
65The [ Google JavaScript Style Guide] ( https://google.github.io/styleguide/jsguide.html ) is the
@@ -12,6 +11,7 @@ ES6 or TypeScript.
1211### General
1312
1413#### Write useful comments
14+
1515Comments that explain what some block of code does are nice; they can tell you something in less
1616time than it would take to follow through the code itself.
1717
@@ -21,6 +21,7 @@ the original author. When collaborators are in the same room, this hurts product
2121When collaborators are in different timezones, this can be devastating to productivity.
2222
2323For example, this is a not-very-useful comment:
24+
2425``` ts
2526// Set default tabindex.
2627if (! $attrs [' tabindex' ]) {
@@ -29,6 +30,7 @@ if (!$attrs['tabindex']) {
2930```
3031
3132While this is much more useful:
33+
3234``` ts
3335// Unless the user specifies so, the calendar should not be a tab stop.
3436// This is necessary because ngAria might add a tabindex to anything with an ng-model
@@ -48,20 +50,23 @@ In HTML code, use `<!-- ... -->` comments, which will be stripped when packaging
4850#### Prefer more focused, granular components vs. complex, configurable components.
4951
5052For example, rather than doing this:
53+
5154``` html
5255<mat-button >Basic button</mat-button >
5356<mat-button class =" mat-fab" >FAB</mat-button >
5457<mat-button class =" mat-icon-button" >pony</mat-button >
5558```
5659
5760do this:
61+
5862``` html
5963<mat-button >Basic button</mat-button >
6064<mat-fab >FAB</mat-fab >
6165<mat-icon-button >pony</mat-icon-button >
6266```
6367
6468#### Prefer small, focused modules
69+
6570Keeping modules to a single responsibility makes the code easier to test, consume, and maintain.
6671ES6 modules offer a straightforward way to organize code into logical, granular units.
6772Ideally, individual files are 200 - 300 lines of code.
@@ -70,6 +75,7 @@ As a rule of thumb, once a file draws near 400 lines (barring abnormally long co
7075start considering how to refactor into smaller pieces.
7176
7277#### Less is more
78+
7379Once a feature is released, it never goes away. We should avoid adding features that don't offer
7480high user value for price we pay both in maintenance, complexity, and payload size. When in doubt,
7581leave it out.
@@ -78,12 +84,14 @@ This applies especially to providing two different APIs to accomplish the same t
7884prefer sticking to a _ single_ API for accomplishing something.
7985
8086### 100 column limit
87+
8188All code and docs in the repo should be 100 columns or fewer. This applies to TypeScript, SCSS,
8289HTML, bash scripts, and markdown files.
8390
8491### API Design
8592
8693#### Boolean arguments
94+
8795Avoid adding boolean arguments to a method in cases where that argument means "do something extra".
8896In these cases, prefer breaking the behavior up into different functions.
8997
@@ -108,6 +116,7 @@ function createTargetElement() {
108116### TypeScript
109117
110118#### Typing
119+
111120Avoid ` any ` where possible. If you find yourself using ` any ` , consider whether a generic may be
112121appropriate in your case.
113122
@@ -116,7 +125,9 @@ specified because our documentation tooling cannot currently infer types in plac
116125can.
117126
118127#### Fluent APIs
128+
119129When creating a fluent or builder-pattern style API, use the ` this ` return type for methods:
130+
120131```
121132class ConfigBuilder {
122133 withName(name: string): this {
@@ -127,27 +138,29 @@ class ConfigBuilder {
127138```
128139
129140#### Access modifiers
130- * Omit the ` public ` keyword as it is the default behavior.
131- * Use ` private ` when appropriate and possible, prefixing the name with an underscore.
132- * Use ` protected ` when appropriate and possible with no prefix.
133- * Prefix * library-internal* properties and methods with an underscore without using the ` private `
134- keyword. This is necessary for anything that must be public (to be used by Angular), but should not
135- be part of the user-facing API. This typically applies to symbols used in template expressions,
136- ` @ViewChildren ` / ` @ContentChildren ` properties, host bindings, and ` @Input ` / ` @Output ` properties
137- (when using an alias).
138-
139- Additionally, the ` @docs-private ` JsDoc annotation can be used to hide any symbol from the public
140- API docs.
141141
142+ - Omit the ` public ` keyword as it is the default behavior.
143+ - Use ` private ` when appropriate and possible, prefixing the name with an underscore.
144+ - Use ` protected ` when appropriate and possible with no prefix.
145+ - Prefix _ library-internal_ properties and methods with an underscore without using the ` private `
146+ keyword. This is necessary for anything that must be public (to be used by Angular), but should not
147+ be part of the user-facing API. This typically applies to symbols used in template expressions,
148+ ` @ViewChildren ` / ` @ContentChildren ` properties, host bindings, and ` @Input ` / ` @Output ` properties
149+ (when using an alias).
150+
151+ Additionally, the ` @nodoc ` JsDoc annotation can be used to hide any symbol from the public
152+ API docs.
142153
143154#### Getters and Setters
144- * Only use getters and setters for ` @Input ` properties or when otherwise required for API
145- compatibility.
146- * Avoid long or complex getters and setters. If the logic of an accessor would take more than
147- three lines, introduce a new method to contain the logic.
148- * A getter should immediately precede its corresponding setter.
149- * Decorators such as ` @Input ` should be applied to the getter and not the setter.
150- * Always use a ` readonly ` property instead of a getter (with no setter) when possible.
155+
156+ - Only use getters and setters for ` @Input ` properties or when otherwise required for API
157+ compatibility.
158+ - Avoid long or complex getters and setters. If the logic of an accessor would take more than
159+ three lines, introduce a new method to contain the logic.
160+ - A getter should immediately precede its corresponding setter.
161+ - Decorators such as ` @Input ` should be applied to the getter and not the setter.
162+ - Always use a ` readonly ` property instead of a getter (with no setter) when possible.
163+
151164 ``` ts
152165 /** YES */
153166 readonly active : boolean ;
@@ -165,17 +178,19 @@ All public APIs must have user-facing comments. These are extracted and shown in
165178on [ material.angular.dev] ( https://material.angular.dev ) .
166179
167180Private and internal APIs should have JsDoc when they are not obvious. Ultimately it is the purview
168- of the code reviewer as to what is "obvious", but the rule of thumb is that * most * classes,
181+ of the code reviewer as to what is "obvious", but the rule of thumb is that _ most _ classes,
169182properties, and methods should have a JsDoc description.
170183
171184Properties should have a concise description of what the property means:
185+
172186``` ts
173187 /** The label position relative to the checkbox. Defaults to 'after' */
174188 @Input () labelPosition : ' before' | ' after' = ' after' ;
175189```
176190
177191Methods blocks should describe what the function does and provide a description for each parameter
178192and the return value:
193+
179194``` ts
180195 /**
181196 * Opens a modal dialog containing the given component.
@@ -187,6 +202,7 @@ and the return value:
187202```
188203
189204Boolean properties and return values should use "Whether..." as opposed to "True if...":
205+
190206``` ts
191207 /** Whether the button is disabled. */
192208 disabled : boolean = false ;
@@ -198,21 +214,24 @@ Avoid `try-catch` blocks, instead preferring to prevent an error from being thro
198214place. When impossible to avoid, the ` try-catch ` block must include a comment that explains the
199215specific error being caught and why it cannot be prevented.
200216
201-
202217#### Naming
203218
204219##### General
205- * Prefer writing out words instead of using abbreviations.
206- * Prefer * exact* names to short names (within reason). E.g., ` labelPosition ` is better than
207- ` align ` because the former much more exactly communicates what the property means.
208- * Except for ` @Input ` properties, use ` is ` and ` has ` prefixes for boolean properties / methods.
220+
221+ - Prefer writing out words instead of using abbreviations.
222+ - Prefer _ exact_ names to short names (within reason). E.g., ` labelPosition ` is better than
223+ ` align ` because the former much more exactly communicates what the property means.
224+ - Except for ` @Input ` properties, use ` is ` and ` has ` prefixes for boolean properties / methods.
209225
210226##### Observables
211- * Don't suffix observables with ` $ ` .
227+
228+ - Don't suffix observables with ` $ ` .
212229
213230##### Classes
231+
214232Classes should be named based on what they're responsible for. Names should capture what the code
215- * does* , not how it is used:
233+ _ does_ , not how it is used:
234+
216235```
217236/** NO: */
218237class RadioService { }
@@ -229,7 +248,8 @@ CDK classes should only have a `Cdk` prefix when the class is a directive with a
229248prefix.
230249
231250##### Methods
232- The name of a method should capture the action that is performed * by* that method rather than
251+
252+ The name of a method should capture the action that is performed _ by_ that method rather than
233253describing when the method will be called. For example,
234254
235255``` ts
@@ -245,11 +265,12 @@ activateRipple() {
245265```
246266
247267##### Selectors
248- * Component selectors should be lowercase and delimited by hyphens. Components should use element
249- selectors except when the component API uses a native HTML element.
250- * Directive selectors should be camel cased. Exceptions may be made for directives that act like a
251- component but would have an empty template, or when the directive is intended to match some
252- existing attribute.
268+
269+ - Component selectors should be lowercase and delimited by hyphens. Components should use element
270+ selectors except when the component API uses a native HTML element.
271+ - Directive selectors should be camel cased. Exceptions may be made for directives that act like a
272+ component but would have an empty template, or when the directive is intended to match some
273+ existing attribute.
253274
254275#### Inheritance
255276
@@ -258,20 +279,25 @@ behaviors can be composed. Instead, [TypeScript mixins][ts-mixins] can be used t
258279common behaviors into a single component.
259280
260281#### Coercion
282+
261283Component and directive inputs for boolean and number values must use an input transform function
262284to coerce values to the expected type.
263285For example:
286+
264287``` ts
265288import {Input , booleanAttribute } from ' @angular/core' ;
266289
267290@Input ({transform: booleanAttribute }) disabled : boolean = false ;
268291```
292+
269293The above code allows users to set ` disabled ` similar to how it can be set on native inputs:
294+
270295``` html
271296<component disabled ></component >
272297```
273298
274299#### Expose native inputs
300+
275301Native inputs used in components should be exposed to developers through ` ng-content ` . This allows
276302developers to interact directly with the input and allows us to avoid providing custom
277303implementations for all the input's native behaviors.
@@ -281,11 +307,13 @@ For example:
281307** Do:**
282308
283309Implementation
310+
284311``` html
285312<ng-content ></ng-content >
286313```
287314
288315Usage
316+
289317``` html
290318<your-component >
291319 <input >
@@ -295,41 +323,45 @@ Usage
295323** Don't:**
296324
297325Implementation
326+
298327``` html
299328<input >
300329```
301330
302331Usage
332+
303333``` html
304334<component ></component >
305335```
306336
307-
308337### Angular
309338
310339#### Host bindings
340+
311341Prefer using the ` host ` object in the directive configuration instead of ` @HostBinding ` and
312342` @HostListener ` . We do this because TypeScript preserves the type information of methods with
313343decorators, and when one of the arguments for the method is a native ` Event ` type, this preserved
314344type information can lead to runtime errors in non-browser environments (e.g., server-side
315345pre-rendering).
316346
317-
318347### CSS
319348
320349#### Be cautious with use of ` display: flex `
321- * The [ baseline calculation for flex elements] ( https://www.w3.org/TR/css-flexbox-1/#flex-baselines )
322- is different from other display values, making it difficult to align flex elements with standard
323- elements like input and button.
324- * Component outermost elements are never flex (block or inline-block)
325- * Don't use ` display: flex ` on elements that will contain projected content.
350+
351+ - The [ baseline calculation for flex elements] ( https://www.w3.org/TR/css-flexbox-1/#flex-baselines )
352+ is different from other display values, making it difficult to align flex elements with standard
353+ elements like input and button.
354+ - Component outermost elements are never flex (block or inline-block)
355+ - Don't use ` display: flex ` on elements that will contain projected content.
326356
327357#### Use the lowest specificity possible
358+
328359Always prioritize lower specificity over other factors. Most style definitions should consist of a
329360single element or css selector plus necessary state modifiers. ** Avoid SCSS nesting for the sake of
330361code organization.** This will allow users to much more easily override styles.
331362
332363For example, rather than doing this:
364+
333365``` scss
334366.mat-calendar {
335367 display : block ;
@@ -345,6 +377,7 @@ For example, rather than doing this:
345377```
346378
347379do this:
380+
348381``` scss
349382.mat-calendar {
350383 display : block ;
@@ -360,9 +393,11 @@ do this:
360393```
361394
362395#### Never set a margin on a host element.
396+
363397The end-user of a component should be the one to decide how much margin a component has around it.
364398
365399#### Prefer styling the host element vs. elements inside the template (where possible).
400+
366401This makes it easier to override styles when necessary. For example, rather than
367402
368403``` scss
@@ -376,6 +411,7 @@ the-host-element {
376411```
377412
378413you can write
414+
379415``` scss
380416the-host-element {
381417 // ...
@@ -386,7 +422,9 @@ the-host-element {
386422The latter is equivalent for the component, but makes it easier override when necessary.
387423
388424#### Support styles for Windows high-contrast mode
425+
389426This is a low-effort task that makes a big difference for low-vision users. Example:
427+
390428``` css
391429@include cdk-high-contrast(active, off) {
392430 .unicorn-motocycle {
@@ -396,7 +434,9 @@ This is a low-effort task that makes a big difference for low-vision users. Exam
396434```
397435
398436#### Explain what CSS classes are for
437+
399438When it is not super obvious, include a brief description of what a class represents. For example:
439+
400440``` scss
401441// The calendar icon button used to open the calendar pane.
402442.mat-datepicker-button { ... }
@@ -411,9 +451,11 @@ When it is not super obvious, include a brief description of what a class repres
411451[ ts-mixins ] : https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html#support-for-mix-in-classes
412452
413453#### Prefer CSS classes to tag names and attributes for styling
454+
414455Targeting tag names can cause conflicts with the MDC version of the component. For this reason, use
415456CSS class names defined by us instead of tag names. We also prefer classes to attributes for
416457consistency.
458+
417459``` scss
418460/* * Do: */
419461.mat-mdc-slider { ... }
@@ -426,4 +468,4 @@ mdc-slider { ... }
426468
427469/* * Don't: */
428470input [type = " button" ] { ... }
429- ```
471+ ```
0 commit comments