@sentropic/design-system-svelte 0.34.66 → 0.34.68

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -32,15 +32,15 @@ Import the package CSS once at the app or preview boundary, then render componen
32
32
  </ThemeProvider>
33
33
  ```
34
34
 
35
- `ThemeProvider` defaults to the Sent Tech theme. Tenant themes can be supplied from `@sentropic/design-system-themes`, `@sentropic/design-system-theme-dsfr`, or `@sentropic/design-system-theme-carbon`.
35
+ `ThemeProvider` defaults to the Sent Tech theme. Tenant themes can be supplied from `@sentropic/design-system-themes`, `@sentropic/design-system-theme-dsfr`, `@sentropic/design-system-theme-canada`, or `@sentropic/design-system-theme-quebec`.
36
36
 
37
37
  ```svelte
38
38
  <script>
39
39
  import { ThemeProvider } from "@sentropic/design-system-svelte";
40
- import { carbonTheme } from "@sentropic/design-system-theme-carbon";
40
+ import { dsfrTheme } from "@sentropic/design-system-theme-dsfr";
41
41
  </script>
42
42
 
43
- <ThemeProvider theme={carbonTheme}>
43
+ <ThemeProvider theme={dsfrTheme}>
44
44
  <!-- your content -->
45
45
  </ThemeProvider>
46
46
  ```
@@ -7,6 +7,16 @@
7
7
  href: string;
8
8
  /** Marqué actif (souligné, aria-current=page). */
9
9
  active?: boolean;
10
+ /** Roles autorisés à voir l'item. Vide/undefined = visible par tous. */
11
+ roles?: string[];
12
+ /** Alias pratique pour un seul rôle autorisé. */
13
+ role?: string;
14
+ /** Coupe la navigation tout en gardant l'item visible/annoncé. */
15
+ disabled?: boolean;
16
+ ariaLabel?: string;
17
+ target?: string;
18
+ rel?: string;
19
+ onClick?: (event: MouseEvent) => void;
10
20
  }
11
21
 
12
22
  /** Une option du sélecteur de thème. */
@@ -38,6 +48,8 @@
38
48
  nav?: AppChromeNavItem[];
39
49
  /** aria-label de la nav principale. */
40
50
  navLabel?: string;
51
+ /** Roles de l'utilisateur courant pour filtrer les nav items gatés par rôle. */
52
+ userRoles?: string[];
41
53
 
42
54
  // ── Contrôle thème (contrôlé) ─────────────────────────────────────────────
43
55
  /** Options de thème. Vide => le sélecteur est masqué. */
@@ -118,6 +130,7 @@
118
130
  brandLabel,
119
131
  nav = [],
120
132
  navLabel = "Primary",
133
+ userRoles = [],
121
134
  themes = [],
122
135
  theme,
123
136
  onThemeChange,
@@ -172,6 +185,23 @@
172
185
  }
173
186
 
174
187
  const classes = () => ["st-appChrome", className].filter(Boolean).join(" ");
188
+ const visibleNav = $derived(
189
+ nav.filter((item) => {
190
+ const allowed = item.roles ?? (item.role ? [item.role] : []);
191
+ return allowed.length === 0 || allowed.some((role) => userRoles.includes(role));
192
+ }),
193
+ );
194
+
195
+ function navRel(item: AppChromeNavItem): string | undefined {
196
+ if (item.disabled) return undefined;
197
+ return item.rel ?? (item.target === "_blank" ? "noreferrer" : undefined);
198
+ }
199
+
200
+ function handleNavClick(event: MouseEvent, item: AppChromeNavItem, closeDrawer = false) {
201
+ if (item.disabled) event.preventDefault();
202
+ item.onClick?.(event);
203
+ if (!item.disabled && closeDrawer) onMobileMenuToggle?.();
204
+ }
175
205
 
176
206
  function closeMenus(target: EventTarget | null) {
177
207
  const el = target as Element | null;
@@ -207,11 +237,17 @@
207
237
 
208
238
  <!-- ── Nav principale ─────────────────────────────────────────────────────── -->
209
239
  {#snippet navContent()}
210
- {#each nav as item (item.href)}
240
+ {#each visibleNav as item (item.href)}
211
241
  <a
212
242
  class="st-appChrome__navLink st-appHeader__navLink"
213
- href={item.href}
243
+ class:st-appChrome__navLink--disabled={item.disabled}
244
+ href={item.disabled ? undefined : item.href}
214
245
  aria-current={item.active ? "page" : undefined}
246
+ aria-disabled={item.disabled ? "true" : undefined}
247
+ aria-label={item.ariaLabel}
248
+ target={item.disabled ? undefined : item.target}
249
+ rel={navRel(item)}
250
+ onclick={(event) => handleNavClick(event, item)}
215
251
  >
216
252
  {item.label}
217
253
  </a>
@@ -357,12 +393,17 @@
357
393
  {#if mobileMenuOpen}
358
394
  <nav id={drawerId} class="st-appChrome__drawer" aria-label={navLabel}>
359
395
  <div class="st-appChrome__drawerSection">
360
- {#each nav as item (item.href)}
396
+ {#each visibleNav as item (item.href)}
361
397
  <a
362
398
  class="st-appChrome__drawerLink"
363
- href={item.href}
399
+ class:st-appChrome__navLink--disabled={item.disabled}
400
+ href={item.disabled ? undefined : item.href}
364
401
  aria-current={item.active ? "page" : undefined}
365
- onclick={() => onMobileMenuToggle?.()}
402
+ aria-disabled={item.disabled ? "true" : undefined}
403
+ aria-label={item.ariaLabel}
404
+ target={item.disabled ? undefined : item.target}
405
+ rel={navRel(item)}
406
+ onclick={(event) => handleNavClick(event, item, true)}
366
407
  >
367
408
  {item.label}
368
409
  </a>
@@ -5,6 +5,16 @@ export interface AppChromeNavItem {
5
5
  href: string;
6
6
  /** Marqué actif (souligné, aria-current=page). */
7
7
  active?: boolean;
8
+ /** Roles autorisés à voir l'item. Vide/undefined = visible par tous. */
9
+ roles?: string[];
10
+ /** Alias pratique pour un seul rôle autorisé. */
11
+ role?: string;
12
+ /** Coupe la navigation tout en gardant l'item visible/annoncé. */
13
+ disabled?: boolean;
14
+ ariaLabel?: string;
15
+ target?: string;
16
+ rel?: string;
17
+ onClick?: (event: MouseEvent) => void;
8
18
  }
9
19
  /** Une option du sélecteur de thème. */
10
20
  export interface AppChromeThemeOption {
@@ -30,6 +40,8 @@ export interface AppChromeProps {
30
40
  nav?: AppChromeNavItem[];
31
41
  /** aria-label de la nav principale. */
32
42
  navLabel?: string;
43
+ /** Roles de l'utilisateur courant pour filtrer les nav items gatés par rôle. */
44
+ userRoles?: string[];
33
45
  /** Options de thème. Vide => le sélecteur est masqué. */
34
46
  themes?: AppChromeThemeOption[];
35
47
  /** Id du thème actif. */
@@ -1 +1 @@
1
- {"version":3,"file":"AppChrome.svelte.d.ts","sourceRoot":"","sources":["../src/lib/AppChrome.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,iDAAiD;AACjD,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wCAAwC;AACxC,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAC3D,MAAM,MAAM,eAAe,GAAG,IAAI,GAAG,IAAI,CAAC;AAE1C,MAAM,WAAW,cAAc;IAE7B,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC;IAGpB,+DAA+D;IAC/D,GAAG,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACzB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAGlB,yDAAyD;IACzD,MAAM,CAAC,EAAE,oBAAoB,EAAE,CAAC;IAChC,yBAAyB;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,aAAa,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,wCAAwC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;IAGpB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,4DAA4D;IAC5D,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACvD,0DAA0D;IAC1D,eAAe,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAGhE,2DAA2D;IAC3D,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,wCAAwC;IACxC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IACnD,yCAAyC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,qDAAqD;IACrD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iCAAiC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAGnB,sDAAsD;IACtD,cAAc,CAAC,EAAE,OAAO,CAAC;IAGzB,+CAA+C;IAC/C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,4CAA4C;IAC5C,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,mCAAmC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAuRH,QAAA,MAAM,SAAS,oDAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"AppChrome.svelte.d.ts","sourceRoot":"","sources":["../src/lib/AppChrome.svelte.ts"],"names":[],"mappings":"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"}
@@ -43,6 +43,15 @@ describe("AppChrome — navigation", () => {
43
43
  expect(links[1].getAttribute("aria-current")).toBeNull();
44
44
  expect(links[0].classList.contains("st-appHeader__navLink")).toBe(true);
45
45
  });
46
+ it("filters role-gated items and renders disabled nav without href", () => {
47
+ const { container } = render(AppChrome, {
48
+ props: { nav: [...nav, { label: "Admin", href: "/admin", role: "admin" }, { label: "Soon", href: "/soon", disabled: true }], userRoles: ["member"] },
49
+ });
50
+ const links = Array.from(container.querySelectorAll(".st-appChrome__navLink"));
51
+ expect(links.map((a) => a.textContent?.trim())).toEqual(["Vues", "Données", "Réglages", "Soon"]);
52
+ expect(links.at(-1)?.hasAttribute("href")).toBe(false);
53
+ expect(links.at(-1)?.getAttribute("aria-disabled")).toBe("true");
54
+ });
46
55
  });
47
56
  describe("AppChrome — contrôle thème", () => {
48
57
  it("shows the active theme label and fires onThemeChange on selection", async () => {
@@ -388,6 +388,15 @@
388
388
  font-weight: 650;
389
389
  }
390
390
 
391
+ :global(.st-appChrome__navLink--disabled),
392
+ :global(.st-appChrome__navLink--disabled:hover),
393
+ :global(.st-appChrome__navLink--disabled:focus-visible) {
394
+ color: var(--st-semantic-text-disabled, var(--st-semantic-text-secondary));
395
+ cursor: not-allowed;
396
+ opacity: 0.56;
397
+ pointer-events: none;
398
+ }
399
+
391
400
  /* --- Contrôle utilitaire canonique (pill : thème / langue / icône) --- */
392
401
  :global(.st-appHeader__control) {
393
402
  align-items: center;
@@ -1,6 +1,7 @@
1
1
  <script lang="ts">
2
2
  import { ChevronDown } from "@lucide/svelte";
3
3
  import type { HTMLAttributes } from "svelte/elements";
4
+ import Portal from "./Portal.svelte";
4
5
 
5
6
  export type DropdownOption = {
6
7
  label: string;
@@ -40,6 +41,7 @@
40
41
  let currentValue = $state<string | undefined>(undefined);
41
42
  let syncedOpen = $state<boolean | undefined>(undefined);
42
43
  let syncedValue = $state<string | undefined>(undefined);
44
+ let listEl: HTMLDivElement | undefined = $state();
43
45
  let listPos = $state({ top: 0, left: 0, width: 0 });
44
46
 
45
47
  const classes = () => ["st-dropdown", className].filter(Boolean).join(" ");
@@ -72,7 +74,7 @@
72
74
  function onWindowPointerDown(event: MouseEvent) {
73
75
  if (!expanded) return;
74
76
  const target = event.target as Node | null;
75
- if (host && target && !host.contains(target)) close();
77
+ if (target && !host?.contains(target) && !listEl?.contains(target)) close();
76
78
  }
77
79
 
78
80
  function onWindowScroll() {
@@ -122,7 +124,9 @@
122
124
  />
123
125
  </button>
124
126
  {#if expanded}
127
+ <Portal>
125
128
  <div
129
+ bind:this={listEl}
126
130
  class="st-dropdown__list"
127
131
  role="listbox"
128
132
  aria-label={label}
@@ -142,6 +146,7 @@
142
146
  </button>
143
147
  {/each}
144
148
  </div>
149
+ </Portal>
145
150
  {/if}
146
151
  </div>
147
152
 
@@ -1 +1 @@
1
- {"version":3,"file":"Dropdown.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Dropdown.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGpD,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,KAAK,aAAa,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC,GAAG;IAChF,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC,CAAC;AAgHJ,QAAA,MAAM,QAAQ,mDAAwC,CAAC;AACvD,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAC5C,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"Dropdown.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Dropdown.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAIpD,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,KAAK,aAAa,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC,GAAG;IAChF,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC,CAAC;AAoHJ,QAAA,MAAM,QAAQ,mDAAwC,CAAC;AACvD,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAC5C,eAAe,QAAQ,CAAC"}
@@ -158,7 +158,8 @@
158
158
  align-items: flex-start;
159
159
  background: var(--st-semantic-surface-subtle);
160
160
  border-left: 3px solid var(--st-semantic-border-strong);
161
- border-radius: var(--st-radius-sm, 0.25rem);
161
+ /* Accent latéral fort = coins carrés. Ne pas arrondir une carte/exergue à liseré. */
162
+ border-radius: 0;
162
163
  display: flex;
163
164
  gap: var(--st-spacing-2, 0.5rem);
164
165
  padding: var(--st-spacing-2, 0.5rem) var(--st-spacing-3, 0.75rem);
@@ -37,7 +37,8 @@
37
37
  --st-highlight-accent: var(--st-semantic-action-primary);
38
38
  background: var(--st-semantic-surface-subtle);
39
39
  border-left: 4px solid var(--st-highlight-accent);
40
- border-radius: var(--st-radius-md, 0.375rem);
40
+ /* Accent latéral fort = coins carrés. Ne pas arrondir une carte/exergue à liseré. */
41
+ border-radius: 0;
41
42
  color: var(--st-semantic-text-primary);
42
43
  padding: var(--st-spacing-4, 1rem);
43
44
  }
@@ -234,9 +234,11 @@
234
234
  padding: var(--st-spacing-6, 1.5rem);
235
235
  }
236
236
 
237
- /* Accent catégoriel : liseré coloré à gauche. */
237
+ /* Accent catégoriel : liseré conservé, mais carte carrée pour éviter
238
+ le liseré arrondi sur conteneur arrondi. */
238
239
  .st-kpiCard--toned {
239
240
  border-inline-start-width: var(--st-spacing-1, 0.25rem);
241
+ border-radius: 0;
240
242
  }
241
243
 
242
244
  .st-kpiCard__label {
@@ -254,11 +254,21 @@
254
254
  width: 100%;
255
255
  }
256
256
 
257
- /* Opt-in accent bar: reserve the 2px gutter only when enabled so text never
258
- shifts on selection. */
257
+ /* Opt-in accent bar: reserve a 2px gutter without attaching a border to the
258
+ rounded host. The selected accent is painted by a square pseudo-element so
259
+ no one-sided stroke follows the row radius. */
259
260
  .st-selectableRow--accentBar {
260
261
  padding-left: calc(0.75rem - 2px);
261
- border-left: 2px solid transparent;
262
+ }
263
+
264
+ .st-selectableRow--accentBar::before {
265
+ background: transparent;
266
+ block-size: 100%;
267
+ content: "";
268
+ inline-size: 2px;
269
+ inset-block: 0;
270
+ inset-inline-start: 0;
271
+ position: absolute;
262
272
  }
263
273
 
264
274
  .st-selectableRow:hover:not(.st-selectableRow--disabled):not(.st-selectableRow--selected) {
@@ -291,8 +301,8 @@
291
301
  }
292
302
 
293
303
  /* The left accent bar paints only when opt-in AND selected. */
294
- .st-selectableRow--accentBar.st-selectableRow--selected {
295
- border-left-color: var(
304
+ .st-selectableRow--accentBar.st-selectableRow--selected::before {
305
+ background: var(
296
306
  --st-component-selectableRow-selectedAccent,
297
307
  var(--st-semantic-action-primary, #2563eb)
298
308
  );
@@ -305,7 +305,7 @@
305
305
  .st-streamingMessage__reasoning {
306
306
  background: var(--st-component-chatMessage-reasoningBackground, var(--st-semantic-surface-subtle));
307
307
  border-left: 2px solid var(--st-semantic-border-subtle);
308
- border-radius: var(--st-component-control-radius, 0.375rem);
308
+ border-radius: 0;
309
309
  margin: 0 0 0.5rem;
310
310
  padding: 0.4rem 0.6rem;
311
311
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentropic/design-system-svelte",
3
- "version": "0.34.66",
3
+ "version": "0.34.68",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -27,7 +27,6 @@
27
27
  ],
28
28
  "dependencies": {
29
29
  "@lucide/svelte": "^0.562.0",
30
- "@sentropic/design-system-theme-carbon": "0.2.2",
31
30
  "@sentropic/design-system-themes": "0.11.0"
32
31
  },
33
32
  "peerDependencies": {
@@ -39,7 +38,6 @@
39
38
  "test": "vitest run src"
40
39
  },
41
40
  "devDependencies": {
42
- "@sentropic/design-system-theme-carbon": "0.2.2",
43
41
  "@sentropic/design-system-theme-dsfr": "0.2.2",
44
42
  "@sentropic/design-system-themes": "0.11.0",
45
43
  "@sveltejs/package": "^2.5.0",