@sia-ui/cli 0.3.2 → 0.4.0
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/CHANGELOG.md +7 -0
- package/README.md +40 -19
- package/dist/registry/package/components/AppShell/index.tsx +101 -7
- package/dist/registry/package/components/AppShell/styles.css +87 -0
- package/dist/registry/package/components/Drawer/index.tsx +9 -5
- package/dist/registry/package/components/Drawer/styles.css +53 -28
- package/dist/registry/package/components/Icons/index.tsx +9 -0
- package/dist/registry/package/components/Sidebar/index.tsx +23 -3
- package/dist/registry/package/components/Sidebar/styles.css +1 -13
- package/dist/registry/package/components/Toggle/styles.css +3 -2
- package/dist/registry/styles/sia-ui.css +11 -0
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
<p align="center"><img src="https://beatjo.github.io/sia-ui-site/brand/sia-ui-logo.png" alt="SIA UI" width="320"></p>
|
|
2
|
-
|
|
1
|
+
<p align="center"><img src="https://beatjo.github.io/sia-ui-site/brand/sia-ui-logo.png" alt="SIA UI" width="320"></p>
|
|
2
|
+
|
|
3
3
|
# @sia-ui/cli
|
|
4
4
|
|
|
5
5
|
Installer les composants SIA UI dans une application, comme shadcn/ui.
|
|
@@ -51,22 +51,42 @@ add src/components/DataTable/styles.css
|
|
|
51
51
|
|
|
52
52
|
Une chose s'écrit au niveau le plus bas où elle a du sens, et une seule fois.
|
|
53
53
|
Voir [la documentation](https://beatjo.github.io/sia-ui-site).
|
|
54
|
-
|
|
55
|
-
## Contribuer
|
|
56
|
-
|
|
57
|
-
Le code source principal de SIA UI est privé pour le moment. Les retours publics passent par le dépôt `BeatJo/sia-ui-site` : bugs, demandes de composants, corrections de documentation et questions d'usage.
|
|
58
|
-
|
|
59
|
-
- Signaler un bug : https://github.com/BeatJo/sia-ui-site/issues
|
|
60
|
-
- Lire la documentation : https://beatjo.github.io/sia-ui-site/
|
|
61
|
-
- Voir la démonstration : https://beatjo.github.io/sia-ui-site/preview/
|
|
62
|
-
|
|
63
|
-
Les contributions directes au code des packages se font sur invitation dans le dépôt source privé.
|
|
64
|
-
## Journal des changements
|
|
65
|
-
|
|
66
|
-
Le contenu ci-dessous reprend intégralement `CHANGELOG.md` pour rester visible sur npm.
|
|
67
|
-
|
|
54
|
+
|
|
55
|
+
## Contribuer
|
|
56
|
+
|
|
57
|
+
Le code source principal de SIA UI est privé pour le moment. Les retours publics passent par le dépôt `BeatJo/sia-ui-site` : bugs, demandes de composants, corrections de documentation et questions d'usage.
|
|
58
|
+
|
|
59
|
+
- Signaler un bug : https://github.com/BeatJo/sia-ui-site/issues
|
|
60
|
+
- Lire la documentation : https://beatjo.github.io/sia-ui-site/
|
|
61
|
+
- Voir la démonstration : https://beatjo.github.io/sia-ui-site/preview/
|
|
62
|
+
|
|
63
|
+
Les contributions directes au code des packages se font sur invitation dans le dépôt source privé.
|
|
64
|
+
## Journal des changements
|
|
65
|
+
|
|
66
|
+
Le contenu ci-dessous reprend intégralement `CHANGELOG.md` pour rester visible sur npm.
|
|
67
|
+
|
|
68
|
+
<!-- sia:changelog:start -->
|
|
68
69
|
# @sia-ui/cli
|
|
69
70
|
|
|
71
|
+
## 0.4.0
|
|
72
|
+
|
|
73
|
+
### Minor Changes
|
|
74
|
+
|
|
75
|
+
- Aligne tous les packages publics SIA UI sur la version 0.4.0 afin de fournir
|
|
76
|
+
un ensemble cohérent à installer, documenter et maintenir.
|
|
77
|
+
|
|
78
|
+
## 0.3.2
|
|
79
|
+
|
|
80
|
+
### Patch Changes
|
|
81
|
+
|
|
82
|
+
- Ajoute l’identité visuelle officielle de SIA UI et améliore la documentation publique, les changelogs et les ressources de contribution.
|
|
83
|
+
|
|
84
|
+
## 0.3.1
|
|
85
|
+
|
|
86
|
+
### Patch Changes
|
|
87
|
+
|
|
88
|
+
- Expose public contribution flow on npm
|
|
89
|
+
|
|
70
90
|
## 0.3.0
|
|
71
91
|
|
|
72
92
|
### Minor Changes
|
|
@@ -226,8 +246,9 @@ Le contenu ci-dessous reprend intégralement `CHANGELOG.md` pour rester visible
|
|
|
226
246
|
|
|
227
247
|
### Patch Changes
|
|
228
248
|
|
|
229
|
-
- Include component styles when installing registry components
|
|
230
|
-
|
|
231
|
-
|
|
249
|
+
- Include component styles when installing registry components
|
|
250
|
+
<!-- sia:changelog:end -->
|
|
251
|
+
|
|
252
|
+
## Licence
|
|
232
253
|
|
|
233
254
|
MIT
|
|
@@ -3,6 +3,8 @@ import {
|
|
|
3
3
|
useMemo,
|
|
4
4
|
useState,
|
|
5
5
|
type CSSProperties,
|
|
6
|
+
type ElementType,
|
|
7
|
+
type HTMLAttributes,
|
|
6
8
|
type ReactNode,
|
|
7
9
|
} from "react";
|
|
8
10
|
import { cn } from "@sia-ui/utils";
|
|
@@ -53,6 +55,87 @@ export type AppShellMobileNav = "drawer" | "tabs" | "both";
|
|
|
53
55
|
|
|
54
56
|
export type AppShellContentWidth = "wide" | "narrow" | "full";
|
|
55
57
|
|
|
58
|
+
export interface AppShellBrandProps extends HTMLAttributes<HTMLDivElement> {
|
|
59
|
+
/** Symbole conservé lorsque la navigation devient un rail. */
|
|
60
|
+
icon: ReactNode;
|
|
61
|
+
/** Nom du produit, masqué automatiquement dans le rail. */
|
|
62
|
+
name: ReactNode;
|
|
63
|
+
/** Ligne secondaire facultative, masquée avec le nom. */
|
|
64
|
+
description?: ReactNode;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Identité de produit adaptée au rail de l'`AppShell`.
|
|
69
|
+
*
|
|
70
|
+
* L'application fournit le symbole et le texte une seule fois. Le composant
|
|
71
|
+
* masque sa copie dès que son parent reçoit `data-collapsed`.
|
|
72
|
+
*/
|
|
73
|
+
export function AppShellBrand({
|
|
74
|
+
icon,
|
|
75
|
+
name,
|
|
76
|
+
description,
|
|
77
|
+
className,
|
|
78
|
+
...props
|
|
79
|
+
}: AppShellBrandProps) {
|
|
80
|
+
return (
|
|
81
|
+
<div className={cn("sia-shell-brand", className)} {...props}>
|
|
82
|
+
<span className="sia-shell-brand__icon" aria-hidden="true">
|
|
83
|
+
{icon}
|
|
84
|
+
</span>
|
|
85
|
+
<span className="sia-shell-brand__copy">
|
|
86
|
+
<span className="sia-shell-brand__name">{name}</span>
|
|
87
|
+
{description !== undefined && (
|
|
88
|
+
<span className="sia-shell-brand__description">{description}</span>
|
|
89
|
+
)}
|
|
90
|
+
</span>
|
|
91
|
+
</div>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface AppShellRailItemProps extends HTMLAttributes<HTMLElement> {
|
|
96
|
+
/** Élément rendu : contenu simple, action ou lien. */
|
|
97
|
+
as?: "div" | "button" | "a";
|
|
98
|
+
/** Symbole toujours visible dans le rail. */
|
|
99
|
+
icon: ReactNode;
|
|
100
|
+
/** Libellé masqué visuellement dans le rail et conservé comme nom accessible. */
|
|
101
|
+
label: string;
|
|
102
|
+
href?: string;
|
|
103
|
+
type?: "button" | "submit" | "reset";
|
|
104
|
+
disabled?: boolean;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Contenu icône + libellé qui s'adapte automatiquement au rail. */
|
|
108
|
+
export function AppShellRailItem({
|
|
109
|
+
as = "div",
|
|
110
|
+
icon,
|
|
111
|
+
label,
|
|
112
|
+
className,
|
|
113
|
+
href,
|
|
114
|
+
type = "button",
|
|
115
|
+
disabled,
|
|
116
|
+
...props
|
|
117
|
+
}: AppShellRailItemProps) {
|
|
118
|
+
const Component: ElementType = as;
|
|
119
|
+
const elementProps = {
|
|
120
|
+
...props,
|
|
121
|
+
...(as === "a" && href ? { href } : {}),
|
|
122
|
+
...(as === "button" ? { type, disabled } : {}),
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
return (
|
|
126
|
+
<Component
|
|
127
|
+
className={cn("sia-shell-rail-item", className)}
|
|
128
|
+
aria-label={props["aria-label"] ?? (as !== "div" ? label : undefined)}
|
|
129
|
+
{...elementProps}
|
|
130
|
+
>
|
|
131
|
+
<span className="sia-shell-rail-item__icon" aria-hidden="true">
|
|
132
|
+
{icon}
|
|
133
|
+
</span>
|
|
134
|
+
<span className="sia-shell-rail-item__label">{label}</span>
|
|
135
|
+
</Component>
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
56
139
|
export interface AppShellProps {
|
|
57
140
|
nav: SidebarEntry[];
|
|
58
141
|
children: ReactNode;
|
|
@@ -97,8 +180,8 @@ export interface AppShellProps {
|
|
|
97
180
|
/**
|
|
98
181
|
* En tête de barre latérale : logo, nom du produit, sélecteur d'entité.
|
|
99
182
|
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
183
|
+
* `AppShellBrand` masque son texte automatiquement dans le rail. Un contenu
|
|
184
|
+
* entièrement personnalisé reçoit toujours `data-collapsed` sur son parent.
|
|
102
185
|
*/
|
|
103
186
|
brand?: ReactNode;
|
|
104
187
|
|
|
@@ -107,8 +190,8 @@ export interface AppShellProps {
|
|
|
107
190
|
*
|
|
108
191
|
* C'est la place de la déconnexion et des réglages du compte — ce qui sort
|
|
109
192
|
* de l'application, par opposition à l'en-tête, réservé à ce qui agit sur
|
|
110
|
-
* l'écran courant.
|
|
111
|
-
*
|
|
193
|
+
* l'écran courant. `AppShellRailItem` masque son libellé automatiquement ;
|
|
194
|
+
* un contenu personnalisé peut encore lire `data-collapsed` sur son parent.
|
|
112
195
|
*/
|
|
113
196
|
sidebarFooter?: ReactNode;
|
|
114
197
|
|
|
@@ -306,7 +389,9 @@ export function AppShell({
|
|
|
306
389
|
{/* Sur petit écran, la barre latérale n'a pas la place de rester
|
|
307
390
|
ouverte : elle devient un tiroir. Sans lui, l'arborescence complète
|
|
308
391
|
ne serait atteignable que par « Plus », ce qui ne se devine pas. */}
|
|
309
|
-
{!compact && !masquee &&
|
|
392
|
+
{!compact && !masquee && (
|
|
393
|
+
<aside className="sia-shell__aside">{barre}</aside>
|
|
394
|
+
)}
|
|
310
395
|
|
|
311
396
|
<div className="sia-shell__main">
|
|
312
397
|
{(header || collapsible !== false || (compact && montrerTiroir)) && (
|
|
@@ -348,7 +433,12 @@ export function AppShell({
|
|
|
348
433
|
</header>
|
|
349
434
|
)}
|
|
350
435
|
|
|
351
|
-
<main
|
|
436
|
+
<main
|
|
437
|
+
className={cn(
|
|
438
|
+
"sia-shell__content",
|
|
439
|
+
`sia-shell__content--${contentWidth}`,
|
|
440
|
+
)}
|
|
441
|
+
>
|
|
352
442
|
{page && <div className="sia-shell__page">{page}</div>}
|
|
353
443
|
{children}
|
|
354
444
|
</main>
|
|
@@ -374,7 +464,11 @@ export function AppShell({
|
|
|
374
464
|
size="sm"
|
|
375
465
|
className="sia-shell__drawer"
|
|
376
466
|
>
|
|
377
|
-
|
|
467
|
+
<Drawer.Header>
|
|
468
|
+
<Drawer.Title>Navigation</Drawer.Title>
|
|
469
|
+
<Drawer.Close />
|
|
470
|
+
</Drawer.Header>
|
|
471
|
+
<Drawer.Body>{barre}</Drawer.Body>
|
|
378
472
|
</Drawer>
|
|
379
473
|
)}
|
|
380
474
|
</div>
|
|
@@ -57,6 +57,92 @@
|
|
|
57
57
|
padding: .5rem;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
/* Les contenus standards de la barre connaissent le rail. L'application
|
|
61
|
+
fournit une icône et un texte une seule fois ; AppShell porte l'état sur le
|
|
62
|
+
parent, et ces primitives prennent en charge la présentation. */
|
|
63
|
+
.sia-shell-brand,
|
|
64
|
+
.sia-shell-rail-item {
|
|
65
|
+
display: flex;
|
|
66
|
+
align-items: center;
|
|
67
|
+
gap: .625rem;
|
|
68
|
+
min-width: 0;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.sia-shell-brand { padding: .25rem; }
|
|
72
|
+
|
|
73
|
+
.sia-shell-brand__icon {
|
|
74
|
+
display: grid;
|
|
75
|
+
place-items: center;
|
|
76
|
+
flex: none;
|
|
77
|
+
width: 2.75rem;
|
|
78
|
+
height: 2.75rem;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.sia-shell-brand__icon > img,
|
|
82
|
+
.sia-shell-brand__icon > svg {
|
|
83
|
+
max-width: 100%;
|
|
84
|
+
max-height: 100%;
|
|
85
|
+
object-fit: contain;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.sia-shell-brand__copy { min-width: 0; }
|
|
89
|
+
.sia-shell-brand__name,
|
|
90
|
+
.sia-shell-brand__description {
|
|
91
|
+
display: block;
|
|
92
|
+
overflow: hidden;
|
|
93
|
+
text-overflow: ellipsis;
|
|
94
|
+
white-space: nowrap;
|
|
95
|
+
}
|
|
96
|
+
.sia-shell-brand__name { font-weight: 700; }
|
|
97
|
+
.sia-shell-brand__description {
|
|
98
|
+
margin-top: .1rem;
|
|
99
|
+
color: var(--sia-muted);
|
|
100
|
+
font-size: .72rem;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.sia-shell-rail-item {
|
|
104
|
+
width: 100%;
|
|
105
|
+
padding: .375rem;
|
|
106
|
+
border: 0;
|
|
107
|
+
border-radius: var(--sia-radius);
|
|
108
|
+
background: transparent;
|
|
109
|
+
color: var(--sia-muted);
|
|
110
|
+
font: inherit;
|
|
111
|
+
font-size: .75rem;
|
|
112
|
+
text-decoration: none;
|
|
113
|
+
}
|
|
114
|
+
.sia-shell-rail-item:is(button, a) { cursor: pointer; }
|
|
115
|
+
.sia-shell-rail-item:is(button, a):hover {
|
|
116
|
+
background: var(--sia-surface-raised, var(--sia-surface));
|
|
117
|
+
color: var(--sia-foreground);
|
|
118
|
+
}
|
|
119
|
+
.sia-shell-rail-item:disabled { opacity: .55; cursor: not-allowed; }
|
|
120
|
+
.sia-shell-rail-item:is(button, a):focus-visible {
|
|
121
|
+
outline: 2px solid var(--sia-primary);
|
|
122
|
+
outline-offset: 2px;
|
|
123
|
+
}
|
|
124
|
+
.sia-shell-rail-item__icon {
|
|
125
|
+
display: grid;
|
|
126
|
+
place-items: center;
|
|
127
|
+
flex: none;
|
|
128
|
+
width: 1.5rem;
|
|
129
|
+
height: 1.5rem;
|
|
130
|
+
}
|
|
131
|
+
.sia-shell-rail-item__label {
|
|
132
|
+
min-width: 0;
|
|
133
|
+
overflow: hidden;
|
|
134
|
+
text-overflow: ellipsis;
|
|
135
|
+
white-space: nowrap;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
[data-collapsed] .sia-shell-brand,
|
|
139
|
+
[data-collapsed] .sia-shell-rail-item {
|
|
140
|
+
justify-content: center;
|
|
141
|
+
gap: 0;
|
|
142
|
+
}
|
|
143
|
+
[data-collapsed] .sia-shell-brand__copy,
|
|
144
|
+
[data-collapsed] .sia-shell-rail-item__label { display: none; }
|
|
145
|
+
|
|
60
146
|
.sia-shell__main {
|
|
61
147
|
display: flex;
|
|
62
148
|
flex-direction: column;
|
|
@@ -154,6 +240,7 @@
|
|
|
154
240
|
padding-bottom: calc(var(--sia-shell-tabs) + env(safe-area-inset-bottom, 0px));
|
|
155
241
|
}
|
|
156
242
|
|
|
243
|
+
.sia-shell__drawer .sia-drawer-body { flex:1; min-height:0; padding:.5rem; overflow:hidden; }
|
|
157
244
|
.sia-shell__drawer .sia-sidebar { height: 100%; }
|
|
158
245
|
|
|
159
246
|
/* ── La barre d'onglets ─────────────────────────────────────────────────── */
|
|
@@ -12,6 +12,7 @@ import "./styles.css";
|
|
|
12
12
|
import { useOutsideClick } from "@sia-ui/react";
|
|
13
13
|
import { DrawerContext } from "./context";
|
|
14
14
|
import { overlayStack, useDisclosureState } from "@sia-ui/headless";
|
|
15
|
+
import { XIcon } from "../Icons";
|
|
15
16
|
/** Ce que la réf impérative expose — ouvrir un tiroir depuis l'extérieur. */
|
|
16
17
|
export type DrawerRef = {
|
|
17
18
|
open: () => void;
|
|
@@ -65,9 +66,10 @@ export const Drawer = forwardRef<DrawerRef, IDrawerProps>(
|
|
|
65
66
|
closeOnOutsideClick = true,
|
|
66
67
|
closeOnEsc = true,
|
|
67
68
|
children,
|
|
69
|
+
className,
|
|
68
70
|
...rest
|
|
69
71
|
},
|
|
70
|
-
ref
|
|
72
|
+
ref,
|
|
71
73
|
) => {
|
|
72
74
|
// Ouverture, fermeture et phase de sortie vivent dans @sia-ui/headless :
|
|
73
75
|
// rien là-dedans n'est propre au DOM, et le pendant mobile réutilisera la
|
|
@@ -96,7 +98,7 @@ export const Drawer = forwardRef<DrawerRef, IDrawerProps>(
|
|
|
96
98
|
toggle: () => (isOpen ? doClose() : doOpen()),
|
|
97
99
|
isOpen: () => isOpen,
|
|
98
100
|
}),
|
|
99
|
-
[isOpen, open]
|
|
101
|
+
[isOpen, open],
|
|
100
102
|
);
|
|
101
103
|
|
|
102
104
|
/* Overlay stack */
|
|
@@ -150,6 +152,7 @@ export const Drawer = forwardRef<DrawerRef, IDrawerProps>(
|
|
|
150
152
|
<DrawerContext.Provider value={{ close: doClose }}>
|
|
151
153
|
<div
|
|
152
154
|
className="sia-drawer-root"
|
|
155
|
+
data-state={state}
|
|
153
156
|
style={{ zIndex: zIndexRef.current ?? undefined }}
|
|
154
157
|
>
|
|
155
158
|
<div className="sia-drawer-overlay" />
|
|
@@ -163,7 +166,8 @@ export const Drawer = forwardRef<DrawerRef, IDrawerProps>(
|
|
|
163
166
|
"sia-drawer",
|
|
164
167
|
`sia-drawer-${position}`,
|
|
165
168
|
`sia-drawer-${size}`,
|
|
166
|
-
state === "closing" && "is-closing"
|
|
169
|
+
state === "closing" && "is-closing",
|
|
170
|
+
className,
|
|
167
171
|
)}
|
|
168
172
|
{...rest}
|
|
169
173
|
>
|
|
@@ -173,7 +177,7 @@ export const Drawer = forwardRef<DrawerRef, IDrawerProps>(
|
|
|
173
177
|
</DrawerContext.Provider>
|
|
174
178
|
</Portal>
|
|
175
179
|
);
|
|
176
|
-
}
|
|
180
|
+
},
|
|
177
181
|
) as DrawerComponent;
|
|
178
182
|
|
|
179
183
|
Drawer.displayName = "SiaDrawer";
|
|
@@ -205,7 +209,7 @@ export function DrawerClose() {
|
|
|
205
209
|
onClick={ctx.close}
|
|
206
210
|
aria-label="Fermer"
|
|
207
211
|
>
|
|
208
|
-
|
|
212
|
+
<XIcon aria-hidden="true" />
|
|
209
213
|
</button>
|
|
210
214
|
);
|
|
211
215
|
}
|
|
@@ -7,17 +7,24 @@
|
|
|
7
7
|
.sia-drawer-overlay {
|
|
8
8
|
position: absolute;
|
|
9
9
|
inset: 0;
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
z-index: 0;
|
|
11
|
+
background: rgb(2 6 23 / .52);
|
|
12
|
+
animation: sia-drawer-fade-in var(--sia-duration-base) var(--sia-easing-entrance) both;
|
|
12
13
|
}
|
|
14
|
+
.sia-drawer-root[data-state="closing"] .sia-drawer-overlay { animation:sia-drawer-fade-out var(--sia-duration-base) var(--sia-easing-exit) both; }
|
|
13
15
|
|
|
14
16
|
.sia-drawer {
|
|
15
17
|
position: absolute;
|
|
16
|
-
|
|
18
|
+
z-index: 1;
|
|
19
|
+
color: var(--sia-foreground, #0f172a);
|
|
20
|
+
background: var(--sia-background, #fff);
|
|
21
|
+
border: 1px solid var(--sia-border, #e2e8f0);
|
|
17
22
|
display: flex;
|
|
18
23
|
flex-direction: column;
|
|
19
|
-
width: var(--sia-drawer-width);
|
|
20
|
-
|
|
24
|
+
width: min(var(--sia-drawer-width), calc(100vw - 2rem));
|
|
25
|
+
overflow: hidden;
|
|
26
|
+
isolation: isolate;
|
|
27
|
+
box-shadow: 0 20px 50px rgb(2 6 23 / .24);
|
|
21
28
|
will-change: transform;
|
|
22
29
|
}
|
|
23
30
|
|
|
@@ -27,7 +34,7 @@
|
|
|
27
34
|
right: 0;
|
|
28
35
|
top: 0;
|
|
29
36
|
height: 100%;
|
|
30
|
-
animation:
|
|
37
|
+
animation: sia-drawer-in-right var(--sia-duration-slow) var(--sia-easing-entrance) both;
|
|
31
38
|
}
|
|
32
39
|
|
|
33
40
|
/* LEFT */
|
|
@@ -35,7 +42,7 @@
|
|
|
35
42
|
left: 0;
|
|
36
43
|
top: 0;
|
|
37
44
|
height: 100%;
|
|
38
|
-
animation:
|
|
45
|
+
animation: sia-drawer-in-left var(--sia-duration-slow) var(--sia-easing-entrance) both;
|
|
39
46
|
}
|
|
40
47
|
|
|
41
48
|
/* TOP */
|
|
@@ -43,9 +50,11 @@
|
|
|
43
50
|
top: 0;
|
|
44
51
|
left: 0;
|
|
45
52
|
right: 0;
|
|
46
|
-
|
|
53
|
+
width: 100%;
|
|
54
|
+
max-width: 100%;
|
|
55
|
+
max-height: min(80vh, 48rem);
|
|
47
56
|
--sia-drawer-width: 100% !important;
|
|
48
|
-
animation:
|
|
57
|
+
animation: sia-drawer-in-top var(--sia-duration-slow) var(--sia-easing-entrance) both;
|
|
49
58
|
}
|
|
50
59
|
|
|
51
60
|
/* BOTTOM */
|
|
@@ -53,9 +62,11 @@
|
|
|
53
62
|
bottom: 0;
|
|
54
63
|
left: 0;
|
|
55
64
|
right: 0;
|
|
56
|
-
|
|
65
|
+
width: 100%;
|
|
66
|
+
max-width: 100%;
|
|
67
|
+
max-height: min(80vh, 48rem);
|
|
57
68
|
--sia-drawer-width: 100% !important;
|
|
58
|
-
animation:
|
|
69
|
+
animation: sia-drawer-in-bottom var(--sia-duration-slow) var(--sia-easing-entrance) both;
|
|
59
70
|
}
|
|
60
71
|
|
|
61
72
|
|
|
@@ -68,14 +79,15 @@
|
|
|
68
79
|
.sia-drawer-header,
|
|
69
80
|
.sia-drawer-footer {
|
|
70
81
|
padding: 16px;
|
|
71
|
-
border-bottom: 1px solid var(--sia-
|
|
82
|
+
border-bottom: 1px solid var(--sia-border, #e2e8f0);
|
|
72
83
|
display: flex;
|
|
73
84
|
align-items: center;
|
|
74
85
|
justify-content: space-between;
|
|
75
86
|
}
|
|
76
87
|
|
|
77
88
|
.sia-drawer-footer {
|
|
78
|
-
border-top: 1px solid var(--sia-
|
|
89
|
+
border-top: 1px solid var(--sia-border, #e2e8f0);
|
|
90
|
+
border-bottom: 0;
|
|
79
91
|
margin-top: auto;
|
|
80
92
|
}
|
|
81
93
|
|
|
@@ -85,67 +97,80 @@
|
|
|
85
97
|
}
|
|
86
98
|
|
|
87
99
|
.sia-drawer-title {
|
|
100
|
+
margin: 0;
|
|
88
101
|
font-size: 1.1rem;
|
|
89
102
|
font-weight: 600;
|
|
90
103
|
}
|
|
91
104
|
|
|
92
105
|
.sia-drawer-close {
|
|
106
|
+
display: grid;
|
|
107
|
+
place-items: center;
|
|
108
|
+
flex: none;
|
|
109
|
+
width: 2.25rem;
|
|
110
|
+
height: 2.25rem;
|
|
93
111
|
margin-left: auto;
|
|
94
|
-
|
|
95
|
-
|
|
112
|
+
padding: 0;
|
|
113
|
+
color: var(--sia-muted, #64748b);
|
|
114
|
+
background: transparent;
|
|
115
|
+
border: 0;
|
|
116
|
+
border-radius: var(--sia-radius, .375rem);
|
|
96
117
|
cursor: pointer;
|
|
97
|
-
font-size: 1.2rem;
|
|
98
118
|
}
|
|
119
|
+
.sia-drawer-close:hover { color:var(--sia-foreground,#0f172a); background:var(--sia-surface,#f8fafc); }
|
|
120
|
+
.sia-drawer-close:focus-visible { outline:2px solid var(--sia-primary,#2563eb); outline-offset:2px; }
|
|
121
|
+
.sia-drawer-close svg { width:1.125rem; height:1.125rem; }
|
|
99
122
|
|
|
100
123
|
.sia-drawer-right.is-closing {
|
|
101
|
-
animation:
|
|
124
|
+
animation: sia-drawer-out-right var(--sia-duration-base) var(--sia-easing-exit) both;
|
|
102
125
|
}
|
|
103
126
|
|
|
104
127
|
.sia-drawer-left.is-closing {
|
|
105
|
-
animation:
|
|
128
|
+
animation: sia-drawer-out-left var(--sia-duration-base) var(--sia-easing-exit) both;
|
|
106
129
|
}
|
|
107
130
|
|
|
108
131
|
.sia-drawer-top.is-closing {
|
|
109
|
-
animation:
|
|
132
|
+
animation: sia-drawer-out-top var(--sia-duration-base) var(--sia-easing-exit) both;
|
|
110
133
|
}
|
|
111
134
|
|
|
112
135
|
.sia-drawer-bottom.is-closing {
|
|
113
|
-
animation:
|
|
136
|
+
animation: sia-drawer-out-bottom var(--sia-duration-base) var(--sia-easing-exit) both;
|
|
114
137
|
}
|
|
115
138
|
|
|
116
139
|
/* Animations */
|
|
117
|
-
@keyframes
|
|
140
|
+
@keyframes sia-drawer-fade-in { from { opacity:0; } to { opacity:1; } }
|
|
141
|
+
@keyframes sia-drawer-fade-out { to { opacity:0; } }
|
|
142
|
+
@keyframes sia-drawer-in-right {
|
|
118
143
|
from { transform: translateX(100%); }
|
|
119
144
|
to { transform: translateX(0); }
|
|
120
145
|
}
|
|
121
146
|
|
|
122
|
-
@keyframes
|
|
147
|
+
@keyframes sia-drawer-in-left {
|
|
123
148
|
from { transform: translateX(-100%); }
|
|
124
149
|
to { transform: translateX(0); }
|
|
125
150
|
}
|
|
126
151
|
|
|
127
|
-
@keyframes
|
|
152
|
+
@keyframes sia-drawer-in-top {
|
|
128
153
|
from { transform: translateY(-100%); }
|
|
129
154
|
to { transform: translateY(0); }
|
|
130
155
|
}
|
|
131
156
|
|
|
132
|
-
@keyframes
|
|
157
|
+
@keyframes sia-drawer-in-bottom {
|
|
133
158
|
from { transform: translateY(100%); }
|
|
134
159
|
to { transform: translateY(0); }
|
|
135
160
|
}
|
|
136
161
|
|
|
137
|
-
@keyframes
|
|
162
|
+
@keyframes sia-drawer-out-right {
|
|
138
163
|
to { transform: translateX(100%); }
|
|
139
164
|
}
|
|
140
165
|
|
|
141
|
-
@keyframes
|
|
166
|
+
@keyframes sia-drawer-out-left {
|
|
142
167
|
to { transform: translateX(-100%); }
|
|
143
168
|
}
|
|
144
169
|
|
|
145
|
-
@keyframes
|
|
170
|
+
@keyframes sia-drawer-out-top {
|
|
146
171
|
to { transform: translateY(-100%); }
|
|
147
172
|
}
|
|
148
173
|
|
|
149
|
-
@keyframes
|
|
174
|
+
@keyframes sia-drawer-out-bottom {
|
|
150
175
|
to { transform: translateY(100%); }
|
|
151
176
|
}
|
|
@@ -182,6 +182,15 @@ export function InfoIcon(props: IconProps) {
|
|
|
182
182
|
</IconBase>
|
|
183
183
|
);
|
|
184
184
|
}
|
|
185
|
+
|
|
186
|
+
export function SettingsIcon(props: IconProps) {
|
|
187
|
+
return (
|
|
188
|
+
<IconBase {...props}>
|
|
189
|
+
<circle cx="12" cy="12" r="3" />
|
|
190
|
+
<path d="M19.4 15a1.7 1.7 0 0 0 .3 1.9l.1.1-2.8 2.8-.1-.1a1.7 1.7 0 0 0-1.9-.3 1.7 1.7 0 0 0-1 1.6v.2h-4V21a1.7 1.7 0 0 0-1-1.6 1.7 1.7 0 0 0-1.9.3l-.1.1L4.2 17l.1-.1a1.7 1.7 0 0 0 .3-1.9A1.7 1.7 0 0 0 3 14H2.8v-4H3a1.7 1.7 0 0 0 1.6-1 1.7 1.7 0 0 0-.3-1.9L4.2 7 7 4.2l.1.1A1.7 1.7 0 0 0 9 4.6 1.7 1.7 0 0 0 10 3v-.2h4V3a1.7 1.7 0 0 0 1 1.6 1.7 1.7 0 0 0 1.9-.3l.1-.1L19.8 7l-.1.1a1.7 1.7 0 0 0-.3 1.9 1.7 1.7 0 0 0 1.6 1h.2v4H21a1.7 1.7 0 0 0-1.6 1Z" />
|
|
191
|
+
</IconBase>
|
|
192
|
+
);
|
|
193
|
+
}
|
|
185
194
|
export function EyeIcon(props: IconProps) {
|
|
186
195
|
return (
|
|
187
196
|
<IconBase {...props}>
|
|
@@ -358,7 +358,8 @@ function Ligne({
|
|
|
358
358
|
aDesEnfants: boolean;
|
|
359
359
|
}) {
|
|
360
360
|
const porteUnePastille =
|
|
361
|
-
collapsed &&
|
|
361
|
+
collapsed &&
|
|
362
|
+
navSome(item, (e) => e.badge !== undefined && e.badge !== null);
|
|
362
363
|
|
|
363
364
|
return (
|
|
364
365
|
<>
|
|
@@ -370,7 +371,16 @@ function Ligne({
|
|
|
370
371
|
<span className="sia-sidebar__label">{item.label}</span>
|
|
371
372
|
|
|
372
373
|
{item.badge !== undefined && !collapsed && (
|
|
373
|
-
<span
|
|
374
|
+
<span
|
|
375
|
+
className="sia-sidebar__badge"
|
|
376
|
+
data-sia-badge={
|
|
377
|
+
typeof item.badge === "string" || typeof item.badge === "number"
|
|
378
|
+
? String(item.badge)
|
|
379
|
+
: undefined
|
|
380
|
+
}
|
|
381
|
+
>
|
|
382
|
+
{item.badge}
|
|
383
|
+
</span>
|
|
374
384
|
)}
|
|
375
385
|
|
|
376
386
|
{/* Le compte exact ne tient pas sur un rail : il devient un point, et se
|
|
@@ -571,7 +581,17 @@ function NoeudRail(props: NoeudProps) {
|
|
|
571
581
|
<div className="sia-sidebar-flyout__title">
|
|
572
582
|
{item.label}
|
|
573
583
|
{item.badge !== undefined && (
|
|
574
|
-
<span
|
|
584
|
+
<span
|
|
585
|
+
className="sia-sidebar__badge"
|
|
586
|
+
data-sia-badge={
|
|
587
|
+
typeof item.badge === "string" ||
|
|
588
|
+
typeof item.badge === "number"
|
|
589
|
+
? String(item.badge)
|
|
590
|
+
: undefined
|
|
591
|
+
}
|
|
592
|
+
>
|
|
593
|
+
{item.badge}
|
|
594
|
+
</span>
|
|
575
595
|
)}
|
|
576
596
|
</div>
|
|
577
597
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
font-size: .875rem;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
.sia-sidebar__body { flex:
|
|
11
|
+
.sia-sidebar__body { flex:1; min-height:0; padding-inline-end:.375rem; overflow-y:auto; display:grid; gap:.125rem; align-content:start; scrollbar-gutter:stable; }
|
|
12
12
|
/* Rognés plutôt que débordants : en mode rail, un en-tête ou un pied qui
|
|
13
13
|
n'a pas été adapté déborderait sur le contenu. Le `data-collapsed` posé
|
|
14
14
|
par `AppShell` permet de l'adapter; ceci garantit que ne pas l'adapter
|
|
@@ -130,17 +130,7 @@
|
|
|
130
130
|
padding-block: .375rem;
|
|
131
131
|
font-size: .825rem;
|
|
132
132
|
}
|
|
133
|
-
/* Le filet qui relie les sous-entrées à leur parent. */
|
|
134
133
|
.sia-sidebar__sub { position: relative; }
|
|
135
|
-
.sia-sidebar__sub::before {
|
|
136
|
-
content: "";
|
|
137
|
-
position: absolute;
|
|
138
|
-
top: .375rem;
|
|
139
|
-
bottom: .375rem;
|
|
140
|
-
left: 1.25rem;
|
|
141
|
-
width: 1px;
|
|
142
|
-
background: var(--sia-border);
|
|
143
|
-
}
|
|
144
134
|
|
|
145
135
|
/* ── Mode réduit ───────────────────────────────────────────────────────── */
|
|
146
136
|
|
|
@@ -197,8 +187,6 @@
|
|
|
197
187
|
font-weight: 650;
|
|
198
188
|
}
|
|
199
189
|
.sia-sidebar-flyout__body { display: grid; gap: .125rem; }
|
|
200
|
-
/* Dans le volet, le filet vertical du parent n'a plus de parent à relier. */
|
|
201
|
-
.sia-sidebar-flyout .sia-sidebar__sub::before { display: none; }
|
|
202
190
|
.sia-sidebar-flyout .sia-sidebar__item--child { padding-left: calc(.625rem + var(--sia-sidebar-depth, 1) * .6rem); }
|
|
203
191
|
|
|
204
192
|
/* ── Variantes ─────────────────────────────────────────────────────────── */
|
|
@@ -63,9 +63,10 @@
|
|
|
63
63
|
--sia-toggle-color: var(--sia-primary);
|
|
64
64
|
display: inline-flex;
|
|
65
65
|
padding: .2rem;
|
|
66
|
-
border: 1px solid var(--sia-border);
|
|
66
|
+
border: 1px solid color-mix(in srgb, var(--sia-muted) 28%, var(--sia-border));
|
|
67
67
|
border-radius: calc(var(--sia-radius) + 2px);
|
|
68
|
-
background: var(--sia-
|
|
68
|
+
background: color-mix(in srgb, var(--sia-muted) 12%, var(--sia-background));
|
|
69
|
+
box-shadow: inset 0 1px 2px rgb(15 23 42 / .05);
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
.sia-toggle-group__item {
|
|
@@ -144,6 +144,17 @@
|
|
|
144
144
|
--sia-elevation-modal: 0 24px 60px rgb(15 23 42 / 0.22);
|
|
145
145
|
}
|
|
146
146
|
/* @end:theme */
|
|
147
|
+
/* Scrollbars SIA UI globales : faibles en spécificité, donc surchargeables. */
|
|
148
|
+
:root {
|
|
149
|
+
--sia-scrollbar-size:.625rem;
|
|
150
|
+
--sia-scrollbar-thumb:color-mix(in srgb,var(--sia-muted) 52%,transparent);
|
|
151
|
+
--sia-scrollbar-thumb-hover:color-mix(in srgb,var(--sia-muted) 76%,transparent);
|
|
152
|
+
}
|
|
153
|
+
:where(*) { scrollbar-width:thin; scrollbar-color:var(--sia-scrollbar-thumb) transparent; }
|
|
154
|
+
:where(*)::-webkit-scrollbar { width:var(--sia-scrollbar-size); height:var(--sia-scrollbar-size); }
|
|
155
|
+
:where(*)::-webkit-scrollbar-track,:where(*)::-webkit-scrollbar-corner { background:transparent; }
|
|
156
|
+
:where(*)::-webkit-scrollbar-thumb { min-width:2.5rem; min-height:2.5rem; border:2px solid transparent; border-radius:var(--sia-radius-full,9999px); background:var(--sia-scrollbar-thumb); background-clip:content-box; }
|
|
157
|
+
:where(*)::-webkit-scrollbar-thumb:hover { border:2px solid transparent; background:var(--sia-scrollbar-thumb-hover); background-clip:content-box; }
|
|
147
158
|
.sia-radius--default { border-radius:var(--sia-radius); }
|
|
148
159
|
.sia-radius--none { border-radius:0; }
|
|
149
160
|
.sia-radius--sm { border-radius:.25rem; }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sia-ui/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Install SIA UI components progressively into an application.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sia-ui",
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
"react-dom": "^19.2.3",
|
|
40
40
|
"typescript": "^5.9.3",
|
|
41
41
|
"vitest": "^4.0.16",
|
|
42
|
-
"@sia-ui/headless": "0.
|
|
43
|
-
"@sia-ui/
|
|
44
|
-
"@sia-ui/tokens": "0.
|
|
45
|
-
"@sia-ui/
|
|
42
|
+
"@sia-ui/headless": "0.4.0",
|
|
43
|
+
"@sia-ui/utils": "0.4.0",
|
|
44
|
+
"@sia-ui/tokens": "0.4.0",
|
|
45
|
+
"@sia-ui/react": "0.4.0"
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
48
|
"build": "node scripts/build.mjs",
|