Installation - Angular

Cette page documente l’installation de Ori dans une app Angular (standalone). Pour React/Next.js, voir la section dédiée du Storybook React.

Prérequis

  • Node.js 20+
  • Angular 20+ (avec composants standalone)
  • Tailwind CSS v3

1. Installer les paquets

pnpm add @govpf/ori-angular @govpf/ori-tokens @govpf/ori-tailwind-preset
pnpm add @angular/cdk lucide-angular
pnpm add -D autoprefixer postcss tailwindcss

@angular/cdk est requis pour le focus-trap des <ori-dialog> / <ori-alert-dialog> et la portal du <ori-dropdown-menu>. lucide-angular est requis pour les icônes utilisées par certains composants (Alert, FileUpload, Toast, DropdownMenu, etc.).

Ne pas installer @govpf/ori-css côté Angular tant que #88 n’est pas résolu : son dist/ori.css référence des polices via chemin relatif cassé dans la version publiée. Le scaffold ci-dessous régénère les classes .ori-* à la volée via le preset Tailwind, c’est le pattern utilisé par apps/storybook-angular et apps/demo-portail.

2. Brancher le preset Tailwind

tailwind.config.js (export ESM par défaut, pas d’import nommé) :

import preset from '@govpf/ori-tailwind-preset';

/** @type {import('tailwindcss').Config} */
export default {
  presets: [preset],
  content: [
    './src/**/*.{ts,html}',
    // Indispensable : sans ça, Tailwind ne voit pas les classes
    // utilisées dans les templates Angular compilés.
    './node_modules/@govpf/ori-angular/**/*.mjs',
  ],
  // Garde-fou : conserve toutes les classes ori-* même si le scanner
  // de contenu rate quelques utilisations dynamiques.
  safelist: [{ pattern: /^ori-/ }],
};

postcss.config.js :

export default {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
};

3. Importer tokens + Tailwind dans styles.css

/* Chemins relatifs vers @govpf/ori-tokens : nécessaire parce que
 * postcss-import ne résout pas les "exports" du package, et les
 * @font-face de tokens/src/fonts.css référencent des TTF voisins
 * (../assets/fonts/) qui ne sont accessibles que via chemin relatif. */
@import '../../node_modules/@govpf/ori-tokens/src/fonts.css';
@import '../../node_modules/@govpf/ori-tokens/build/css/tokens.css';
@import '../../node_modules/@govpf/ori-tokens/src/dark.css';

@tailwind base;
@tailwind components;
@tailwind utilities;

L’ordre importe : tokens d’abord (variables CSS + fonts), puis Tailwind layers (base reset, components .ori-*, utilities).

4. Bootstrap standalone

src/main.ts :

import 'zone.js';
import { bootstrapApplication } from '@angular/platform-browser';
import { provideAnimations } from '@angular/platform-browser/animations';
import { AppComponent } from './app/app.component';

bootstrapApplication(AppComponent, {
  providers: [provideAnimations()],
}).catch((err) => console.error(err));

provideAnimations() est requis par les composants qui utilisent @angular/cdk (dialog, dropdown, tooltip).

5. Utiliser un composant

Composants standalone, à importer dans le tableau imports du composant qui les consomme :

import { Component } from '@angular/core';
import { OriButtonComponent } from '@govpf/ori-angular';

@Component({
  selector: 'app-home',
  standalone: true,
  imports: [OriButtonComponent],
  template: `<ori-button variant="primary">Démarrer une démarche</ori-button>`,
})
export class HomeComponent {}

Pièges strict-templates à connaître

strictTemplates: true est activé par défaut dans tsconfig.json des scaffolds Angular CLI modernes (et obligatoire pour apps/storybook-angular et toute app du monorepo Ori). Il refuse plusieurs patterns courants quand on consomme des composants Ori :

Inputs booléens : [x]="true", jamais x seul

<!-- KO : passe la string vide "" au lieu de true -->
<ori-notification dismissible>...</ori-notification>

<!-- OK -->
<ori-notification [dismissible]="true">...</ori-notification>

S’applique à dismissible, iconOnlyButton, striped, loading, hideLabel, hideCrest, removable, etc.

Variant et statut indexés : passer par un helper typé

<!-- KO : row est typé `any` dans <ng-template let-row>, donc
     STATUT_VARIANT[row.statut] devient un index `any` -> rejeté -->
<ori-tag [variant]="STATUT_VARIANT[row.statut]">{{ STATUT_LABEL[row.statut] }}</ori-tag>

Solution : exposer des méthodes typées sur le composant.

statutVariant(row: Dossier) { return STATUT_VARIANT[row.statut]; }
statutLabel(row: Dossier)   { return STATUT_LABEL[row.statut]; }
<ori-tag [variant]="statutVariant(row)">{{ statutLabel(row) }}</ori-tag>

cellTemplate du <ori-table> : typer le TemplateRef

OriTableColumn.cellTemplate attend TemplateRef<{ $implicit: TRow; index: number }>. Avec une typage plus large (TemplateRef<unknown>) le compilateur refuse :

TS2322: Type 'TemplateRef<unknown>' is not assignable to
        type 'TemplateRef<{ $implicit: Dossier; index: number; }>'.

Bonne forme :

@ViewChild('statutTpl', { static: true })
statutTpl!: TemplateRef<{ $implicit: Dossier; index: number }>;

ngAfterViewInit() {
  this.columns.set([
    { key: 'statut', label: 'Statut', cellTemplate: this.statutTpl },
    /* ... */
  ]);
}
<ng-template #statutTpl let-row let-i="index">
  <ori-tag [variant]="statutVariant(row)">{{ statutLabel(row) }}</ori-tag>
</ng-template>

Forms réactifs

Les composants form de Ori (<ori-input>, <ori-checkbox>, <ori-select>, etc.) sont compatibles avec [(ngModel)] via le couple [value] / (valueChange) :

<ori-input
  label="Nom"
  [required]="true"
  [(value)]="model.name"
></ori-input>

Pour ReactiveFormsModule, l’app peut wrapper ou accéder via ViewChild. Un ControlValueAccessor natif n’est pas fourni par le DS pour rester découplé de @angular/forms (les apps qui utilisent des Signals exclusivement n’en ont pas besoin). Voir Patterns Angular pour un wrapper type.

Theme sombre

Le DS supporte light/dark via data-theme="dark" sur l’élément racine :

document.documentElement.setAttribute('data-theme', 'dark');

Exemple complet

Voir apps/example-agent/ dans le monorepo : back-office d’instruction de dossiers consommant <ori-app-shell>, <ori-table> (sélection multiple + tri + cellTemplate), <ori-dropdown-menu>, <ori-alert-dialog>, <ori-notification>, <ori-search-bar>, <ori-statistic> et <ori-tag>. Toute la stack scaffold (angular.json, tsconfig, tailwind.config, styles.css) est en place.

Voir aussi