Package Exports
- @asemh/design-system
- @asemh/design-system/styles.css
- @asemh/design-system/tokens.css
Readme
@asemh/design-system
Sistema de diseño modular y temático especializado para interfaces CRM y aplicaciones administrativas con alta densidad de datos. Construido con React, TypeScript, Tailwind CSS v4 y Radix UI.
✨ Características
- 🎨 Sistema de temas completo con modo claro/oscuro
- 🧩 50+ componentes organizados en Atomic Design
- 🔒 TypeScript estricto con tipos exportados
- ♿ Accesibilidad WCAG 2.1 via Radix UI primitives
- 🚀 Tree-shakeable - importa solo lo que necesitas
- 💅 Glass morphism utilities incluidas
- 📦 Zero config - funciona out of the box
📦 Guía de Instalación y Configuración
Este sistema de diseño es una biblioteca de componentes que debes instalar dentro de un proyecto React existente. No es un framework autónomo.
📋 Requisitos Previos
Antes de comenzar, asegúrate de tener un proyecto configurado con:
- React 18 o superior
- Tailwind CSS v4 (o superior)
- TypeScript (recomendado para mejor experiencia)
Funciona perfectamente con frameworks como Astro, Next.js, Vite, o Remix.
🛠️ Paso 1: Instalación
Instala el paquete y sus dependencias principales en tu proyecto:
# pnpm (recomendado)
pnpm add @asemh/design-system react react-dom
# npm
npm install @asemh/design-system react react-dom
# yarn
yarn add @asemh/design-system react react-domNota: Si ya tienes
reactyreact-dominstalados, puedes omitirlos en el comando.
🔌 Paso 2: Integración con Tailwind CSS
Para que los estilos funcionen correctamente, debes decirle a Tailwind dónde buscar los componentes de la librería.
Edita tu archivo de configuración de Tailwind (usualmente tailwind.config.js o tailwind.config.mjs):
/** @type {import('tailwindcss').Config} */
export default {
content: [
// ...tus rutas existentes (ej. './src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'),
// 👇 AÑADE ESTA LÍNEA para incluir los componentes del sistema de diseño
'./node_modules/@asemh/design-system/dist/**/*.{js,mjs}'
],
// ... resto de tu configuración
}🎨 Paso 3: Importar Estilos Base
Debes importar los estilos compilados del sistema de diseño en el punto de entrada principal de tu aplicación.
En Astro (dentro de Layout.astro o similar):
---
import '@asemh/design-system/styles.css';
---En Vite / Create React App (main.tsx o App.tsx):
import React from 'react';
import ReactDOM from 'react-dom/client';
import '@asemh/design-system/styles.css'; // 👈 Importar aquí al inicio
import App from './App';En Next.js (app/layout.tsx o pages/_app.tsx):
import '@asemh/design-system/styles.css';
import './globals.css';🌓 Paso 4: Configuración de Tema (Dark Mode)
El sistema soporta modo oscuro nativamente usando la clase .dark en el elemento html o body.
Para evitar el "flash" de tema blanco al cargar, recomendamos añadir este script en el <head> de tu documento principal (index.html, Layout.astro, o layout.tsx):
<script is:inline>
// El 'is:inline' es necesario si usas Astro
(function() {
const stored = localStorage.getItem('theme');
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const theme = stored || (prefersDark ? 'dark' : 'light');
if (theme === 'dark') document.documentElement.classList.add('dark');
})();
</script>🚀 Paso 5: ¡Listo para usar!
Ahora puedes importar y usar los componentes en cualquier parte de tu aplicación:
import { Button, Card, CardHeader, CardTitle, CardContent, Badge } from '@asemh/design-system';
export default function MiComponente() {
return (
<Card className="max-w-sm">
<CardHeader>
<CardTitle className="flex items-center justify-between">
Dashboard
<Badge variant="success">Sistema Activo</Badge>
</CardTitle>
</CardHeader>
<CardContent>
<p className="mb-4 text-muted-foreground">Bienvenido al sistema de gestión.</p>
<Button variant="default" className="w-full">
Iniciar Sesión
</Button>
</CardContent>
</Card>
);
}📚 Componentes
Atoms (Primitivos)
| Componente | Descripción |
|---|---|
Avatar |
Imagen de perfil con fallback |
Badge |
Etiquetas de estado y categorías |
Breadcrumb |
Navegación jerárquica |
Button |
Botón con múltiples variantes |
Calendar |
Calendario interactivo |
Card |
Contenedor con header, content, footer |
Checkbox |
Casilla de verificación |
DropdownMenu |
Menú desplegable contextual |
Input |
Campo de texto |
Label |
Etiqueta para formularios |
List |
Listas estructuradas |
Media |
Imágenes y videos responsivos |
PasswordInput |
Input con toggle de visibilidad |
Progress |
Barra de progreso |
Radio |
Botones de radio |
ScrollArea |
Área de scroll personalizada |
Select |
Selector desplegable |
Separator |
Divisor visual |
Skeleton |
Placeholder de carga |
Slider |
Control deslizante |
SpecializedInput |
Inputs especializados (moneda, porcentaje) |
Spinner |
Indicador de carga |
Switch |
Toggle on/off |
Table |
Tabla de datos |
Tabs |
Navegación por pestañas |
Textarea |
Área de texto multilínea |
Tooltip |
Información emergente |
Zoom |
Zoom de imágenes |
Molecules (Compuestos)
| Componente | Descripción |
|---|---|
DatePicker |
Selector de fecha |
DateRangePicker |
Selector de rango de fechas |
FormField |
Campo de formulario con label y error |
ThemeToggle |
Toggle de tema claro/oscuro |
Organisms (Complejos)
| Componente | Descripción |
|---|---|
Header |
Header de aplicación |
DocsHeader |
Header para documentación |
Sidebar |
Barra lateral de navegación |
GlassHeader |
Header con efecto glass morphism |
🎨 Temas y Personalización
Variables CSS
El sistema usa variables CSS que puedes sobrescribir:
:root {
/* Colores primarios */
--primary: 215 100% 50%;
--primary-foreground: 0 0% 100%;
/* Colores de fondo */
--background: 0 0% 100%;
--foreground: 0 0% 10%;
/* Bordes y superficies */
--border: 0 0% 90%;
--card: 0 0% 100%;
--muted: 0 0% 96%;
/* Estados semánticos */
--success: 142 76% 36%;
--warning: 38 92% 50%;
--destructive: 0 84% 60%;
/* Radio de bordes */
--radius: 0.5rem;
}
.dark {
--background: 0 0% 7%;
--foreground: 0 0% 95%;
/* ... más variables */
}Glass Morphism
Utilidades incluidas para efectos glass:
// Clases disponibles
<div className="glass">...</div> // Glass básico
<div className="glass-subtle">...</div> // Glass sutil
<div className="glass-strong">...</div> // Glass pronunciado
<div className="glass-border">...</div> // Bordes glassSolo Tokens CSS
Si solo necesitas las variables CSS sin los componentes:
import '@asemh/design-system/tokens.css';📜 Scripts disponibles
| Script | Descripción |
|---|---|
pnpm dev |
Inicia el entorno de desarrollo con Astro |
pnpm build |
Construye el sitio de documentación estático |
pnpm build:lib |
Compila la librería para distribución (JS/DTS/CSS) |
pnpm preview |
Vista previa local del build de documentación |
pnpm release:patch |
Incrementa versión patch + build + publish + git push |
pnpm release:minor |
Incrementa versión minor + build + publish + git push |
pnpm release:major |
Incrementa versión major + build + publish + git push |
⚙️ Configuración Avanzada
Con Tailwind CSS v4
// tailwind.config.js
export default {
content: [
'./src/**/*.{js,ts,jsx,tsx}',
'./node_modules/@asemh/design-system/dist/**/*.{js,mjs}'
],
// El tema se extiende automáticamente via CSS variables
}Estado Global (Tema)
El paquete exporta un store de tema basado en nanostores:
import { themeStore, toggleTheme, setTheme } from '@asemh/design-system';
import { useStore } from '@nanostores/react';
function ThemeButton() {
const $theme = useStore(themeStore);
return (
<button onClick={toggleTheme}>
Tema actual: {$theme}
</button>
);
}
// O establece un tema específico
setTheme('dark');Notificaciones Toast
import { toast, Toaster } from '@asemh/design-system';
// En tu layout
function Layout({ children }) {
return (
<>
{children}
<Toaster richColors position="bottom-right" />
</>
);
}
// En cualquier componente
function SaveButton() {
const handleSave = () => {
toast.success('Guardado exitosamente');
// toast.error('Error al guardar');
// toast.info('Información');
// toast.warning('Advertencia');
};
return <Button onClick={handleSave}>Guardar</Button>;
}📖 Ejemplos
Dashboard KPI Card
import {
Card, CardHeader, CardTitle, CardContent,
Badge, Progress
} from '@asemh/design-system';
function KPICard({ title, value, target, trend }) {
const percentage = (value / target) * 100;
return (
<Card>
<CardHeader className="pb-2">
<CardTitle className="text-sm font-medium text-muted-foreground">
{title}
</CardTitle>
</CardHeader>
<CardContent>
<div className="flex items-baseline justify-between">
<span className="text-2xl font-bold">{value}</span>
<Badge variant={trend > 0 ? 'success' : 'destructive'}>
{trend > 0 ? '+' : ''}{trend}%
</Badge>
</div>
<Progress value={percentage} className="mt-3" />
<p className="text-xs text-muted-foreground mt-1">
{percentage.toFixed(0)}% del objetivo
</p>
</CardContent>
</Card>
);
}Formulario de Contacto
import {
Card, CardHeader, CardTitle, CardContent, CardFooter,
Input, Label, Textarea, Button, toast
} from '@asemh/design-system';
function ContactForm() {
const handleSubmit = (e) => {
e.preventDefault();
toast.success('Mensaje enviado correctamente');
};
return (
<Card className="max-w-md">
<form onSubmit={handleSubmit}>
<CardHeader>
<CardTitle>Contáctanos</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-2">
<Label htmlFor="name">Nombre</Label>
<Input id="name" placeholder="Tu nombre" required />
</div>
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" placeholder="tu@email.com" required />
</div>
<div className="space-y-2">
<Label htmlFor="message">Mensaje</Label>
<Textarea id="message" placeholder="Escribe tu mensaje..." rows={4} />
</div>
</CardContent>
<CardFooter>
<Button type="submit" className="w-full">
Enviar mensaje
</Button>
</CardFooter>
</form>
</Card>
);
}🤝 Contribuir
Las contribuciones son bienvenidas. Por favor, abre un issue primero para discutir los cambios que te gustaría hacer.
📄 Licencia
MIT © ASEMH
¿Encontraste útil este paquete? ⭐ Dale una estrella en GitHub