@robosophy/ui-vue 1.1.10 → 1.1.12

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/components.md CHANGED
@@ -1,442 +1,447 @@
1
- # @robosophy/ui-vue Components
2
-
3
- Reference for agents and developers using Robosophy Vue components in consuming projects.
4
-
5
- ## Priority
6
-
7
- When building a module or complex UI, prefer these components before creating local equivalents:
8
-
9
- - `RsSidebar`: module navigation, side menu, mobile sidebar.
10
- - `RsAccountSelector`: user/account selector.
11
- - `RsIcon`: Material Symbols icon component and PrimeVue icon helper.
12
- - `RsAvatar`: user/account image or initials.
13
- - `RsCard`: reusable content container.
14
-
15
- Keep app behavior in the consuming project. Components emit events; the app handles routing, stores, fetches, permissions, logout, and redirects.
16
-
17
- ## Setup
18
-
19
- ```ts
20
- import {
21
- RsAccountSelector,
22
- RsAvatar,
23
- RsCard,
24
- RsIcon,
25
- RsSidebar,
26
- rsPrimeIcon,
27
- } from "@robosophy/ui-vue";
28
- ```
29
-
30
- PrimeVue apps should register the Robosophy preset and import the theme CSS:
31
-
32
- ```ts
33
- import PrimeVue from "primevue/config";
34
- import RobosophyPreset from "@robosophy/prime-theme";
35
- import "@robosophy/prime-theme/prime.css";
36
-
37
- app.use(PrimeVue, {
38
- theme: {
39
- preset: RobosophyPreset,
40
- },
41
- });
42
- ```
43
-
44
- `RsSidebar` and `RsAccountSelector` render their interactive controls with PrimeVue components, so PrimeVue apps should use the setup above to apply PrimeVue defaults plus Robosophy Button/Menu styling.
45
-
46
- Apps without PrimeVue should import:
47
-
48
- ```ts
49
- import "@robosophy/tokens/tokens.css";
50
- ```
51
-
52
- RsIcon uses SVG icons inline. Enable the Vite plugin to auto-detect icons and generate an SVG sprite:
53
-
54
- ```ts
55
- import { robosophyMaterialSymbols } from "@robosophy/ui-vue/vite";
56
-
57
- export default defineConfig({
58
- plugins: [vue(), robosophyMaterialSymbols()],
59
- });
60
- ```
61
-
62
- El plugin escanea automaticamente `<RsIcon name="..." />`, `rsPrimeIcon("...")` y
63
- `icon: "..."` en el codigo fuente. Descarga los SVGs del repositorio oficial de Google
64
- durante el build, los cachea localmente y genera un sprite SVG inline. Sin fuentes
65
- tipograficas.
66
-
67
- ## RsIcon
68
-
69
- Use for Material Symbols. The Vite plugin generates an SVG sprite with only the detected
70
- icons and inlines it in the HTML. No fonts are loaded.
71
-
72
- ```vue
73
- <template>
74
- <RsIcon name="home" />
75
- <RsIcon name="settings" family="rounded" color="primary" />
76
- <Button label="Inicio" :icon="rsPrimeIcon('home')" />
77
- </template>
78
- ```
79
-
80
- For dynamic icon names that the scanner cannot see, add them to
81
- `robosophyMaterialSymbols({ include: [...] })`.
82
-
83
- ### How the scanner works
84
-
85
- The plugin scans source files and detects icons using five patterns:
86
-
87
- | Pattern | Detects | Example |
88
- |---------|---------|---------|
89
- | 1 | `<RsIcon name="..." />` tags | `<RsIcon name="home" />` |
90
- | 2 | `rsPrimeIcon("...")` calls | `rsPrimeIcon('settings', { family: 'rounded' })` |
91
- | 3 | `icon: "..."` in objects | `{ icon: "inbox" }` |
92
- | 4 | Magic comments | `// @robosophy-icon: home` |
93
- | 5 | Arrays of strings (name has "icon") | `const iconNames = ["home", "search"]` |
94
-
95
- **Pattern 3** also extracts `weight` and `family` from the enclosing object:
96
- ```ts
97
- { icon: "home", weight: 200, family: "rounded" }
98
- // → weight 200, family "rounded"
99
- ```
100
-
101
- **Pattern 4** (magic comments) is for cases where the scanner cannot detect an icon
102
- statically — typically when icon names are passed as props, stored in variables, or
103
- returned from functions:
104
-
105
- ```ts
106
- // @robosophy-icon: manage_accounts
107
- // @robosophy-icon: settings family=rounded weight=200
108
- // @robosophy-icon: logout
109
-
110
- const action = { icon: "manage_accounts", label: "Perfil" };
111
- const getIcon = () => "settings";
112
- ```
113
-
114
- **Pattern 5** detects arrays assigned to variables whose name contains "icon":
115
- ```ts
116
- const icons = ["home", "search"]; // detected
117
- const sidebarIconNames = ["warning"]; // detected
118
- const names = ["home", "search"]; // NOT detected (no "icon" in name)
119
- ```
120
-
121
- ### When to use `include`
122
-
123
- Use the `include` option when an icon is used in many places or is controlled by
124
- remote configuration:
125
-
126
- ```ts
127
- robosophyMaterialSymbols({
128
- include: [
129
- "home",
130
- { family: "rounded", name: "settings", weight: 200 },
131
- ],
132
- });
133
- ```
134
-
135
- If `weight` is omitted, all valid weights (100–700) are included.
136
-
137
- ### When to use magic comments
138
-
139
- Use `// @robosophy-icon:` when the icon is used in a single file and the variable
140
- name doesn't contain "icon":
141
-
142
- ```ts
143
- // @robosophy-icon: manage_accounts
144
- // @robosophy-icon: logout
145
- const actions = [
146
- { id: "profile", label: "Perfil", icon: "manage_accounts" },
147
- { id: "logout", label: "Salir", icon: "logout" },
148
- ];
149
- ```
150
-
151
- ### Special cases: props and iteration
152
-
153
- **Props to RsSidebar:** icons defined in the `items` array's `icon` property
154
- are detected by Pattern 3:
155
- ```ts
156
- const items = [
157
- { id: "home", label: "Home", icon: "home" }, // ✅ detected
158
- ];
159
- ```
160
-
161
- **Props to RsAccountSelector:** same — `icon` in action objects is detected.
162
-
163
- **v-for iteration with inline objects:** objects in the iterated array are detected:
164
- ```vue
165
- <RsIcon v-for="item in items" :name="item.icon" />
166
- ```
167
-
168
- **v-for with external variable:** not detectable — use magic comments:
169
- ```vue
170
- <RsIcon v-for="name in iconNames" :name="name" /> <!-- add @robosophy-icon -->
171
- ```
172
-
173
- ### Full documentation
174
-
175
- For the complete technical reference (regex patterns, scanner architecture, plugin
176
- options, and known limitations), read `icon-scanner.md` in this package.
177
-
178
- For full control over icon props (fill, grade, etc.), use the slot approach:
179
-
180
- ```vue
181
- <Button label="Favorito">
182
- <template #icon>
183
- <RsIcon name="favorite" fill color="danger" />
184
- </template>
185
- </Button>
186
- ```
187
-
188
- ## RsSidebar
189
-
190
- Use for module navigation. It is controlled and presentational.
191
-
192
- Main props:
193
-
194
- ```ts
195
- type RsSidebarItem = {
196
- id: string;
197
- label: string;
198
- icon?: string;
199
- active?: boolean;
200
- disabled?: boolean;
201
- visible?: boolean;
202
- children?: RsSidebarItem[];
203
- };
204
-
205
- type RsSidebarProps = {
206
- items: RsSidebarItem[];
207
- footerItems?: RsSidebarItem[];
208
- modules?: Array<{
209
- text: string;
210
- link: string;
211
- active?: boolean;
212
- disabled?: boolean;
213
- }>;
214
- navigateOnModuleSelect?: boolean;
215
- title?: string;
216
- icon?: string;
217
- variant?: "pc" | "alta" | "cc" | "pog" | "cyo";
218
- expanded?: boolean;
219
- expandOnHover?: boolean;
220
- mobileOpen?: boolean;
221
- widthCollapsed?: string;
222
- widthExpanded?: string;
223
- ariaLabel?: string;
224
- };
225
- ```
226
-
227
- Emits: `item-click`, `close-mobile`, `expanded-change`, `module-select`.
228
-
229
- Slots: `header`, `header-action`, `item`, `footer`.
230
-
231
- Example:
232
-
233
- ```vue
234
- <script setup lang="ts">
235
- import { ref } from "vue";
236
- import { RsSidebar, type RsSidebarItem } from "@robosophy/ui-vue";
237
-
238
- const items: RsSidebarItem[] = [
239
- { id: "liquidaciones", label: "Liquidacion", icon: "contract", active: true },
240
- { id: "adquisiciones", label: "Adquisiciones", icon: "sell" },
241
- {
242
- id: "config",
243
- label: "Config",
244
- icon: "subtitles_gear",
245
- children: [
246
- { id: "excel", label: "Cargas Excel", icon: "upload" },
247
- { id: "ayuda", label: "Ayuda", icon: "info" },
248
- ],
249
- },
250
- ];
251
-
252
- const footerItems: RsSidebarItem[] = [{ id: "home", label: "Volver al home", icon: "home" }];
253
- const modules = [
254
- { text: "Mi Alta", link: "/alta" },
255
- { text: "Mi Cuenta y Orden", link: "/cyo", active: true },
256
- { text: "Mi Cuenta Corriente", link: "/cc" },
257
- ];
258
- const isMenuOpen = ref(false);
259
-
260
- function handleSidebarItem(item: RsSidebarItem) {
261
- // Route, redirect, or store updates belong in the consuming app.
262
- }
263
- </script>
264
-
265
- <template>
266
- <RsSidebar
267
- title="CYO"
268
- variant="cyo"
269
- :items="items"
270
- :modules="modules"
271
- :footer-items="footerItems"
272
- :mobile-open="isMenuOpen"
273
- @item-click="handleSidebarItem"
274
- @close-mobile="isMenuOpen = false"
275
- />
276
- </template>
277
- ```
278
-
279
- `modules` renders the default header dropdown. Each option has `text` and `link`. Selecting one emits `module-select`.
280
-
281
- If `navigateOnModuleSelect` is `true` the component also redirects with `window.location.href = module.link`. Set it to `false` in Storybook, tests, or apps that want to intercept navigation and route manually.
282
-
283
- Use the `header` slot only when the app needs to replace that default dropdown entirely.
284
-
285
- Project variants set sidebar icon and active colors:
286
-
287
- - `pc`: Plan Comercial, `#014A9F`.
288
- - `alta`: Alta, `#65AC1E`.
289
- - `cc`: Cuenta Corriente, `#49A0D4`.
290
- - `pog`: POG, `#007C2F`.
291
- - `cyo`: Cuenta y Orden, `#49A0D4`.
292
-
293
- ## RsAccountSelector
294
-
295
- Use for user/account switching. It renders the clickable profile image trigger,
296
- opens the account panel, and closes it on outside click. It does not fetch,
297
- redirect, log out, or mutate stores.
298
-
299
- Main props:
300
-
301
- ```ts
302
- type RsAccountSelectorUser = {
303
- email: string;
304
- name?: string;
305
- avatarSrc?: string;
306
- secondaryAvatarSrc?: string;
307
- initials?: string;
308
- };
309
-
310
- type RsAccountSelectorAccount = {
311
- id: string | number;
312
- label: string;
313
- avatarSrc?: string;
314
- initials?: string;
315
- active?: boolean;
316
- disabled?: boolean;
317
- };
318
-
319
- type RsAccountSelectorAction = {
320
- id: string;
321
- label: string;
322
- icon?: string;
323
- visible?: boolean;
324
- disabled?: boolean;
325
- variant?: "ghost" | "danger";
326
- };
327
- ```
328
-
329
- Use `v-model` when the open state needs to be controlled from the parent.
330
-
331
- Emits: `select-account`, `action`, `footer-action`, `update:modelValue`, `open`, `close`.
332
-
333
- Slots: `trigger-avatar`, `user-avatar`, `account-avatar`, `account-trailing`, `actions`, `footer`, `empty`.
334
-
335
- Example:
336
-
337
- ```vue
338
- <script setup lang="ts">
339
- import { RsAccountSelector } from "@robosophy/ui-vue";
340
-
341
- const user = {
342
- email: "usuario@robosophy.com",
343
- initials: "UR",
344
- name: "Usuario Robosophy",
345
- };
346
-
347
- const accounts = [
348
- { id: "1", label: "Cuenta Activa SA", initials: "CA", active: true },
349
- { id: "2", label: "Cuenta Inactiva SRL", initials: "CI" },
350
- ];
351
-
352
- const actions = [{ id: "profile", label: "Ver mi perfil", icon: "manage_accounts" }];
353
- const footerActions = [{ id: "logout", label: "Cerrar sesion", icon: "logout", variant: "danger" }];
354
- </script>
355
-
356
- <template>
357
- <RsAccountSelector
358
- :user="user"
359
- :accounts="accounts"
360
- :actions="actions"
361
- :footer-actions="footerActions"
362
- @select-account="selectAccount"
363
- @action="handleAccountAction"
364
- @footer-action="handleFooterAction"
365
- />
366
- </template>
367
- ```
368
-
369
- ## RsAvatar
370
-
371
- Use for user or account identity.
372
-
373
- Useful props: `src`, `alt`, `initials`, `size`, `interactive`.
374
-
375
- Example:
376
-
377
- ```vue
378
- <template>
379
- <RsAvatar src="/avatar.png" alt="Usuario Robosophy" size="lg" />
380
- <RsAvatar initials="CA" size="sm" interactive />
381
- </template>
382
- ```
383
-
384
- ## RsCard
385
-
386
- Use as a reusable content container.
387
-
388
- Variants: `default`, `brand`, `success`, `warning`, `danger`.
389
-
390
- Padding: `none`, `sm`, `md`, `lg`.
391
-
392
- Useful props: `title`, `subtitle`, `variant`, `padding`, `interactive`, `as`, `ariaLabel`.
393
-
394
- Example:
395
-
396
- ```vue
397
- <template>
398
- <RsCard title="Resumen" subtitle="Estado del modulo">
399
- Contenido del proyecto consumidor.
400
- </RsCard>
401
-
402
- <RsCard variant="success" title="Operacion completada">
403
- Mensaje de estado.
404
- </RsCard>
405
- </template>
406
- ```
407
-
408
- ## Module Composition Pattern
409
-
410
- For a new module, start with `RsSidebar` for navigation, `RsCard` for sections, PrimeVue `Button` for actions, and `RsAccountSelector` only when user/account switching is needed.
411
-
412
- ```vue
413
- <script setup lang="ts">
414
- import Button from "primevue/button";
415
- import { RsCard, RsSidebar, type RsSidebarItem } from "@robosophy/ui-vue";
416
-
417
- const sidebarItems: RsSidebarItem[] = [
418
- { id: "dashboard", label: "Dashboard", icon: "dashboard", active: true },
419
- { id: "settings", label: "Configuracion", icon: "settings" },
420
- ];
421
-
422
- function navigateToSection(item: RsSidebarItem) {
423
- // Push a route or update local module state in the consuming app.
424
- }
425
- </script>
426
-
427
- <template>
428
- <div class="module-layout">
429
- <RsSidebar title="Modulo" :items="sidebarItems" @item-click="navigateToSection" />
430
-
431
- <main>
432
- <RsCard title="Dashboard" subtitle="Indicadores principales">
433
- <Button>
434
- <span class="action-content">
435
- <span>Crear</span>
436
- </span>
437
- </Button>
438
- </RsCard>
439
- </main>
440
- </div>
441
- </template>
442
- ```
1
+ # @robosophy/ui-vue Components
2
+
3
+ Reference for agents and developers using Robosophy Vue components in consuming projects.
4
+
5
+ ## Priority
6
+
7
+ When building a module or complex UI, prefer these components before creating local equivalents:
8
+
9
+ - `RsSidebar`: module navigation, side menu, mobile sidebar.
10
+ - `RsAccountSelector`: user/account selector.
11
+ - `RsIcon`: Material Symbols icon component and PrimeVue icon helper.
12
+ - `RsAvatar`: user/account image or initials.
13
+ - `RsCard`: reusable content container.
14
+
15
+ Keep app behavior in the consuming project. Components emit events; the app handles routing, stores, fetches, permissions, logout, and redirects.
16
+
17
+ ## Setup
18
+
19
+ ```ts
20
+ import {
21
+ RsAccountSelector,
22
+ RsAvatar,
23
+ RsCard,
24
+ RsIcon,
25
+ RsSidebar,
26
+ rsPrimeIcon,
27
+ } from "@robosophy/ui-vue";
28
+ ```
29
+
30
+ PrimeVue apps should register the Robosophy preset and import the theme CSS:
31
+
32
+ ```ts
33
+ import PrimeVue from "primevue/config";
34
+ import RobosophyPreset from "@robosophy/prime-theme";
35
+ import "@robosophy/prime-theme/prime.css";
36
+
37
+ app.use(PrimeVue, {
38
+ theme: {
39
+ preset: RobosophyPreset,
40
+ },
41
+ });
42
+ ```
43
+
44
+ `RsSidebar` and `RsAccountSelector` render their interactive controls with PrimeVue components, so PrimeVue apps should use the setup above to apply PrimeVue defaults plus Robosophy Button/Menu styling.
45
+
46
+ Apps without PrimeVue should import:
47
+
48
+ ```ts
49
+ import "@robosophy/tokens/tokens.css";
50
+ ```
51
+
52
+ RsIcon uses SVG icons inline. Enable the Vite plugin to auto-detect icons and generate an SVG sprite:
53
+
54
+ ```ts
55
+ import { robosophyMaterialSymbols } from "@robosophy/ui-vue/vite";
56
+
57
+ export default defineConfig({
58
+ plugins: [vue(), robosophyMaterialSymbols()],
59
+ });
60
+ ```
61
+
62
+ El plugin escanea automaticamente `<RsIcon name="..." />`, `rsPrimeIcon("...")` y
63
+ `icon: "..."` en el codigo fuente. Descarga los SVGs del repositorio oficial de Google
64
+ durante el build, los cachea localmente y genera un sprite SVG inline. Sin fuentes
65
+ tipograficas.
66
+
67
+ ## RsIcon
68
+
69
+ Use for Material Symbols. The Vite plugin generates an SVG sprite with only the detected
70
+ icons and inlines it in the HTML. No fonts are loaded.
71
+
72
+ ```vue
73
+ <template>
74
+ <RsIcon name="home" />
75
+ <RsIcon name="settings" family="rounded" color="primary" />
76
+ <RsIcon name="manage_accounts" notification />
77
+ <RsIcon name="manage_accounts" notification notification-color="#d80115" />
78
+ <Button label="Inicio" :icon="rsPrimeIcon('home')" />
79
+ </template>
80
+ ```
81
+
82
+ `notification` muestra un punto de aviso sobre el ícono (por defecto amarillo del design system,
83
+ `--rs-color-yellow-500`). `notificationColor` permite sobreescribir el color del punto.
84
+
85
+ For dynamic icon names that the scanner cannot see, add them to
86
+ `robosophyMaterialSymbols({ include: [...] })`.
87
+
88
+ ### How the scanner works
89
+
90
+ The plugin scans source files and detects icons using five patterns:
91
+
92
+ | Pattern | Detects | Example |
93
+ |---------|---------|---------|
94
+ | 1 | `<RsIcon name="..." />` tags | `<RsIcon name="home" />` |
95
+ | 2 | `rsPrimeIcon("...")` calls | `rsPrimeIcon('settings', { family: 'rounded' })` |
96
+ | 3 | `icon: "..."` in objects | `{ icon: "inbox" }` |
97
+ | 4 | Magic comments | `// @robosophy-icon: home` |
98
+ | 5 | Arrays of strings (name has "icon") | `const iconNames = ["home", "search"]` |
99
+
100
+ **Pattern 3** also extracts `weight` and `family` from the enclosing object:
101
+ ```ts
102
+ { icon: "home", weight: 200, family: "rounded" }
103
+ // → weight 200, family "rounded"
104
+ ```
105
+
106
+ **Pattern 4** (magic comments) is for cases where the scanner cannot detect an icon
107
+ statically — typically when icon names are passed as props, stored in variables, or
108
+ returned from functions:
109
+
110
+ ```ts
111
+ // @robosophy-icon: manage_accounts
112
+ // @robosophy-icon: settings family=rounded weight=200
113
+ // @robosophy-icon: logout
114
+
115
+ const action = { icon: "manage_accounts", label: "Perfil" };
116
+ const getIcon = () => "settings";
117
+ ```
118
+
119
+ **Pattern 5** detects arrays assigned to variables whose name contains "icon":
120
+ ```ts
121
+ const icons = ["home", "search"]; // detected
122
+ const sidebarIconNames = ["warning"]; // detected
123
+ const names = ["home", "search"]; // NOT detected (no "icon" in name)
124
+ ```
125
+
126
+ ### When to use `include`
127
+
128
+ Use the `include` option when an icon is used in many places or is controlled by
129
+ remote configuration:
130
+
131
+ ```ts
132
+ robosophyMaterialSymbols({
133
+ include: [
134
+ "home",
135
+ { family: "rounded", name: "settings", weight: 200 },
136
+ ],
137
+ });
138
+ ```
139
+
140
+ If `weight` is omitted, all valid weights (100–700) are included.
141
+
142
+ ### When to use magic comments
143
+
144
+ Use `// @robosophy-icon:` when the icon is used in a single file and the variable
145
+ name doesn't contain "icon":
146
+
147
+ ```ts
148
+ // @robosophy-icon: manage_accounts
149
+ // @robosophy-icon: logout
150
+ const actions = [
151
+ { id: "profile", label: "Perfil", icon: "manage_accounts" },
152
+ { id: "logout", label: "Salir", icon: "logout" },
153
+ ];
154
+ ```
155
+
156
+ ### Special cases: props and iteration
157
+
158
+ **Props to RsSidebar:** icons defined in the `items` array's `icon` property
159
+ are detected by Pattern 3:
160
+ ```ts
161
+ const items = [
162
+ { id: "home", label: "Home", icon: "home" }, // ✅ detected
163
+ ];
164
+ ```
165
+
166
+ **Props to RsAccountSelector:** same — `icon` in action objects is detected.
167
+
168
+ **v-for iteration with inline objects:** objects in the iterated array are detected:
169
+ ```vue
170
+ <RsIcon v-for="item in items" :name="item.icon" />
171
+ ```
172
+
173
+ **v-for with external variable:** not detectable — use magic comments:
174
+ ```vue
175
+ <RsIcon v-for="name in iconNames" :name="name" /> <!-- add @robosophy-icon -->
176
+ ```
177
+
178
+ ### Full documentation
179
+
180
+ For the complete technical reference (regex patterns, scanner architecture, plugin
181
+ options, and known limitations), read `icon-scanner.md` in this package.
182
+
183
+ For full control over icon props (fill, grade, etc.), use the slot approach:
184
+
185
+ ```vue
186
+ <Button label="Favorito">
187
+ <template #icon>
188
+ <RsIcon name="favorite" fill color="danger" />
189
+ </template>
190
+ </Button>
191
+ ```
192
+
193
+ ## RsSidebar
194
+
195
+ Use for module navigation. It is controlled and presentational.
196
+
197
+ Main props:
198
+
199
+ ```ts
200
+ type RsSidebarItem = {
201
+ id: string;
202
+ label: string;
203
+ icon?: string;
204
+ active?: boolean;
205
+ disabled?: boolean;
206
+ visible?: boolean;
207
+ children?: RsSidebarItem[];
208
+ };
209
+
210
+ type RsSidebarProps = {
211
+ items: RsSidebarItem[];
212
+ footerItems?: RsSidebarItem[];
213
+ modules?: Array<{
214
+ text: string;
215
+ link: string;
216
+ active?: boolean;
217
+ disabled?: boolean;
218
+ }>;
219
+ navigateOnModuleSelect?: boolean;
220
+ title?: string;
221
+ icon?: string;
222
+ variant?: "pc" | "alta" | "cc" | "pog" | "cyo";
223
+ expanded?: boolean;
224
+ expandOnHover?: boolean;
225
+ mobileOpen?: boolean;
226
+ widthCollapsed?: string;
227
+ widthExpanded?: string;
228
+ ariaLabel?: string;
229
+ };
230
+ ```
231
+
232
+ Emits: `item-click`, `close-mobile`, `expanded-change`, `module-select`.
233
+
234
+ Slots: `header`, `header-action`, `item`, `footer`.
235
+
236
+ Example:
237
+
238
+ ```vue
239
+ <script setup lang="ts">
240
+ import { ref } from "vue";
241
+ import { RsSidebar, type RsSidebarItem } from "@robosophy/ui-vue";
242
+
243
+ const items: RsSidebarItem[] = [
244
+ { id: "liquidaciones", label: "Liquidacion", icon: "contract", active: true },
245
+ { id: "adquisiciones", label: "Adquisiciones", icon: "sell" },
246
+ {
247
+ id: "config",
248
+ label: "Config",
249
+ icon: "subtitles_gear",
250
+ children: [
251
+ { id: "excel", label: "Cargas Excel", icon: "upload" },
252
+ { id: "ayuda", label: "Ayuda", icon: "info" },
253
+ ],
254
+ },
255
+ ];
256
+
257
+ const footerItems: RsSidebarItem[] = [{ id: "home", label: "Volver al home", icon: "home" }];
258
+ const modules = [
259
+ { text: "Mi Alta", link: "/alta" },
260
+ { text: "Mi Cuenta y Orden", link: "/cyo", active: true },
261
+ { text: "Mi Cuenta Corriente", link: "/cc" },
262
+ ];
263
+ const isMenuOpen = ref(false);
264
+
265
+ function handleSidebarItem(item: RsSidebarItem) {
266
+ // Route, redirect, or store updates belong in the consuming app.
267
+ }
268
+ </script>
269
+
270
+ <template>
271
+ <RsSidebar
272
+ title="CYO"
273
+ variant="cyo"
274
+ :items="items"
275
+ :modules="modules"
276
+ :footer-items="footerItems"
277
+ :mobile-open="isMenuOpen"
278
+ @item-click="handleSidebarItem"
279
+ @close-mobile="isMenuOpen = false"
280
+ />
281
+ </template>
282
+ ```
283
+
284
+ `modules` renders the default header dropdown. Each option has `text` and `link`. Selecting one emits `module-select`.
285
+
286
+ If `navigateOnModuleSelect` is `true` the component also redirects with `window.location.href = module.link`. Set it to `false` in Storybook, tests, or apps that want to intercept navigation and route manually.
287
+
288
+ Use the `header` slot only when the app needs to replace that default dropdown entirely.
289
+
290
+ Project variants set sidebar icon and active colors:
291
+
292
+ - `pc`: Plan Comercial, `#014A9F`.
293
+ - `alta`: Alta, `#65AC1E`.
294
+ - `cc`: Cuenta Corriente, `#49A0D4`.
295
+ - `pog`: POG, `#007C2F`.
296
+ - `cyo`: Cuenta y Orden, `#49A0D4`.
297
+
298
+ ## RsAccountSelector
299
+
300
+ Use for user/account switching. It renders the clickable profile image trigger,
301
+ opens the account panel, and closes it on outside click. It does not fetch,
302
+ redirect, log out, or mutate stores.
303
+
304
+ Main props:
305
+
306
+ ```ts
307
+ type RsAccountSelectorUser = {
308
+ email: string;
309
+ name?: string;
310
+ avatarSrc?: string;
311
+ secondaryAvatarSrc?: string;
312
+ initials?: string;
313
+ };
314
+
315
+ type RsAccountSelectorAccount = {
316
+ id: string | number;
317
+ label: string;
318
+ avatarSrc?: string;
319
+ initials?: string;
320
+ active?: boolean;
321
+ disabled?: boolean;
322
+ };
323
+
324
+ type RsAccountSelectorAction = {
325
+ id: string;
326
+ label: string;
327
+ icon?: string;
328
+ visible?: boolean;
329
+ disabled?: boolean;
330
+ variant?: "ghost" | "danger";
331
+ };
332
+ ```
333
+
334
+ Use `v-model` when the open state needs to be controlled from the parent.
335
+
336
+ Emits: `select-account`, `action`, `footer-action`, `update:modelValue`, `open`, `close`.
337
+
338
+ Slots: `trigger-avatar`, `user-avatar`, `account-avatar`, `account-trailing`, `actions`, `footer`, `empty`.
339
+
340
+ Example:
341
+
342
+ ```vue
343
+ <script setup lang="ts">
344
+ import { RsAccountSelector } from "@robosophy/ui-vue";
345
+
346
+ const user = {
347
+ email: "usuario@robosophy.com",
348
+ initials: "UR",
349
+ name: "Usuario Robosophy",
350
+ };
351
+
352
+ const accounts = [
353
+ { id: "1", label: "Cuenta Activa SA", initials: "CA", active: true },
354
+ { id: "2", label: "Cuenta Inactiva SRL", initials: "CI" },
355
+ ];
356
+
357
+ const actions = [{ id: "profile", label: "Ver mi perfil", icon: "manage_accounts" }];
358
+ const footerActions = [{ id: "logout", label: "Cerrar sesion", icon: "logout", variant: "danger" }];
359
+ </script>
360
+
361
+ <template>
362
+ <RsAccountSelector
363
+ :user="user"
364
+ :accounts="accounts"
365
+ :actions="actions"
366
+ :footer-actions="footerActions"
367
+ @select-account="selectAccount"
368
+ @action="handleAccountAction"
369
+ @footer-action="handleFooterAction"
370
+ />
371
+ </template>
372
+ ```
373
+
374
+ ## RsAvatar
375
+
376
+ Use for user or account identity.
377
+
378
+ Useful props: `src`, `alt`, `initials`, `size`, `interactive`.
379
+
380
+ Example:
381
+
382
+ ```vue
383
+ <template>
384
+ <RsAvatar src="/avatar.png" alt="Usuario Robosophy" size="lg" />
385
+ <RsAvatar initials="CA" size="sm" interactive />
386
+ </template>
387
+ ```
388
+
389
+ ## RsCard
390
+
391
+ Use as a reusable content container.
392
+
393
+ Variants: `default`, `brand`, `success`, `warning`, `danger`.
394
+
395
+ Padding: `none`, `sm`, `md`, `lg`.
396
+
397
+ Useful props: `title`, `subtitle`, `variant`, `padding`, `interactive`, `as`, `ariaLabel`.
398
+
399
+ Example:
400
+
401
+ ```vue
402
+ <template>
403
+ <RsCard title="Resumen" subtitle="Estado del modulo">
404
+ Contenido del proyecto consumidor.
405
+ </RsCard>
406
+
407
+ <RsCard variant="success" title="Operacion completada">
408
+ Mensaje de estado.
409
+ </RsCard>
410
+ </template>
411
+ ```
412
+
413
+ ## Module Composition Pattern
414
+
415
+ For a new module, start with `RsSidebar` for navigation, `RsCard` for sections, PrimeVue `Button` for actions, and `RsAccountSelector` only when user/account switching is needed.
416
+
417
+ ```vue
418
+ <script setup lang="ts">
419
+ import Button from "primevue/button";
420
+ import { RsCard, RsSidebar, type RsSidebarItem } from "@robosophy/ui-vue";
421
+
422
+ const sidebarItems: RsSidebarItem[] = [
423
+ { id: "dashboard", label: "Dashboard", icon: "dashboard", active: true },
424
+ { id: "settings", label: "Configuracion", icon: "settings" },
425
+ ];
426
+
427
+ function navigateToSection(item: RsSidebarItem) {
428
+ // Push a route or update local module state in the consuming app.
429
+ }
430
+ </script>
431
+
432
+ <template>
433
+ <div class="module-layout">
434
+ <RsSidebar title="Modulo" :items="sidebarItems" @item-click="navigateToSection" />
435
+
436
+ <main>
437
+ <RsCard title="Dashboard" subtitle="Indicadores principales">
438
+ <Button>
439
+ <span class="action-content">
440
+ <span>Crear</span>
441
+ </span>
442
+ </Button>
443
+ </RsCard>
444
+ </main>
445
+ </div>
446
+ </template>
447
+ ```