@cuenti-cn/ui
v0.1.8
Published
A modern React component library built with Tailwind CSS and Radix UI
Maintainers
Readme
Cuenti CN UI
Una librería moderna de componentes React construida con Tailwind CSS y Radix UI.
🚀 Instalación
Instalación Completa
Instala todos los componentes de una vez:
npm install cuenti-cn-ui
# o
yarn add cuenti-cn-ui
# o
pnpm add cuenti-cn-uiInstalación por Componentes Individuales
Instala solo los componentes que necesites para un bundle más pequeño:
# Primero instala las utilidades core (siempre requeridas)
npm install @cuenti-cn/core
# Luego instala los componentes específicos que necesites
npm install @cuenti-cn/button
# O múltiples componentes a la vez
npm install @cuenti-cn/button @cuenti-cn/coreVentajas de la instalación individual:
- 📦 Bundle más pequeño - Solo incluye lo que necesitas
- 🚀 Carga más rápida - Menos código para cargar
- 🔄 Actualizaciones granulares - Actualiza solo componentes específicos
Paquetes Disponibles
| Paquete | Descripción | Instalación | Tamaño |
| ------------------- | ------------------------------------------ | ------------------------------- | ------ |
| cuenti-cn-ui | Paquete completo con todos los componentes | npm install cuenti-cn-ui | ~50KB |
| @cuenti-cn/core | Utilidades y estilos base (requerido) | npm install @cuenti-cn/core | ~5KB |
| @cuenti-cn/button | Componente Button | npm install @cuenti-cn/button | ~8KB |
Próximos componentes en desarrollo:
@cuenti-cn/input- Componente de entrada de texto@cuenti-cn/card- Componente de tarjeta@cuenti-cn/modal- Componente modal/dialog
🎨 Configuración de Estilos
Configuración Automática
Al instalar cualquier paquete, se ejecutará automáticamente un script que:
- 🔍 Detecta tu archivo CSS global (globals.css, global.css, index.css, etc.)
- 💾 Crea una copia de seguridad del archivo existente
- ❓ Te pregunta si deseas sobrescribirlo con los estilos de Cuenti CN UI
- ✅ Aplica los estilos necesarios para que los componentes funcionen correctamente
Configuración Manual
Si prefieres configurar manualmente los estilos:
/* En tu archivo CSS principal */
@import 'cuenti-cn-ui/styles';
/* O si usas componentes individuales */
@import '@cuenti-cn/core/styles';📦 Uso
Uso de la Librería Completa
import { Button } from 'cuenti-cn-ui'
function App() {
return (
<Button variant="default" size="lg">
¡Hola Mundo!
</Button>
)
}Uso de Componentes Individuales
import { Button } from '@cuenti-cn/button'
function App() {
return <Button variant="outline">Botón Individual</Button>
}Importación de Utilidades
import { cn } from '@cuenti-cn/core'
// Uso de la función de utilidad para combinar clases
const buttonClass = cn('base-button-classes', condition && 'conditional-classes')/_ O si usas componentes individuales _/ @import '@cuenti-cn/core/styles';
## 📦 Uso
### Uso de la Librería Completa
```tsx
import { Button } from 'cuenti-cn-ui'
function App() {
return (
<Button variant="default" size="lg">
¡Hola Mundo!
</Button>
)
}Uso de Componentes Individuales
import { Button } from '@cuenti-cn/button'
function App() {
return <Button variant="outline">Botón Individual</Button>
}Importación de Utilidades
import { cn } from '@cuenti-cn/core'
// Uso de la función de utilidad para combinar clases
const buttonClass = cn('base-button-classes', condition && 'conditional-classes')Ejemplos de Instalación y Uso
Caso 1: Proyecto nuevo con todos los componentes
# Instalación
npm install cuenti-cn-ui
# Uso
import { Button } from 'cuenti-cn-ui'Caso 2: Proyecto con bundle optimization
# Instalación granular
npm install @cuenti-cn/core @cuenti-cn/button
# Uso
import { Button } from '@cuenti-cn/button'
import { cn } from '@cuenti-cn/core'Caso 3: Añadir un componente a proyecto existente
# Si ya tienes @cuenti-cn/core
npm install @cuenti-cn/button
# Si es tu primer componente individual
npm install @cuenti-cn/core @cuenti-cn/button🧱 Componentes Disponibles
Button
Un componente de botón versátil con múltiples variantes y tamaños.
import { Button } from 'cuenti-cn-ui'
// o
import { Button } from '@cuenti-cn/button'
// Variantes disponibles
<Button variant="default">Default</Button>
<Button variant="destructive">Destructive</Button>
<Button variant="outline">Outline</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>
// Tamaños disponibles
<Button size="sm">Pequeño</Button>
<Button size="default">Default</Button>
<Button size="lg">Grande</Button>
<Button size="icon">🔍</Button>Props del Button
| Prop | Tipo | Default | Descripción |
| -------------------- | ----------------------------------------------------------------------------- | ----------- | --------------------------------------------------- |
| variant | 'default' \| 'destructive' \| 'outline' \| 'secondary' \| 'ghost' \| 'link' | 'default' | Estilo visual del botón |
| size | 'default' \| 'sm' \| 'lg' \| 'icon' | 'default' | Tamaño del botón |
| asChild | boolean | false | Renderiza como un componente hijo usando Radix Slot |
| accessibilityLabel | string | - | Label de accesibilidad (requerido para size="icon") |
🛠️ Desarrollo
Ejecutar Storybook
pnpm storybookBuild de la librería
# Build completo (librería + paquetes individuales)
pnpm build
# Solo paquetes individuales
pnpm build:packagesLinting y Formateo
pnpm lint
pnpm format➕ Añadir Nuevos Componentes
Estructura para Nuevos Componentes
Para añadir un nuevo componente, sigue esta estructura de directorios:
packages/
├── tu-nuevo-componente/
│ ├── package.json
│ ├── tsconfig.json
│ ├── rollup.config.js
│ └── src/
│ ├── index.ts
│ └── tu-componente.tsxPaso a Paso: Crear un Nuevo Componente
1. Crear la estructura del paquete
# Desde la raíz del proyecto
mkdir packages/mi-componente
cd packages/mi-componente2. Crear package.json
{
"name": "@cuenti-cn/mi-componente",
"version": "0.0.1",
"type": "module",
"description": "Mi Componente para Cuenti CN UI",
"main": "dist/index.js",
"module": "dist/index.esm.js",
"types": "dist/index.d.ts",
"files": ["dist"],
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.esm.js",
"require": "./dist/index.js"
}
},
"scripts": {
"build": "rollup -c",
"type-check": "tsc --noEmit"
},
"peerDependencies": {
"react": ">=18.0.0",
"react-dom": ">=18.0.0"
},
"dependencies": {
"@cuenti-cn/core": "workspace:*",
"@radix-ui/react-slot": "1.2.3",
"class-variance-authority": "0.7.1"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^28.0.1",
"@rollup/plugin-node-resolve": "^15.3.0",
"@rollup/plugin-typescript": "^12.1.1",
"@types/react": "19.1.13",
"@types/react-dom": "19.1.9",
"rollup": "^4.28.1",
"rollup-plugin-dts": "^6.1.1",
"tslib": "^2.6.0",
"typescript": "5.9.2"
},
"keywords": ["react", "mi-componente", "component", "ui", "tailwind"],
"author": "Cuenti",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/Cuenti/cuenti-cn-ui.git",
"directory": "packages/mi-componente"
}
}3. Crear tsconfig.json
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "dist",
"rootDir": "src",
"jsx": "react-jsx",
"module": "ESNext",
"moduleResolution": "bundler",
"skipLibCheck": true
},
"include": ["src/**/*"],
"exclude": ["**/*.test.*", "**/*.stories.*"]
}4. Crear rollup.config.js
import resolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import typescript from '@rollup/plugin-typescript'
import dts from 'rollup-plugin-dts'
const external = [
'react',
'react-dom',
'react/jsx-runtime',
'@radix-ui/react-slot',
'class-variance-authority',
'class-variance-authority/types',
'@cuenti-cn/core',
'tslib'
]
export default [
{
input: 'src/index.ts',
output: [
{
file: 'dist/index.js',
format: 'cjs',
sourcemap: true
},
{
file: 'dist/index.esm.js',
format: 'esm',
sourcemap: true
}
],
plugins: [
resolve({
preferBuiltins: false
}),
commonjs(),
typescript({
tsconfig: './tsconfig.json',
declaration: false,
importHelpers: true
})
],
external
},
{
input: 'src/index.ts',
output: {
file: 'dist/index.d.ts',
format: 'esm'
},
plugins: [dts()],
external
}
]5. Crear el componente
src/mi-componente.tsx:
import * as React from 'react'
import { Slot } from '@radix-ui/react-slot'
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@cuenti-cn/core'
const miComponenteVariants = cva(
'base-classes', // Clases base de Tailwind
{
variants: {
variant: {
default: 'default-variant-classes',
secondary: 'secondary-variant-classes'
},
size: {
default: 'default-size-classes',
sm: 'small-size-classes',
lg: 'large-size-classes'
}
},
defaultVariants: {
variant: 'default',
size: 'default'
}
}
)
export type MiComponenteProps = React.ComponentProps<'div'> &
VariantProps<typeof miComponenteVariants> & {
asChild?: boolean
}
function MiComponente({
className,
variant,
size,
asChild = false,
children,
...props
}: MiComponenteProps) {
const Comp = asChild ? Slot : 'div'
return (
<Comp className={cn(miComponenteVariants({ variant, size, className }))} {...props}>
{children}
</Comp>
)
}
export { MiComponente, miComponenteVariants }src/index.ts:
export { MiComponente, miComponenteVariants } from './mi-componente'
export type { MiComponenteProps } from './mi-componente'6. Crear Storybook (Opcional)
src/mi-componente.stories.tsx:
import type { Meta, StoryObj } from '@storybook/react'
import { MiComponente } from './mi-componente'
const meta: Meta<typeof MiComponente> = {
title: 'Components/MiComponente',
component: MiComponente,
parameters: {
layout: 'centered'
},
tags: ['autodocs'],
argTypes: {
variant: {
control: { type: 'select' },
options: ['default', 'secondary']
}
}
}
export default meta
type Story = StoryObj<typeof meta>
export const Default: Story = {
args: {
children: 'Mi Componente'
}
}
export const Secondary: Story = {
args: {
variant: 'secondary',
children: 'Mi Componente Secundario'
}
}7. Añadir al paquete principal
Actualiza src/index.ts en la raíz:
// Exports existentes...
export { MiComponente, miComponenteVariants } from '@cuenti-cn/mi-componente'
export type { MiComponenteProps } from '@cuenti-cn/mi-componente'Actualiza package.json principal para incluir el nuevo export:
{
"exports": {
// ... exports existentes
"./mi-componente": {
"types": "./packages/mi-componente/dist/index.d.ts",
"import": "./packages/mi-componente/dist/index.esm.js",
"require": "./packages/mi-componente/dist/index.js"
}
}
}8. Build y test
# Instalar dependencias
pnpm install
# Build del nuevo componente
cd packages/mi-componente
pnpm build
# Build completo
cd ../..
pnpm build
# Test en Storybook
pnpm storybookPublicar el Nuevo Componente
# Desde packages/mi-componente
npm publish --access public💡 Mejores Prácticas
Instalación Recomendada por Tipo de Proyecto
| Tipo de Proyecto | Recomendación | Razón |
| ------------------------------ | ----------------------------------------- | ----------------------------------------------------- |
| Proyecto pequeño/prototipo | npm install cuenti-cn-ui | Instalación rápida, todos los componentes disponibles |
| Aplicación en producción | Instalación individual por componente | Bundle más pequeño, mejor performance |
| Librería/paquete NPM | Instalación individual | Evita dependencias innecesarias |
| Aplicación empresarial | Instalación individual + alias de imports | Máximo control y optimización |
Optimización de Bundle
// ✅ Buena práctica - importación específica
import { Button } from '@cuenti-cn/button'
import { cn } from '@cuenti-cn/core'
// ❌ Evitar - importación completa innecesaria
import { Button } from 'cuenti-cn-ui' // Si solo necesitas ButtonAlias de Importación (Recomendado para proyectos grandes)
// tsconfig.json o vite.config.ts
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@ui/*": ["node_modules/@cuenti-cn/*/src"],
"@ui/core": ["node_modules/@cuenti-cn/core/src"]
}
}
}// Uso con alias
import { Button } from '@ui/button'
import { cn } from '@ui/core'🔧 Troubleshooting
Problema: Estilos no se aplican
Solución:
- Verifica que hayas importado los estilos:
@import '@cuenti-cn/core/styles'; - Asegúrate de que Tailwind CSS esté configurado en tu proyecto
- Ejecuta el script postinstall manualmente:
node node_modules/@cuenti-cn/core/scripts/postinstall.js
Problema: Tipos TypeScript no funcionan
Solución:
- Asegúrate de tener
@types/reactinstalado - Verifica que
moduleResolutionesté en"bundler"o"node" - Añade a tu
tsconfig.json:{ "compilerOptions": { "skipLibCheck": true } }
Problema: Build errors con "Cannot resolve module"
Solución:
- Instala
@cuenti-cn/coresi usas componentes individuales - Verifica que todas las peerDependencies estén instaladas:
npm install react react-dom @types/react @types/react-dom
Problema: Bundle muy grande
Solución:
- Usa instalación individual en lugar del paquete completo
- Implementa tree-shaking en tu bundler
- Verifica que uses importaciones específicas, no wildcard imports
🔄 Versionado y Actualizaciones
Estrategia de Versionado
Seguimos Semantic Versioning:
- Patch (0.0.x): Bug fixes y mejoras menores
- Minor (0.x.0): Nuevos componentes y features
- Major (x.0.0): Breaking changes
Actualizar Componentes
# Actualizar todos los paquetes de Cuenti CN UI
npm update cuenti-cn-ui @cuenti-cn/core @cuenti-cn/button
# Actualizar un componente específico
npm update @cuenti-cn/button
# Verificar versiones instaladas
npm list | grep cuenti-cnMigración entre Versiones Mayores
Consulta siempre el CHANGELOG.md para guías de migración detalladas entre versiones mayores.
📖 Documentación
- 📚 Storybook - Documentación interactiva de componentes
- 🔗 Repositorio GitHub
🤝 Contribuir
Las contribuciones son bienvenidas. Por favor:
- Haz fork del repositorio
- Crea una rama para tu feature (
git checkout -b feature/nueva-caracteristica) - Commit tus cambios (
git commit -am 'Añadir nueva característica') - Push a la rama (
git push origin feature/nueva-caracteristica) - Abre un Pull Request
📄 Licencia
MIT © Cuenti
🙏 Agradecimientos
- Radix UI - Primitivos accesibles
- Tailwind CSS - Framework de utilidades CSS
- class-variance-authority - Para gestión de variantes
- Storybook - Para documentación de componentes
