Cheat Sheet
Packages
@microsoft/fast-element
A lightweight library for building performant, memory-efficient, standards-compliant Web Components.
- Provides a thin layer of opinion on top of Web Components, lifting the level of abstraction just enough to make it easier and faster to build components.
- Use this library when you want to create new custom web components.
To install the fast-element
library, use either npm
or yarn
:
npm install --save @microsoft/fast-element
yarn add @microsoft/fast-element
Within your JavaScript or TypeScript code, you can then import library APIs like this:
import { FASTElement } from "@microsoft/fast-element";
@microsoft/fast-foundation
This package is a library of Web Component classes, templates, and other utilities intended to be composed into registered Web Components by design systems.
- Exports of this package can generally be thought of as un-styled base components that implement semantic and accessible markup and behavior.
- Use this library when you want to create something like Google's Material Design or Bootstrap.
Example
import {
Button as FoundationButton,
buttonTemplate as template,
} from "@microsoft/fast-foundation";
import { css } from "@microsoft/fast-element";
export class MyButton extends FoundationButton {
...
}
export const buttonStyles = css`
:host {
background-color: azure;
}
`;
export const myButton = MyButton.compose({
baseName: "button",
baseClass: FoundationButton,
template,
styles: buttonStyles,
shadowOptions: {
delegatesFocus: true,
},
});
@microsoft/fast-components
The FAST component library and visual system FAST Frame, which implements fast-foundation.
- Assembles the building blocks of
@microsoft/fast-foundation
to create its component set. - Use this library when you want to integrate FAST Components into an existing site or app.
To install the components, use either npm
or yarn
:
npm install --save @microsoft/fast-components
yarn add @microsoft/fast-components
To use a component as a custom element in HTML, the custom element must be registered.
Example
import {
fastButton,
provideFASTDesignSystem
} from "@microsoft/fast-components";
provideFASTDesignSystem()
.register(
fastButton() // custom element registration
);
Using components
Setup
Example
To register design system components:
import {
fastButton,
provideFASTDesignSystem
} from "@microsoft/fast-components";
provideFASTDesignSystem()
.register(
fastButton() // custom element registration
);
Or, register all system components:
import {
allComponents,
provideFASTDesignSystem
} from "@microsoft/fast-components";
provideFASTDesignSystem().register(allComponents);
With the components registered, add any component to the HTML.
Example
<fast-button>Hello world</fast-button>
Launch our Component Explorer for a comprehensive list of FAST Components.
Integrations
FAST libraries can also be used in combination with a wide variety of existing technologies:
Not seeing an integration for your preferred technology? Open an issue on GitHub.
Building components
There are two main approaches to building a component:
- The first approach is for simple declarations of non-shared components.
- The second approach is for components designed to be published in shareable libraries.
Setup
Example
To define a custom element:
import { FASTElement, customElement } from "@microsoft/fast-element";
@customElement("name-tag") // custom element being created
export class NameTag extends FASTElement {
...
}
With this in place, you can now use your <name-tag>
element anywhere in HTML with the following markup:
<name-tag></name-tag>
Attributes
To add attributes to your HTML element, create properties decorated by the @attr
decorator.
All attributes defined this way will be automatically registered with the platform so that they can be updated through the browser's native setAttribute
API as well as the property.
You can optionally add a method with the naming convention propertyNameChanged to your class, and this method will be called whenever your property changes, whether it changes through the property or the attribute API.
Example
import { FASTElement, customElement, attr } from "@microsoft/fast-element";
@customElement("name-tag")
export class NameTag extends FASTElement {
@attr greeting: string = "Hello";
// optional method
greetingChanged() {
...
}
}
Example: To use a Web Component with Attributes
<name-tag greeting="Hola"></name-tag>
Customizing attributes
There are three modes available through the mode
property of the attribute configuration:
Mode | Guidance |
---|---|
reflect | The default mode that is used if none is specified. |
boolean | This mode causes your attribute to function using the HTML boolean attribute behavior. |
fromView | This mode skips reflecting the value of the property back to the HTML attribute. |
In addition to setting the mode, you can also supply a custom ValueConverter
by setting the converter
property of the attribute configuration.
The converter must implement the following interface:
interface ValueConverter {
toView(value: any): string;
fromView(value: string): any;
}
Example: An Attribute in Reflect
Mode with No Special Conversion
import { FASTElement, customElement, attr } from '@microsoft/fast-element';
@customElement('name-tag')
export class NameTag extends FASTElement {
@attr greeting: string = 'Hello';
}
Example: An Attribute in Boolean
Mode with Boolean Conversion
import { FASTElement, customElement, attr } from '@microsoft/fast-element';
@customElement('my-checkbox')
export class MyCheckbox extends FASTElement {
@attr({ mode: 'boolean' }) disabled: boolean = false;
}
Example: An Attribute in Reflect
Mode with Custom Conversion
import { FASTElement, customElement, attr, ValueConverter } from '@microsoft/fast-element';
const numberConverter: ValueConverter = {
toView(value: number): string {
return String(value);
},
fromView(value: string): number {
return Number(value);
}
};
@customElement("my-counter")
export class MyCounter extends FASTElement {
@attr({
mode: "reflect",
converter: numberConverter
})
count: number = 0;
}
Templates
To create an HTML template for an element, import and use the html
tagged template helper and pass the template to the @customElement
decorator.
Example
import { FASTElement, customElement, attr, html } from "@microsoft/fast-element";
const template = html<NameTag>`
<div class="header">
<h3>${x => x.greeting.toUpperCase()}</h3>
<h4>my name is</h4>
</div>
<div class="body">TODO: Name Here</div>
<div class="footer"></div>
`;
@customElement({
name: "name-tag",
template
})
export class NameTag extends FASTElement {
...
}
Observables
To enable binding tracking and change notification, properties must be decorated with either @attr
or @observable
.
Use @attr
for primitive properties (string, bool, number) that are intended to be surfaced on your element as HTML attributes. Use @observable
for all other property types on an HTMLElement and all observable properties on plain classes.
Example
import { Observable } from "@microsoft/fast-element";
export class Person {
@observable firstName = "";
@observable lastName = "";
get fullName() {
return `${this.firstName} ${this.LastName}`;
}
}
Bindings
(x
refers to the custom-element class instance in the examples below.)
Binding Type | Example | Notes |
---|---|---|
Content | <p>${x => x.greeting} friend!</p> | Creates a binding to interpolate text or child templates into element content. |
HTML Attribute | <a href=${x => x.aboutLink}></a> | Creates a binding that uses the setAttribute API. Attribute bindings also support interpolation with text and other bindings. |
HTML Boolean Attribute | <input ?disabled=${x => x.isDisabled}> | Creates a binding that adds or removes the attribute based on truthy/falsey values. |
JS Property | <input :value=${x => x.name}> | Creates a binding that sets a JavaScript property on the element. |
Event Handler | <button @click=${x => x.handleClick()}>Button</button> | Registers an event handler using addEventListener. The listener is automatically removed when the template is unbound. After your event handler is executed, preventDefault() will be called on the event object by default. You can return true from your handler to opt-out of this behavior. |
HTML Element Reference | <button ${ref("myButton")}>Button</button> | Captures a reference to the element and assigns it to the named property on the element instance. |
Slotted Node Capture | <slot ${slotted("defaultSlotNodes")}></slot> | Watches the slot for changes and synchronizes those to an array, assigned to the named property on the element instance. |
Child Node Capture | <div ${children("divChildren")}></div> | Watches the element's children or changes and synchronizes those to an array, assigned to the named property on the element instance. |
Directives
Use the when
directive to conditionally render blocks of HTML.
Example
import { FASTElement, customElement, observable, html, when } from "@microsoft/fast-element";
const template = html<MyApp>`
...
${when(x => !x.ready, html<MyApp>`
Loading...
`)}
`;
@customElement({
name: "my-app",
template
})
export class MyApp extends FASTElement {
@observable ready: boolean = false;
...
}
Use the repeat
directive to render a list of data.
Example
import { FASTElement, customElement, observable, html, repeat } from "@microsoft/fast-element";
const template = html<FriendList>`
...
${repeat(x => x.friends, html<string>`
<li>${x => x}</li>
`)}
`;
@customElement({
name: "friend-list",
template
})
export class FriendList extends FASTElement {
@observable friends: Person[] = [];
...
}
Properties available on the context object within a repeat
block:
Property | Definition |
---|---|
event | The event object when inside an event handler. |
parent | The parent view-model when inside a repeat block. |
parentContext | The parent ExecutionContext when inside a repeat block. This is useful when repeats are nested and the inner-most repeat needs access to the root view-model. |
Opt-in
properties that are not available by default:
Opt-in Properties | Definition |
---|---|
index | The index of the current item when inside a repeat block. |
length | The length of the array when inside a repeat block. |
isEven | True if the index of the current item is even when inside a repeat block. |
isOdd | True if the index of the current item is odd when inside a repeat block. |
isFirst | True if the current item is first in the array inside a repeat block. |
isInMiddle | True if the current item is somewhere in the middle of the array inside a repeat block. |
isLast | True if the current item is last in the array inside a repeat block. |
To opt into the positioning properties, pass options to the repeat
directive, with the setting positioning: true
.
Example: Rendering a list with Item Index
<ul>
${repeat(x => x.friends, html<string>`
<li>${(x, c) => c.index} ${x => x}</li>
`, { positioning: true })}
</ul>
Styles
FASTElement
provides a css tagged template helper that allows for the creation of ElementStyles
.
Example: Adding CSS to a FASTElement
import { FASTElement, customElement } from "@microsoft/fast-element";
import { css, customElement, FASTElement } from "@microsoft/fast-element";
import { disabledOpacity } from "../design-tokens";
const styles = css`
:host([disabled]) {
opacity: ${disabledOpacity};
}
`;
@customElement({
styles
})
export class MyElement extends FASTElement {}
Composing styles
ElementStyles
can be composed with other styles.
Example
import { normalize } from "./normalize";
const styles = css`
${normalize}
:host {
...
}
`;
Partial CSS
Use the cssPartial
tagged template literal to create reusable blocks of partial CSS.
Example
import { css, cssPartial } from "@microsoft/fast-element";
const partial = cssPartial`color: red;`;
const styles = css`:host{ ${partial} }`;
CSSDirective
To create a CSSDirective
, import and extend CSSDirective
from @microsoft/fast-element
.
Example
import { CSSDirective } from "@microsoft/fast-element"
class RandomWidth extends CSSDirective {}
createCSS method
CSSDirective
has a createCSS()
method that returns a string to be interpolated into an ElementStyles
.
Example
class RandomWidth extends CSSDirective {
createCSS() {
return "width: var(--random-width);"
}
}
createBehavior method
The createBehavior()
method can be used to create a Behavior
that is bound to the element using the CSSDirective
.
Example
class RandomWidth extends CSSDirective {
private property = "20px";
createCSS() {
return `width: ${this.property};`
}
createBehavior() {
return {
bind(el) {
el.style.setProperty(this.property, Math.floor(Math.random() * 100) + "px")
}
unbind(el) {
el.style.removeProperty(this.property);
}
}
}
}
Design system
Creating a design system
- Start with the base components defined in
@microsoft/fast-foundation
and compose them with your own styles.
Example
import {
Button,
buttonTemplate as template,
} from "@microsoft/fast-foundation";
import { buttonStyles as styles } from "./special-button.styles";
export const specialButton = Button.compose({
baseName: "button",
template,
styles,
shadowOptions: {
delegatesFocus: true,
},
});
export const buttonStyles = styles;
- Export a
provider function
for your community to use in setting everything up.
Example
export function provideSpecialDesignSystem(element?: HTMLElement): DesignSystem {
return DesignSystem.getOrCreate(element).withPrefix("special");
}
Design tokens
Example: Creating a token
import { DesignToken } from "@microsoft/fast-foundation";
// create a design token
export const specialColor = DesignToken.create<string>("special-color");
Example: Using design tokens in CSS
// use the design token to build styles
const styles = css`
:host {
background: ${specialColor};
}
`;
Example: Setting values
// change the value for a given element
specialColor.setValueFor(ancestor, "#FFF");
specialColor.setValueFor(descendent, "#000");
Example: Getting values
// get the value
specialColor.getValueFor(ancestor); // "#FFF"
specialColor.getValueFor(descendent); // "#000"
Example: Deleting values
// unset the value (inherits from ancestor)
specialColor.deleteValueFor(descendent);
specialColor.getValueFor(descendent); // "#FFF"
Configuring a FAST design token
FAST exposes non-color related Design Tokens that can be used to configure components stylistically. For Design Tokens related to color, see the adaptive color system.
Example: Changing the value for the typeRampBaseFontSize
design token
import { typeRampBaseFontSize } from "@microsoft/fast-components";
import { FASTElement } from '@microsoft/fast-element';
const myElement = document.querySelector("my-element") as FASTElement;
typeRampBaseFontSize.setValueFor(myElement, "20px");
Contributing to FAST
Connect with us:
Unsure of what to work on?
- Here are good first issues.
Contributor guide
- Machine setup
- Cloning the repository
- Installing & building
- Testing
- Submitting a pull request
- Merging a pull request
Branch Guide
When contributing to the FAST repository, please follow the standards defined in this guide.
Contributing to fast-components
cd packages/web-components/fast-components
yarn start
Storybook will open in a browser window at localhost:6006
.
Contributing to documentation
cd sites/website
yarn start
Docusaurus will open in a browser window at localhost:3000
.