design-system-dashboard-devmunity 0.3.0 → 1.0.1
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 +33 -31
- package/app/app.config.ts +2 -1
- package/app/app.vue +21 -3
- package/app/assets/css/settings/base.css +33 -33
- package/app/assets/css/themes/components/badge.js +7 -0
- package/app/assets/css/themes/components/input.js +5 -0
- package/app/assets/css/themes/index.js +2 -1
- package/app/components/BaseButton.vue +3 -0
- package/app/components/Colors.mdx +42 -0
- package/app/components/Indroduction.mdx +100 -0
- package/app/components/a/button/a-button-avatar-dropdown.stories.ts +83 -0
- package/app/components/a/button/a-button-avatar-dropdown.vue +41 -17
- package/app/components/a/button/a-button-navigation.stories.ts +66 -0
- package/app/components/a/button/a-button-navigation.vue +57 -0
- package/app/components/a/card/a-card-inner.stories.ts +89 -0
- package/app/components/a/card/a-card-inner.vue +38 -0
- package/app/components/a/dropdown/a-dropdown-avatar.stories.ts +160 -0
- package/app/components/a/dropdown/a-dropdown-avatar.vue +75 -33
- package/app/components/a/pill/a-pill.stories.ts +91 -0
- package/app/components/a/pill/a-pill.vue +63 -42
- package/app/components/b/badge/b-badge.stories.ts +77 -0
- package/app/components/b/badge/b-badge.vue +55 -0
- package/app/components/b/card/b-card.stories.ts +120 -0
- package/app/components/b/card/b-card.vue +49 -32
- package/app/components/b/modal/b-modal.stories.ts +210 -0
- package/app/components/b/modal/b-modal.vue +125 -81
- package/app/components/c/badge/c-badge-status.stories.ts +72 -0
- package/app/components/c/badge/c-badge-status.vue +60 -0
- package/app/components/c/modal/c-modal-danger.stories.ts +112 -0
- package/app/components/c/modal/c-modal-danger.vue +60 -41
- package/app/components/d/action-buttons/d-action-buttons.stories.ts +90 -0
- package/app/components/d/action-buttons/d-action-buttons.vue +121 -0
- package/app/components/d/card/d-card-header.stories.ts +123 -0
- package/app/components/{b/card/b-card-header.vue → d/card/d-card-header.vue} +62 -44
- package/app/components/d/upload/d-upload-avatar.stories.ts +66 -0
- package/app/components/d/upload/d-upload-avatar.vue +95 -0
- package/app/pages/test.vue +27 -16
- package/app/types/index.ts +1 -0
- package/app/types/semantic-colors.type.ts +3 -0
- package/app/utils/util-get-colors-from-css.ts +53 -0
- package/nuxt.config.ts +11 -16
- package/package.json +84 -68
- package/.editorconfig +0 -13
- package/.github/workflows/release.yml +0 -36
- package/.husky/commit-msg +0 -1
- package/.husky/pre-commit +0 -0
- package/.prettierrc +0 -24
- package/.storybook/main.js +0 -25
- package/.storybook/preview.js +0 -13
- package/.vscode/settings.json +0 -28
- package/CHANGELOG.md +0 -46
- package/app/Introduction.mdx +0 -44
- package/app/components/a/button/a-button-back.vue +0 -33
- package/app/components/b/card/b-card-inner.vue +0 -25
- package/app/components/d/d-action-buttons.vue +0 -99
- package/commitlint.config.js +0 -8
- package/tsconfig.json +0 -8
package/README.md
CHANGED
|
@@ -1,60 +1,62 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Design System Dashboard Devmunity
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Este proyecto es un **Nuxt Layer** que funciona como un sistema de diseño para aplicaciones Nuxt. Contiene componentes, estilos y configuraciones compartidas.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Uso como Nuxt Layer
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- [Documentation](https://ui.nuxt.com/docs/getting-started/installation/nuxt)
|
|
7
|
+
Para usar este proyecto como una librería en otro proyecto de Nuxt, sigue estos pasos:
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
<picture>
|
|
12
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://ui.nuxt.com/assets/templates/nuxt/starter-dark.png">
|
|
13
|
-
<source media="(prefers-color-scheme: light)" srcset="https://ui.nuxt.com/assets/templates/nuxt/starter-light.png">
|
|
14
|
-
<img alt="Nuxt Starter Template" src="https://ui.nuxt.com/assets/templates/nuxt/starter-light.png">
|
|
15
|
-
</picture>
|
|
16
|
-
</a>
|
|
9
|
+
### 1. Instalación
|
|
17
10
|
|
|
18
|
-
|
|
11
|
+
Instala el paquete por medio de NPM (o tu gestor de paquetes preferido):
|
|
19
12
|
|
|
20
|
-
|
|
13
|
+
```bash
|
|
14
|
+
npm install design-system-dashboard-devmunity
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### 2. Configuración en Nuxt
|
|
21
18
|
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
En el proyecto donde desees usar el sistema de diseño, añade el paquete a la propiedad `extends` en tu archivo `nuxt.config.ts`:
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
// nuxt.config.ts
|
|
23
|
+
export default defineNuxtConfig({
|
|
24
|
+
extends: ['design-system-dashboard-devmunity'],
|
|
25
|
+
})
|
|
24
26
|
```
|
|
25
27
|
|
|
26
|
-
|
|
28
|
+
¡Y listo! Nuxt automáticamente cargará los componentes, composables, assets y la configuración de este layer en tu proyecto.
|
|
27
29
|
|
|
28
|
-
|
|
30
|
+
## Desarrollo Local
|
|
29
31
|
|
|
30
|
-
|
|
32
|
+
Si deseas contribuir o probar este proyecto localmente:
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
### Instalación de dependencias
|
|
33
35
|
|
|
34
36
|
```bash
|
|
35
|
-
|
|
37
|
+
npm install
|
|
36
38
|
```
|
|
37
39
|
|
|
38
|
-
|
|
40
|
+
### Servidor de Desarrollo
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
Inicia el servidor de desarrollo:
|
|
41
43
|
|
|
42
44
|
```bash
|
|
43
|
-
|
|
45
|
+
npm run dev
|
|
44
46
|
```
|
|
45
47
|
|
|
46
|
-
|
|
48
|
+
### Storybook
|
|
47
49
|
|
|
48
|
-
|
|
50
|
+
Para ver y probar los componentes de forma aislada:
|
|
49
51
|
|
|
50
52
|
```bash
|
|
51
|
-
|
|
53
|
+
npm run storybook
|
|
52
54
|
```
|
|
53
55
|
|
|
54
|
-
|
|
56
|
+
## Producción
|
|
57
|
+
|
|
58
|
+
Para construir el proyecto para producción (como aplicación independiente):
|
|
55
59
|
|
|
56
60
|
```bash
|
|
57
|
-
|
|
61
|
+
npm run build
|
|
58
62
|
```
|
|
59
|
-
|
|
60
|
-
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
|
package/app/app.config.ts
CHANGED
|
@@ -6,12 +6,13 @@ export default defineAppConfig({
|
|
|
6
6
|
colors: {
|
|
7
7
|
primary: 'brand-blue',
|
|
8
8
|
secondary: 'brand-purple',
|
|
9
|
+
accent: 'brand-yellow',
|
|
9
10
|
success: 'brand-green',
|
|
10
11
|
warning: 'brand-orange',
|
|
11
12
|
error: 'brand-red',
|
|
12
13
|
info: 'brand-blue-sky',
|
|
13
14
|
neutral: 'brand-grey',
|
|
14
|
-
test: 'purple',
|
|
15
|
+
// test: 'purple',
|
|
15
16
|
},
|
|
16
17
|
},
|
|
17
18
|
})
|
package/app/app.vue
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
<script setup>
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import AButtonAvatarDropdown from './components/a/button/a-button-avatar-dropdown.vue'
|
|
3
|
+
import ADropdownAvatar from './components/a/dropdown/a-dropdown-avatar.vue'
|
|
4
|
+
|
|
2
5
|
useHead({
|
|
3
6
|
meta: [{ name: 'viewport', content: 'width=device-width, initial-scale=1' }],
|
|
4
7
|
link: [{ rel: 'icon', href: '/favicon.ico' }],
|
|
@@ -20,6 +23,8 @@ useSeoMeta({
|
|
|
20
23
|
twitterImage: 'https://ui.nuxt.com/assets/templates/nuxt/starter-light.png',
|
|
21
24
|
twitterCard: 'summary_large_image',
|
|
22
25
|
})
|
|
26
|
+
|
|
27
|
+
const isOpen = ref(false)
|
|
23
28
|
</script>
|
|
24
29
|
|
|
25
30
|
<template>
|
|
@@ -35,7 +40,6 @@ useSeoMeta({
|
|
|
35
40
|
|
|
36
41
|
<template #right>
|
|
37
42
|
<UColorModeButton />
|
|
38
|
-
|
|
39
43
|
<UButton
|
|
40
44
|
to="https://github.com/nuxt-ui-templates/starter"
|
|
41
45
|
target="_blank"
|
|
@@ -57,7 +61,21 @@ useSeoMeta({
|
|
|
57
61
|
<template #left>
|
|
58
62
|
<p class="text-muted text-sm">Built with Nuxt UI • © {{ new Date().getFullYear() }}</p>
|
|
59
63
|
</template>
|
|
60
|
-
|
|
64
|
+
<CModalDanger v-model="isOpen" title="Modal" description="Modal description" />
|
|
65
|
+
<UButton @click="isOpen = true">Open Modal</UButton>
|
|
66
|
+
<UBadge color="accent" />
|
|
67
|
+
<DCardHeader title="Card Header" subtitle="Card Subtitle" />
|
|
68
|
+
<DActionButtons
|
|
69
|
+
primary-button-text="Primary"
|
|
70
|
+
secondary-button-text="Secondary"
|
|
71
|
+
primary-button-icon="i-heroicons-solid-arrow-right"
|
|
72
|
+
primary-button-trailing-icon="i-heroicons-solid-arrow-right"
|
|
73
|
+
/>
|
|
74
|
+
<UButton
|
|
75
|
+
icon="i-heroicons-solid-arrow-right"
|
|
76
|
+
trailing-icon="i-heroicons-solid-arrow-right"
|
|
77
|
+
label="Button"
|
|
78
|
+
/>
|
|
61
79
|
<template #right>
|
|
62
80
|
<UButton
|
|
63
81
|
to="https://github.com/nuxt-ui-templates/starter"
|
|
@@ -1,38 +1,38 @@
|
|
|
1
1
|
@layer base {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
2
|
+
* {
|
|
3
|
+
/* @apply border-neutral-300; */
|
|
4
|
+
}
|
|
5
|
+
body {
|
|
6
|
+
@apply text-default overflow-x-hidden scroll-smooth text-pretty;
|
|
7
|
+
scrollbar-gutter: stable;
|
|
8
|
+
}
|
|
9
|
+
h1,
|
|
10
|
+
h2,
|
|
11
|
+
h3,
|
|
12
|
+
h4,
|
|
13
|
+
h5,
|
|
14
|
+
h6 {
|
|
15
|
+
@apply text-balance;
|
|
16
|
+
}
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
label {
|
|
19
|
+
@apply block cursor-pointer text-sm font-medium text-neutral-800;
|
|
20
|
+
}
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
22
|
+
::-webkit-scrollbar {
|
|
23
|
+
@apply size-1;
|
|
24
|
+
}
|
|
25
|
+
::-webkit-scrollbar-thumb {
|
|
26
|
+
@apply bg-primary-400 rounded-sm transition-colors;
|
|
27
|
+
}
|
|
28
|
+
::-webkit-scrollbar-track {
|
|
29
|
+
@apply bg-transparent;
|
|
30
|
+
}
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
::selection {
|
|
33
|
+
@apply !bg-primary-500 text-neutral-50;
|
|
34
|
+
}
|
|
35
|
+
::-moz-selection {
|
|
36
|
+
@apply !bg-primary-500 text-neutral-50;
|
|
37
|
+
}
|
|
38
38
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { default as card } from './components/card.js'
|
|
2
2
|
export { default as button } from './components/button.js'
|
|
3
3
|
export { default as modal } from './components/modal.js'
|
|
4
|
-
|
|
4
|
+
export { default as badge } from './components/badge.js'
|
|
5
|
+
export { default as input } from './components/input.js'
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Meta, ColorPalette, ColorItem, Title } from '@storybook/blocks'
|
|
2
|
+
|
|
3
|
+
import { colorsFromCss, semanticColors } from '@/utils/util-get-colors-from-css'
|
|
4
|
+
|
|
5
|
+
<Meta title='Tokens/Colors' />
|
|
6
|
+
<Title>Colors</Title>
|
|
7
|
+
|
|
8
|
+
The color tokens within this design system encapsulates a rich palette of semantic colors, each with specific
|
|
9
|
+
roles and shades to cater to various UI elements and states.
|
|
10
|
+
|
|
11
|
+
The `primary` colors, with shades ranging from light lavender (#faf7fd) to deep purple (#361952), form the core visual identity, suitable for branding elements and primary actions.
|
|
12
|
+
|
|
13
|
+
The `secondary` colors shift towards teal (#f0fdfa to #042f2d), providing a refreshing contrast ideal for secondary actions or highlighting important UI elements without overpowering the primary hue.
|
|
14
|
+
|
|
15
|
+
The `accent` color spectrum, from a soft peach (#fff7ed) to a dark burnt orange (#431307), is designed to draw attention to specific components or prompts, making it perfect for call-to-action buttons or interactive elements.
|
|
16
|
+
|
|
17
|
+
- The information color in a design system typically employs a clear, subdued shade, such as a light blue or gray, to convey neutral and informative messages without invoking urgency or emotion.
|
|
18
|
+
- The `success` shades signify positive actions or confirmations, with a vibrant green (#f1fcf2 to #082b11) that should be used to indicate completion, approval, or progress.
|
|
19
|
+
- The `warning` palette, transitioning from a light yellow (#fffde7) to a darker shade (#442004), is tailored for cautionary messages or to highlight areas that require user attention.
|
|
20
|
+
- `danger` colors range from a soft pinkish-red (#fef3f2) to a dark maroon (#490815), ideal for error messages, critical warnings, or delete actions, signaling users to proceed with caution.
|
|
21
|
+
|
|
22
|
+
Lastly, the `slate` collection, with shades from very light gray (#f6f7f9) to almost black (#23272e), provides a neutral backdrop suited for text, backgrounds, and UI frames, ensuring legibility and a muted contrast against more vibrant colors.
|
|
23
|
+
|
|
24
|
+
Additional constants like `white`, `black`, `transparent`, and `currentColor` offer foundational colors for designing with flexibility and precision, supporting a cohesive and accessible user interface across the design system.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Raw Colors
|
|
29
|
+
|
|
30
|
+
<ColorPalette>
|
|
31
|
+
{Object.entries(colorsFromCss).map(([name, value]) => (
|
|
32
|
+
<ColorItem key={name} title={name} colors={value} />
|
|
33
|
+
))}
|
|
34
|
+
</ColorPalette>
|
|
35
|
+
|
|
36
|
+
## Semantic Colors
|
|
37
|
+
|
|
38
|
+
<ColorPalette>
|
|
39
|
+
{Object.entries(semanticColors).map(([name, value]) => (
|
|
40
|
+
<ColorItem key={name} title={name} colors={colorsFromCss[value]} subtitle={value} />
|
|
41
|
+
))}
|
|
42
|
+
</ColorPalette>
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { Meta } from '@storybook/blocks'
|
|
2
|
+
|
|
3
|
+
<Meta title='Introduction' />
|
|
4
|
+
|
|
5
|
+
# Introducción al Sistema de Diseño
|
|
6
|
+
|
|
7
|
+
Este sistema de diseño ha sido concebido como una infraestructura robusta y escalable para la creación de **Dashboards** unificados. Su objetivo principal es optimizar el ciclo de desarrollo mediante una biblioteca de componentes preconfigurados y diseñados específicamente para un diseño de Dashboard ya definido, que garantizan consistencia visual y funcional, sin sacrificar la flexibilidad necesaria para adaptaciones de marca.
|
|
8
|
+
|
|
9
|
+
## Arquitectura Subyacente
|
|
10
|
+
|
|
11
|
+
La librería está construida sobre **Nuxt UI**, lo que significa que todos sus componentes están disponibles para los desarrolladores. Sin embargo, el enfoque principal es crear componentes especializados que incorporen estilos y funcionalidades predefinidas adaptadas específicamente para el diseño del tipo de dashboard que se usa como base.
|
|
12
|
+
|
|
13
|
+
Por ejemplo, en lugar de utilizar directamente `UModal` de Nuxt UI y personalizarlo desde cero, el sistema proporciona `BModal`, un componente que extiende `UModal` con características adicionales y diseño preconfigurado para uso inmediato.
|
|
14
|
+
|
|
15
|
+
De esta manera, a diferencia de una biblioteca de componentes tradicional, este sistema actúa como una capa de abstracción semántica que:
|
|
16
|
+
|
|
17
|
+
1. **Agiliza el desarrollo:** Proporciona componentes con diseño base ya integrado para casos de uso comunes en dashboards.
|
|
18
|
+
2. **Mantiene la flexibilidad:** Aprovecha las capacidades de _Theming_ de Nuxt UI y las variables de CSS de Tailwind para permitir personalizaciones profundas (colores, bordes, espaciados) mediante archivos de configuración centralizados.
|
|
19
|
+
3. **Encapsula la complejidad:** En lugar de configurar componentes de terceros desde cero en cada vista, utilizamos "Wrappers" inteligentes (como `BModal` sobre `UModal`) que ya contienen la lógica y los estilos específicos de nuestro ecosistema.
|
|
20
|
+
|
|
21
|
+
## Sistema de Organización de Componentes
|
|
22
|
+
|
|
23
|
+
### Fundamento: Atomic Design
|
|
24
|
+
|
|
25
|
+
El sistema se basa en los principios de **[Atomic Design](https://bradfrost.com/blog/post/atomic-web-design/)**, adaptados específicamente para el desarrollo de componentes. La metodología se centra en tres niveles principales:
|
|
26
|
+
|
|
27
|
+
- **Átomos**: Unidades fundamentales e indivisibles del sistema. Son elementos reconocibles que requieren contexto adicional para tener sentido funcional. _Ejemplos_: botones, etiquetas, títulos.
|
|
28
|
+
- **Moléculas**: Composición de dos o más átomos que crean elementos con significado propio, aunque no son completamente independientes. _Ejemplos_: cards, pares label-input.
|
|
29
|
+
- **Organismos**: Estructuras complejas formadas por múltiples moléculas. Son elementos completamente independientes que mantienen su funcionalidad sin importar el contexto. _Ejemplos_: headers, grids con filtros.
|
|
30
|
+
|
|
31
|
+
> **Nota**: Los niveles de Templates y Páginas del Atomic Design original no aplican directamente al desarrollo de estilos, ya que se construyen mediante la composición de organismos en el marcado HTML.
|
|
32
|
+
|
|
33
|
+
### Sistema de Clasificación A-B-C-D
|
|
34
|
+
|
|
35
|
+
Basándonos en los principios de **Atomic Design**, hemos implementado una variación denominada **Sistema ABCD** (Atoms, Bases, Composites, Designs), que mantiene los conceptos fundamentales pero los reorganiza para mejor adaptarse a los tipos de componentes de la librería.
|
|
36
|
+
|
|
37
|
+
### A - Atoms (Átomos)
|
|
38
|
+
|
|
39
|
+
Se mantiene el concepto de _Átomos_ de **Atomic Design**, siendo los bloques de construcción más básicos e indivisibles de la interfaz. Aunque Nuxt UI provee la mayoría de los átomos estándar, en esta capa definimos elementos específicos que no existen en la biblioteca base o que requieren una estructura única.
|
|
40
|
+
|
|
41
|
+
- **Ejemplo:** `ACardInner`, `AButtonNavigation`, `APill`.
|
|
42
|
+
|
|
43
|
+
### B - Bases (Componentes Base)
|
|
44
|
+
|
|
45
|
+
Son componentes generales que pueden contener _Átomos_ o _Moléculas_, que actúan como "contenedores" o versiones estandarizadas de componentes más complejos. Si bien pueden usarse de forma directa, su propósito principal es definir un comportamiento y diseño general para ser reutilizados o extendidos.
|
|
46
|
+
|
|
47
|
+
- **Ejemplo:** `BModal`. Es un envoltorio (_wrapper_) de `UModal` que ya incluye los estándares de estilos, funcionalidades y estructura interna del proyecto.
|
|
48
|
+
|
|
49
|
+
### C - Composites (Compuestos)
|
|
50
|
+
|
|
51
|
+
Son especializaciones semánticas de un componente **Base**. Se crean para cubrir casos de uso específicos y repetitivos, eliminando la necesidad de pasar las mismas props y modificaciones de estilos repetidamente a un componente base.
|
|
52
|
+
|
|
53
|
+
- **Ejemplo:** `CModalDanger` (Una instancia de `BModal` preconfigurada con colores de error, iconos de advertencia y acciones de confirmación destructivas).
|
|
54
|
+
|
|
55
|
+
### D - Designs (Diseños/Organismos)
|
|
56
|
+
|
|
57
|
+
Son estructuras complejas y autónomas compuestas por la unión de _Atoms_, _Bases_, o _Composites_. A menudo representan secciones enteras de una página o componentes con una lógica de negocio específica y altamente reutilizable.
|
|
58
|
+
|
|
59
|
+
- **Ejemplo:** Pueden ser secciones reutilizables más grandes similares a _Organismos_ compuestas por varios componentes, como por ejemplo `DCardHeader`, o algo más contenidas como _Moléculas_ pero que no requerirá de variantes al ser más específicas, que por lo tanto pueden tener lógica ya suscrita, por ejemplo `DUploadAvatar`
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Convención de Nomenclatura y Estructura
|
|
64
|
+
|
|
65
|
+
La librería implementa el **sistema de nombramiento por ruta de Nuxt**, donde el nombre del componente refleja directamente su ubicación en la estructura de directorios. Este enfoque proporciona trazabilidad inmediata y facilita su auto-importación y la identificación de la categoría del componente mediante su prefijo.
|
|
66
|
+
|
|
67
|
+
La ubicación en el sistema de archivos dicta el nombre del componente:
|
|
68
|
+
|
|
69
|
+
```text
|
|
70
|
+
app/
|
|
71
|
+
└── components/
|
|
72
|
+
├── a/ # Átomos
|
|
73
|
+
│ └── a-pill.vue
|
|
74
|
+
├── b/ # Bases
|
|
75
|
+
│ └── b-modal.vue
|
|
76
|
+
├── c/ # Composites
|
|
77
|
+
│ └── c-modal-danger.vue
|
|
78
|
+
└── d/ # Designs
|
|
79
|
+
└── d-card-header.vue
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Beneficios de este enfoque:
|
|
83
|
+
|
|
84
|
+
- **Autodescriptivo:** El prefijo (`A-`, `B-`, `C-`, `D-`) indica inmediatamente el nivel de complejidad y el propósito del componente.
|
|
85
|
+
- **Escalabilidad**: Facilita la organización de nuevos componentes dentro de la estructura existente basandose en la jerarquía
|
|
86
|
+
- **Trazabilidad**: La ruta del componente indica inmediatamente su categoría y propósito
|
|
87
|
+
- **Sin Colisiones:** Evita conflictos con los componentes nativos de Nuxt UI (prefijados con `U-`).
|
|
88
|
+
- **Mantenimiento**: Simplifica la localización y modificación de componentes específicos
|
|
89
|
+
- **Colaboración**: Estandariza el proceso de desarrollo para equipos múltiples
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Stack Tecnológico
|
|
94
|
+
|
|
95
|
+
Este sistema está alineado con las últimas versiones de las tecnologías líderes en el ecosistema Vue:
|
|
96
|
+
|
|
97
|
+
- **Framework:** [Nuxt 4](https://nuxt.com/) (Estructura de directorios `app/`, auto-imports y alta performance).
|
|
98
|
+
- **UI Library:** [@nuxt/ui 4](https://ui.nuxt.com/) (Base de componentes accesibles y personalizables).
|
|
99
|
+
- **Styling:** [Tailwind CSS 4](https://tailwindcss.com/) (Motor de utilidades de última generación).
|
|
100
|
+
- **Documentación:** [Storybook 8](https://storybook.js.org/) (Desarrollo y pruebas de componentes en aislamiento).
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
|
+
import { fn } from '@storybook/test'
|
|
3
|
+
import AButtonAvatarDropdown, { type ButtonSize, type AvatarSize } from './a-button-avatar-dropdown.vue'
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: 'Atoms/Button/AButtonAvatarDropdown',
|
|
7
|
+
component: AButtonAvatarDropdown,
|
|
8
|
+
parameters: {
|
|
9
|
+
docs: {
|
|
10
|
+
description: {
|
|
11
|
+
component: 'Button with avatar for drop-down menus with user information. Typically used in the navigation bar.',
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
argTypes: {
|
|
16
|
+
src: {
|
|
17
|
+
control: 'text',
|
|
18
|
+
},
|
|
19
|
+
buttonSize: {
|
|
20
|
+
control: 'select',
|
|
21
|
+
options: ['xs', 'sm', 'md', 'lg', 'xl'] satisfies ButtonSize[],
|
|
22
|
+
},
|
|
23
|
+
avatarSize: {
|
|
24
|
+
control: 'select',
|
|
25
|
+
options: ['3xs', '2xs', 'xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl'] satisfies AvatarSize[],
|
|
26
|
+
},
|
|
27
|
+
'onOn-click': {
|
|
28
|
+
table: {
|
|
29
|
+
disable: true,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
args: {
|
|
34
|
+
'onOn-click': fn(),
|
|
35
|
+
},
|
|
36
|
+
} satisfies Meta<typeof AButtonAvatarDropdown>
|
|
37
|
+
|
|
38
|
+
export default meta
|
|
39
|
+
|
|
40
|
+
type Story = StoryObj<typeof meta>
|
|
41
|
+
|
|
42
|
+
export const Default: Story = {
|
|
43
|
+
args: {
|
|
44
|
+
src: '~/../public/media/img/user-unknown.png',
|
|
45
|
+
buttonSize: 'md',
|
|
46
|
+
avatarSize: 'sm',
|
|
47
|
+
},
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export const SmallButton: Story = {
|
|
51
|
+
args: {
|
|
52
|
+
...Default.args,
|
|
53
|
+
buttonSize: 'xs',
|
|
54
|
+
avatarSize: 'xs',
|
|
55
|
+
},
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const LargeButton: Story = {
|
|
59
|
+
args: {
|
|
60
|
+
...Default.args,
|
|
61
|
+
buttonSize: 'xl',
|
|
62
|
+
avatarSize: 'md',
|
|
63
|
+
},
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export const WithSlot: Story = {
|
|
67
|
+
args: {
|
|
68
|
+
...Default.args,
|
|
69
|
+
},
|
|
70
|
+
render: (args) => ({
|
|
71
|
+
components: { AButtonAvatarDropdown },
|
|
72
|
+
setup() {
|
|
73
|
+
return { args }
|
|
74
|
+
},
|
|
75
|
+
template: `
|
|
76
|
+
<AButtonAvatarDropdown v-bind="args">
|
|
77
|
+
<template #default>
|
|
78
|
+
<span>Victor Alvarez</span>
|
|
79
|
+
</template>
|
|
80
|
+
</AButtonAvatarDropdown>
|
|
81
|
+
`,
|
|
82
|
+
}),
|
|
83
|
+
}
|
|
@@ -1,21 +1,44 @@
|
|
|
1
|
-
<script lang="
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import type { UButton, UAvatar } from '#components'
|
|
3
|
+
|
|
4
|
+
export type ButtonSize = InstanceType<typeof UButton>['$props']['size']
|
|
5
|
+
export type AvatarSize = InstanceType<typeof UAvatar>['$props']['size']
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
/**
|
|
9
|
+
* The source (path or URL) of the avatar
|
|
10
|
+
* @type string
|
|
11
|
+
*/
|
|
12
|
+
src?: string
|
|
13
|
+
/**
|
|
14
|
+
* The size of the button
|
|
15
|
+
* @type ButtonSize
|
|
16
|
+
*/
|
|
17
|
+
buttonSize?: ButtonSize
|
|
18
|
+
/**
|
|
19
|
+
* The size of the avatarSize
|
|
20
|
+
* @type AvatarSize
|
|
21
|
+
*/
|
|
22
|
+
avatarSize?: AvatarSize
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
26
|
+
src: '/media/img/user-unknown.png',
|
|
27
|
+
buttonSize: 'md',
|
|
28
|
+
avatarSize: 'sm',
|
|
18
29
|
})
|
|
30
|
+
|
|
31
|
+
defineSlots<{
|
|
32
|
+
/** Example description for default */
|
|
33
|
+
default(): any
|
|
34
|
+
}>()
|
|
35
|
+
|
|
36
|
+
const emit = defineEmits<{
|
|
37
|
+
/**
|
|
38
|
+
* Emitted when the button is clicked
|
|
39
|
+
*/
|
|
40
|
+
(e: 'on-click'): void
|
|
41
|
+
}>()
|
|
19
42
|
</script>
|
|
20
43
|
|
|
21
44
|
<template>
|
|
@@ -35,6 +58,7 @@ const props = defineProps({
|
|
|
35
58
|
color="primary"
|
|
36
59
|
variant="ghost"
|
|
37
60
|
class="rounded-full"
|
|
61
|
+
@click="emit('on-click')"
|
|
38
62
|
>
|
|
39
63
|
<slot />
|
|
40
64
|
</UButton>
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
|
+
import { fn } from '@storybook/test'
|
|
3
|
+
import AButtonNavigation, { type ButtonSize } from './a-button-navigation.vue'
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: 'Atoms/Button/AButtonNavigation',
|
|
7
|
+
component: AButtonNavigation,
|
|
8
|
+
parameters: {
|
|
9
|
+
docs: {
|
|
10
|
+
description: {
|
|
11
|
+
component: 'Navigation button with icon, useful for moving between pages or triggering an action. Generally used in the header of main sections alongside the [DCardHeader](?path=/docs/design-card-header--docs) component.',
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
argTypes: {
|
|
16
|
+
size: {
|
|
17
|
+
control: 'select',
|
|
18
|
+
options: ['xs', 'sm', 'md', 'lg', 'xl'] satisfies ButtonSize[],
|
|
19
|
+
},
|
|
20
|
+
'onOn-click': {
|
|
21
|
+
table: {
|
|
22
|
+
disable: true,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
args: {
|
|
27
|
+
'onOn-click': fn(),
|
|
28
|
+
},
|
|
29
|
+
} satisfies Meta<typeof AButtonNavigation>
|
|
30
|
+
|
|
31
|
+
type Story = StoryObj<typeof meta>
|
|
32
|
+
|
|
33
|
+
export default meta
|
|
34
|
+
|
|
35
|
+
export const Default: Story = {
|
|
36
|
+
args: {
|
|
37
|
+
icon: 'heroicons:arrow-left-16-solid',
|
|
38
|
+
to: '',
|
|
39
|
+
hasBackAction: false,
|
|
40
|
+
},
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const CustomIconWithCustomRoute: Story = {
|
|
44
|
+
args: {
|
|
45
|
+
icon: 'heroicons:home-20-solid',
|
|
46
|
+
to: '/',
|
|
47
|
+
hasBackAction: false,
|
|
48
|
+
},
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export const HasBackAction: Story = {
|
|
52
|
+
args: {
|
|
53
|
+
icon: 'heroicons:arrow-left-16-solid',
|
|
54
|
+
to: '',
|
|
55
|
+
hasBackAction: true,
|
|
56
|
+
},
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export const LargeButton: Story = {
|
|
60
|
+
args: {
|
|
61
|
+
icon: 'heroicons:arrow-left-16-solid',
|
|
62
|
+
to: '',
|
|
63
|
+
hasBackAction: true,
|
|
64
|
+
size: 'xl',
|
|
65
|
+
},
|
|
66
|
+
}
|