# Error State

Use `ui-error-state` for failed loads, missing resources, permission blocks, and similar broken flows where the user needs both context and a next step. The copy should explain the problem in human terms, not just restate a technical failure.

## Import
```ts
import { ErrorStateComponent, type QuickAction } from 'ui';
```

## Basic error messaging
```ts
import { Component } from '@angular/core';
import { ErrorStateComponent } from 'ui';

@Component({
  selector: 'app-error-state-basic-demo',
  standalone: true,
  imports: [ErrorStateComponent],
  template: `
    <div
      style="width:100%;max-width:28rem;padding:1.5rem;border:1px solid var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background-rest)"
    >
      <ui-error-state
        title="Something went wrong"
        description="An unexpected problem occurred. Please try again in a moment."
      />
    </div>
  `,
})
export class ErrorStateBasicDemoComponent {}
```

## Icons and sizes
```ts
import { Component } from '@angular/core';
import { ErrorStateComponent } from 'ui';

@Component({
  selector: 'app-error-state-icons-sizes-demo',
  standalone: true,
  imports: [ErrorStateComponent],
  template: `
    <div
      style="display:grid;grid-template-columns:repeat(auto-fit,minmax(15rem,1fr));gap:1rem;width:100%;max-width:56rem"
    >
      <div
        style="padding:1rem;border:1px solid var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background-rest)"
      >
        <p
          style="margin:0 0 0.75rem;font-size:0.875rem;font-weight:600;color:var(--color-neutral-foreground2-rest)"
        >
          Small
        </p>
        <ui-error-state
          title="Sync failed"
          description="Please try again."
          icon="arrow_sync"
          size="small"
        />
      </div>

      <div
        style="padding:1rem;border:1px solid var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background-rest)"
      >
        <p
          style="margin:0 0 0.75rem;font-size:0.875rem;font-weight:600;color:var(--color-neutral-foreground2-rest)"
        >
          Medium
        </p>
        <ui-error-state
          title="Connection error"
          description="We could not reach the server. Check your connection and try again."
          icon="wifi_off"
        />
      </div>

      <div
        style="padding:1rem;border:1px solid var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background-rest)"
      >
        <p
          style="margin:0 0 0.75rem;font-size:0.875rem;font-weight:600;color:var(--color-neutral-foreground2-rest)"
        >
          Large
        </p>
        <ui-error-state
          title="Import failed"
          description="The uploaded file could not be processed due to invalid data."
          icon="document_dismiss"
          size="large"
        />
      </div>
    </div>
  `,
})
export class ErrorStateIconsSizesDemoComponent {}
```

## Recovery actions
```ts
import { Component, signal } from '@angular/core';
import { ErrorStateComponent, type QuickAction } from 'ui';

@Component({
  selector: 'app-error-state-actions-demo',
  standalone: true,
  imports: [ErrorStateComponent],
  template: `
    <div
      style="display:flex;flex-wrap:wrap;gap:1rem;align-items:flex-start;width:100%;max-width:56rem"
    >
      <div
        style="flex:0 0 30rem;padding:1.5rem;border:1px solid var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background-rest)"
      >
        <ui-error-state
          title="Upload failed"
          description="The file could not be uploaded. Retry the operation or contact support if the problem persists."
          icon="arrow_upload"
          [primaryAction]="retryAction"
          [secondaryAction]="supportAction"
        />
      </div>

      <div
        style="flex:1 1 16rem;padding:0.875rem 1rem;border:1px dashed var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background2-rest)"
      >
        <p
          style="margin:0 0 0.5rem;font-size:0.75rem;font-weight:600;letter-spacing:0.06em;text-transform:uppercase;color:var(--color-neutral-foreground2-rest)"
        >
          Last action
        </p>
        <div style="font-size:0.875rem;line-height:1.5;color:var(--color-neutral-foreground-rest)">
          {{ lastAction() || 'No action yet.' }}
        </div>
      </div>
    </div>
  `,
})
export class ErrorStateActionsDemoComponent {
  protected readonly lastAction = signal('');

  protected readonly retryAction: QuickAction = {
    label: 'Try again',
    variant: 'primary',
    icon: 'arrow_sync',
    action: () => this.lastAction.set('Try again'),
  };

  protected readonly supportAction: QuickAction = {
    label: 'Contact support',
    variant: 'secondary',
    icon: 'person_support',
    action: () => this.lastAction.set('Contact support'),
  };
}
```

## Custom projected guidance
```ts
import { Component } from '@angular/core';
import { ButtonComponent, ErrorStateComponent } from 'ui';

@Component({
  selector: 'app-error-state-custom-content-demo',
  standalone: true,
  imports: [ButtonComponent, ErrorStateComponent],
  template: `
    <div
      style="width:100%;max-width:34rem;padding:1.5rem;border:1px solid var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background-rest)"
    >
      <ui-error-state title="Fix the highlighted issues" icon="error_circle">
        <ng-template #content>
          <div
            style="display:flex;flex-direction:column;gap:0.875rem;align-items:center;text-align:center"
          >
            <div style="color:var(--color-shared-red-foreground);font-size:0.875rem">
              We found problems in your submission:
            </div>
            <div
              style="width:100%;max-width:24rem;padding:0.875rem 1rem;border:1px dashed var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background2-rest);text-align:left"
            >
              <div>Email address is required</div>
              <div>Password must be at least 8 characters</div>
              <div>Phone number format is invalid</div>
            </div>
            <ui-button variant="primary" size="small">Review form</ui-button>
          </div>
        </ng-template>
      </ui-error-state>
    </div>
  `,
})
export class ErrorStateCustomContentDemoComponent {}
```

## Common error scenarios
```ts
import { Component } from '@angular/core';
import { ErrorStateComponent } from 'ui';

@Component({
  selector: 'app-error-state-scenarios-demo',
  standalone: true,
  imports: [ErrorStateComponent],
  template: `
    <div
      style="display:grid;grid-template-columns:repeat(auto-fit,minmax(15rem,1fr));gap:1rem;width:100%;max-width:58rem"
    >
      <div
        style="padding:1rem;border:1px solid var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background-rest)"
      >
        <p
          style="margin:0 0 0.75rem;font-size:0.875rem;font-weight:600;color:var(--color-neutral-foreground2-rest)"
        >
          Network
        </p>
        <ui-error-state
          title="Network connection failed"
          description="Unable to connect to the server. Check your internet connection and retry."
          icon="wifi_off"
        />
      </div>

      <div
        style="padding:1rem;border:1px solid var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background-rest)"
      >
        <p
          style="margin:0 0 0.75rem;font-size:0.875rem;font-weight:600;color:var(--color-neutral-foreground2-rest)"
        >
          Permissions
        </p>
        <ui-error-state
          title="Access denied"
          description="You do not have permission to view this resource. Contact an administrator if access is required."
          icon="shield"
        />
      </div>

      <div
        style="padding:1rem;border:1px solid var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background-rest)"
      >
        <p
          style="margin:0 0 0.75rem;font-size:0.875rem;font-weight:600;color:var(--color-neutral-foreground2-rest)"
        >
          Missing resource
        </p>
        <ui-error-state
          title="Page not found"
          description="The resource you requested no longer exists or the link is outdated."
          icon="document_dismiss"
        />
      </div>
    </div>
  `,
})
export class ErrorStateScenariosDemoComponent {}
```

## Embedded panel or view layout
```ts
import { Component } from '@angular/core';
import { ButtonComponent, ErrorStateComponent, TextComponent } from 'ui';

@Component({
  selector: 'app-error-state-panel-layout-demo',
  standalone: true,
  imports: [ButtonComponent, ErrorStateComponent, TextComponent],
  template: `
    <div
      style="display:flex;flex-direction:column;gap:1rem;width:100%;max-width:60rem;padding:1rem;border:1px solid var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background-rest)"
    >
      <div
        style="display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:0.75rem"
      >
        <ui-text placeholder="Search activity..." style="width:16rem" />
        <ui-button variant="secondary" appearance="outline">Filter</ui-button>
      </div>

      <div
        style="display:flex;align-items:center;justify-content:center;min-height:18rem;padding:1.5rem;border:1px dashed var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background2-rest)"
      >
        <ui-error-state
          title="Could not load activity"
          description="The activity panel failed to refresh. Retry the request or come back later."
          icon="history"
        />
      </div>
    </div>
  `,
})
export class ErrorStatePanelLayoutDemoComponent {}
```

## Accessibility

### Clear problem statement
An error state should clearly describe what failed and, when possible, what the user can do next. Avoid vague titles that communicate only that 'something happened.'

### Recovery actions
If actions are present, they should offer meaningful recovery rather than decorative options.

| Element | Guidance |
| --- | --- |
| Primary action | Use for the most direct recovery path, such as retrying. |
| Secondary action | Use for alternate paths such as contacting support or going elsewhere. |
| Custom projected controls | Keep them simple and semantically clear. |

### Icons and supporting content
Icons and custom projected details should reinforce the error message, not replace it. The main title and description must still communicate the state clearly on their own.
