@cristianrg/vue-components
v1.0.0
Published
A collection of Vue.js components for building modern web applications.
Maintainers
Readme
@cris/vue-components
Librería de componentes Vue 3 moderna y minimalista
Created by @Cristianrg
Una librería de componentes Vue 3 diseñada con un enfoque moderno y minimalista, perfecta para aplicaciones web contemporáneas. Cada componente está construido siguiendo principios de diseño centrado en la experiencia del usuario, con estilos predeterminados elegantes y una arquitectura completamente personalizable.
✨ Características principales
- 🎨 Diseño minimalista y moderno: Componentes con estilos limpios, elegantes y cohesivos
- 🏗️ Arquitectura basada en interfaces: Sistema robusto de props tipadas con TypeScript para máxima flexibilidad
- ⚙️ Totalmente personalizable: Variables CSS y props para adaptar colores, tamaños y comportamientos
- 📱 Responsive por defecto: Optimizados para cualquier dispositivo y tamaño de pantalla
- 🚀 TypeScript nativo: Soporte completo con tipado estricto e IntelliSense
- 🌳 Tree-shaking friendly: Importa solo los componentes que necesitas para bundles optimizados
- ♿ Accesibilidad: Componentes construidos siguiendo estándares WCAG
- 🎛️ Componentes inteligentes: Lógica de estado interna para funcionalidades complejas
📦 Instalación
npm install @cris/vue-components🎨 Importar estilos
¡IMPORTANTE! Para que los componentes se muestren correctamente, debes importar los estilos CSS:
// En tu main.js o main.ts
import '@cris/vue-components/vue-components.css'O alternativamente en tu CSS principal:
@import '@cris/vue-components/vue-components.css';🚀 Componentes disponibles
La librería incluye los siguientes componentes listos para usar:
- Button - Botones interactivos con múltiples variantes
- Modal - Modales con gestión automática de estado y accesibilidad
- Card - Contenedores con elevación y efectos hover opcionales
- Input - Campos de entrada con validación y múltiples tipos
- Form - Formularios completos con validación automática
- Table - Tablas dinámicas con edición inline
- Search - Componente de búsqueda con callback personalizable
- ChoiceBox - Checkboxes estilizados con múltiples tamaños
- Details - Acordeones expansibles
- Hero - Secciones destacadas para landing pages
- Separator - Divisores visuales
- ConfirmActions - Diálogos de confirmación
💡 Ejemplos de uso
Ejemplo básico - Button y Modal
<template>
<div>
<!-- Botón principal que abre modal -->
<Button :button="primaryButton" />
<!-- Modal con acciones personalizadas -->
<Modal :modal="confirmModal">
<p>¿Estás seguro de que quieres realizar esta acción?</p>
<p>Esta operación no se puede deshacer.</p>
</Modal>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { Button, Modal, type Ibutton, type IModal } from "@cris/vue-components"
const showModal = ref(false)
// Configuración del botón principal
const primaryButton: Ibutton = {
label: "Abrir Modal",
class: "primary",
size: "medium",
action: () => {
showModal.value = true
}
}
// Configuración del modal con botones de acción
const confirmModal: IModal = {
title: "Confirmar Acción",
isOpen: showModal,
onClose: () => {
showModal.value = false
},
buttons: [
{
label: "Cancelar",
class: "secondary",
action: () => {
showModal.value = false
}
},
{
label: "Confirmar",
class: "primary",
action: () => {
console.log('¡Acción confirmada!')
showModal.value = false
}
}
]
}
</script>Ejemplo avanzado - Formulario completo
<template>
<Card :elevationInHover="true">
<Form :form="userForm" @submit="handleSubmit" />
</Card>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
import { Card, Form, type IForm, type IInput } from "@cris/vue-components"
// Configuración del formulario
const userForm: IForm = {
id: "user-registration",
title: "Registro de Usuario",
inputs: [
{
id: "name",
label: "Nombre completo",
type: "text",
placeholder: "Ingresa tu nombre",
required: true,
validator: (value: string) => value.length >= 2,
errorMessage: "El nombre debe tener al menos 2 caracteres"
},
{
id: "email",
label: "Correo electrónico",
type: "email",
placeholder: "[email protected]",
required: true,
validator: (value: string) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value),
errorMessage: "Ingresa un email válido"
},
{
id: "role",
label: "Rol",
type: "select",
required: true,
options: [
{ value: "admin", label: "Administrador" },
{ value: "user", label: "Usuario" },
{ value: "guest", label: "Invitado" }
]
}
],
submit: {
label: "Registrar Usuario",
class: "primary",
action: () => console.log('Formulario enviado')
},
cancel: {
label: "Cancelar",
class: "secondary",
action: () => console.log('Formulario cancelado')
}
}
const handleSubmit = (data: Record<string, any>) => {
console.log('Datos del formulario:', data)
// Aquí puedes enviar los datos a tu API
}
</script>Ejemplo con Table y búsqueda
<template>
<div>
<!-- Buscador -->
<Search :search="searchConfig" />
<!-- Tabla de datos -->
<Table :table="usersTable" />
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { Table, Search, type ITable, type ISearch, type IRow } from "@cris/vue-components"
const searchTerm = ref('')
// Configuración del buscador
const searchConfig: ISearch = {
placeholder: "Buscar usuarios...",
value: searchTerm.value,
onSearch: (value: string) => {
searchTerm.value = value
}
}
// Datos de ejemplo
const allUsers = [
{ name: 'Juan Pérez', email: '[email protected]', role: 'Admin' },
{ name: 'María García', email: '[email protected]', role: 'Usuario' },
{ name: 'Carlos López', email: '[email protected]', role: 'Invitado' }
]
// Tabla con filtrado dinámico
const usersTable = computed((): ITable => {
const filteredUsers = allUsers.filter(user =>
user.name.toLowerCase().includes(searchTerm.value.toLowerCase()) ||
user.email.toLowerCase().includes(searchTerm.value.toLowerCase())
)
return {
name: "Usuarios del Sistema",
headers: ["Nombre", "Email", "Rol", "Acciones"],
rows: filteredUsers.map((user): IRow => ({
cells: [
{ value: user.name, type: 'text' },
{ value: user.email, type: 'text' },
{ value: user.role, type: 'text' }
],
actions: [
{
label: "Editar",
class: "primary",
size: "small",
action: () => console.log('Editando:', user.name)
},
{
label: "Eliminar",
class: "danger",
size: "small",
action: () => console.log('Eliminando:', user.name)
}
]
}))
}
})
</script>🎨 Personalización y temas
Variables CSS personalizables
Todos los componentes pueden ser personalizados mediante variables CSS globales:
:root {
/* Colores principales */
--primary-color: #007bff;
--primary-color-hover: #0056b3;
--secondary-color: #6c757d;
--secondary-color-hover: #545b62;
--secondary-color-light: #f8f9fa;
--secondary-color-light-hover: #e9ecef;
/* Colores de estado */
--danger-color: #dc3545;
--success-color: #28a745;
--warning-color: #ffc107;
/* Tipografía */
--font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
--font-size-sm: 0.875rem;
--font-size-base: 1rem;
--font-size-lg: 1.125rem;
/* Espaciado */
--spacing-xs: 0.25rem;
--spacing-sm: 0.5rem;
--spacing-md: 1rem;
--spacing-lg: 1.5rem;
--spacing-xl: 2rem;
/* Bordes y sombras */
--border-radius: 0.375rem;
--box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
--box-shadow-lg: 0 4px 12px rgba(0, 0, 0, 0.15);
}Personalización por componente
<template>
<!-- Botón con estilos personalizados -->
<Button
:button="customButton"
:style="customButtonStyle"
/>
<!-- Card con tema oscuro -->
<Card
:elevationInHover="true"
class="dark-theme"
>
<h3>Contenido en tema oscuro</h3>
</Card>
</template>
<script setup lang="ts">
import { Button, Card } from "@cris/vue-components"
const customButton = {
label: "Botón Personalizado",
class: "primary" as const,
size: "large" as const,
action: () => console.log('Click!')
}
// Estilos CSS personalizados
const customButtonStyle = {
'--primary-color': '#ff6b6b',
'--primary-color-hover': '#ff5252',
'--border-radius': '50px',
'--font-weight': 'bold'
}
</script>
<style scoped>
.dark-theme {
--secondary-color-light: #2d3748;
--text-color: #f7fafc;
color: var(--text-color);
}
</style>🔧 Configuración avanzada
Importación selectiva
Para optimizar el bundle, importa solo los componentes que necesitas:
// Importación específica (recomendado)
import { Button, Modal, type Ibutton, type IModal } from "@cris/vue-components"
// Importación completa (no recomendado para producción)
import * as CrisComponents from "@cris/vue-components"Configuración global
Puedes configurar estilos globales en tu aplicación principal:
// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import '@cris/vue-components/dist/style.css' // Estilos base
const app = createApp(App)
// Configuración de variables CSS globales
document.documentElement.style.setProperty('--primary-color', '#your-brand-color')
app.mount('#app')📚 Interfaces TypeScript
La librería proporciona interfaces TypeScript completas para todos los componentes:
import type {
Ibutton,
IModal,
IInput,
IForm,
ITable,
IRow,
ICell,
ISearch,
IChoiceBox,
IDetails,
IConfirmAction
} from "@cris/vue-components"
// Ejemplo de tipado estricto
const myButton: Ibutton = {
label: "Mi Botón",
class: "primary", // Solo acepta: 'primary' | 'secondary' | 'danger'
size: "medium", // Solo acepta: 'small' | 'medium' | 'large' | 'xlarge'
disabled: false,
action: () => {
// Tu lógica aquí
}
}🚀 Mejores prácticas
- Reactivity: Usa
ref()oreactive()para datos que cambien dinámicamente - Performance: Implementa
computed()para datos derivados complejos - Accessibility: Los componentes incluyen ARIA labels, aprovecha las funcionalidades integradas
- Validación: Utiliza las funciones
validatoren inputs para UX mejorada - Gestión de estado: Para aplicaciones complejas, considera usar Pinia o Vuex
🤝 Contribución y soporte
Esta librería está en desarrollo activo. Para reportar bugs, solicitar features o contribuir:
- Reporta issues detallados con ejemplos reproducibles
- Sigue las convenciones de código existentes
- Incluye tests para nuevas funcionalidades
- Documenta cambios en el README
