# Fabric UX Angular Components

The Fabric UX System represents a leap forward in design consistency and extensibility for Microsoft Fabric. Developed by the Fabric UX Team, this system is a collection of design guidance, common patterns, and reusable components created to empower designers and developers to build consistent, accessible, and engaging workload experiences across Fabric surfaces.

View the [Fabric UX System documentation](https://aka.ms/fabricux).

The Fabric UX System's Angular components are built with web components under the hood. This allows all components within the Fabric UX System to share common style, logic, and interaction regardless of the development environment.

## Installation

**Note:** These packages are currently published to the PowerBIClients Azure Artifacts registry, not NPM. You'll need to configure your package manager to use the Azure Artifacts feed.

**Registry Information:**

- **Package:** [@fabric-msft/fabric-angular](https://dev.azure.com/powerbi/Trident/_artifacts/feed/PowerBIClients/Npm/@fabric-msft%2Ffabric-angular/overview/4.0.0-beta.15)
- **Feed:** PowerBIClients at `https://dev.azure.com/powerbi/Trident/_artifacts/feed/PowerBIClients`

Once you've configured access to the Azure Artifacts feed, you can install the components using:

**npm**

```bash
npm install @fabric-msft/fabric-angular
```

**Yarn**

```bash
yarn add @fabric-msft/fabric-angular
```

After installation, the library is immediately ready for use, allowing developers to begin incorporating Fabric UI components into their Angular applications with minimal setup.

## Configuring and Importing Components

Before diving into the specifics of component usage, it's essential to understand how to configure and import the Fabric Angular Components library within your project. This step is crucial for ensuring that the components are correctly initialized and ready to be used within your application.

### Initial Configuration

Upon successful installation, the next step is to configure your project to use the Fabric Angular Components. These components use **standalone directives** that provide lightweight Angular wrappers around web components and automatically register custom elements when imported.

### Importing Components

**Recommended: Individual imports**

Import individual standalone directives into your Angular component:

```typescript
import { FabricBadgeDirective } from "@fabric-msft/fabric-angular/badge";
import { FabricButtonDirective } from "@fabric-msft/fabric-angular/button";
import { FabricTagDirective } from "@fabric-msft/fabric-angular/tag";

@Component({
  selector: "app-my-component",
  imports: [FabricBadgeDirective, FabricButtonDirective, FabricTagDirective],
  template: `
    <fabric-badge shape="rounded" size="large" color="danger">
      New Feature
    </fabric-badge>
    <fabric-button appearance="primary">Click me</fabric-button>
    <fabric-tag>Important</fabric-tag>
  `
})
export class MyComponent {}
```

## Using Fabric UX Angular Components

With the modules imported, you can start using the components in your Angular templates:

```html
<!-- Basic components -->
<fabric-badge shape="rounded" size="large" color="danger">
  New Feature
</fabric-badge>
<fabric-button appearance="primary">Click me</fabric-button>
<fabric-tag>Important</fabric-tag>

<!-- Dialog with content projection -->
<fabric-dialog>
  <div slot="heading">Dialog Title</div>
  <p>Dialog content goes here.</p>
  <div slot="footer">
    <fabric-button appearance="secondary">Cancel</fabric-button>
    <fabric-button appearance="primary">Confirm</fabric-button>
  </div>
</fabric-dialog>

<!-- Card component -->
<fabric-card>
  <fabric-card-header>
    <div slot="header">Card Title</div>
    <div slot="description">Card description</div>
  </fabric-card-header>
  <fabric-card-preview>Card content area</fabric-card-preview>
</fabric-card>

<!-- Form components -->
<fabric-checkbox>Accept terms and conditions</fabric-checkbox>
<fabric-text-input placeholder="Enter your name"></fabric-text-input>

<fabric-dropdown>
  <fabric-dropdown-option value="option1">Option 1</fabric-dropdown-option>
  <fabric-dropdown-option value="option2">Option 2</fabric-dropdown-option>
</fabric-dropdown>
```

## Standalone Directive Architecture

Fabric Angular components use **standalone directives** that:

- Provide lightweight Angular wrappers around web components
- Automatically register custom elements when directives are imported
- Maintain consistent patterns across all component libraries
- Eliminate complex proxy component logic for better performance

```typescript
// Example of the standalone directive pattern
@Directive({
  selector: "fabric-button"
})
export class FabricButtonDirective {
  constructor() {
    if (!customElements.get("fabric-button")) {
      ButtonDefinition.define(customElements);
    }
  }
}
```

## Setting the Fabric Theme

Out of the box, the components do not include CSS variables. This may make some components feel "unstyled". CSS variables must be applied to your application to see the Fabric UX System's design language.

To apply the Fabric design language, install the theme package and set up the theme:

```bash
npm install @fabric-msft/theme
```

At the root of your Angular application, add the following snippet to install all the CSS variables:

```typescript
import { fabricLightTheme, setTheme } from "@fabric-msft/theme";

setTheme(fabricLightTheme);
```

## Listening for Events from Fabric UX System Components

Fabric UX components use conventional naming for events (click, dismiss, etc). For components that use custom events, the names can be imported and bound to like any other event:

```typescript
import { PopoverEventNames } from "@fabric-msft/fabric-web";

@Component({
  selector: "app-popover-example",
  template: `
    <fabric-popover (hidePopover)="onHidePopover($event)">
      Popover Content
    </fabric-popover>
  `
})
export class PopoverExampleComponent {
  onHidePopover(event: CustomEvent): void {
    console.log("Popover hidden!", event);
  }
}
```

## Angular Reactive Forms Compatibility

All form control components implement the Angular `ControlValueAccessor` interface and can be used with reactive forms:

```typescript
import { FormBuilder, FormGroup } from "@angular/forms";

@Component({
  template: `
    <form [formGroup]="myForm">
      <fabric-text-input
        formControlName="username"
        placeholder="Enter username"
      ></fabric-text-input>

      <fabric-checkbox formControlName="acceptTerms">
        Accept terms and conditions
      </fabric-checkbox>

      <fabric-dropdown formControlName="country">
        <fabric-dropdown-option value="us">
          United States
        </fabric-dropdown-option>
        <fabric-dropdown-option value="ca">Canada</fabric-dropdown-option>
      </fabric-dropdown>
    </form>
  `
})
export class MyFormComponent {
  myForm: FormGroup;

  constructor(private fb: FormBuilder) {
    this.myForm = this.fb.group({
      username: [""],
      acceptTerms: [false],
      country: [""]
    });
  }
}
```

## Styling Fabric UX Components

Web components have some styling differences from typical components in Angular. In every web component is a shadowDOM that is separate from the html element's view. The shadowDOM is a protected tree that is not directly accessible by standard CSS selectors. Web components provide their own API for accessing and styling the shadowDOM:

### CSS Parts

All relevant CSS classes in Fabric UX components are exposed as CSS parts:

```css
/* Example of styling a fabric-tag component using CSS parts */
fabric-tag::part(container) {
  outline: 1px solid red;
}

fabric-button::part(control) {
  border-radius: 8px;
}
```

### CSS Variables

Sometimes the web component will expose CSS variables for specific styling aspects:

```css
/* Example of styling components using CSS variables */
fabric-filter-pill {
  --icon-spacing: 8px;
}

fabric-button {
  --button-padding: 12px;
}
```

### Slots and Content Projection

Web components support named and default slots for flexible content placement:

```html
<fabric-dialog>
  <div slot="heading">Dialog Title</div>
  Main dialog content
  <div slot="footer">
    <fabric-button appearance="secondary">Cancel</fabric-button>
    <fabric-button appearance="primary">OK</fabric-button>
  </div>
</fabric-dialog>
```
