336 lines
8.0 KiB
Markdown
336 lines
8.0 KiB
Markdown
# Implementación de Avanza UI en Studio Panel
|
|
|
|
## 🚀 Pasos de Instalación
|
|
|
|
### 1. Instalar Avanza UI en studio-panel
|
|
|
|
```bash
|
|
cd packages/studio-panel
|
|
npm install ../ui-components
|
|
```
|
|
|
|
### 2. Actualizar package.json de studio-panel
|
|
|
|
```json
|
|
{
|
|
"dependencies": {
|
|
"avanza-ui": "file:../ui-components",
|
|
"react": "^18.3.1",
|
|
"react-dom": "^18.3.1"
|
|
}
|
|
}
|
|
```
|
|
|
|
### 3. Importar estilos globales en main.tsx
|
|
|
|
```tsx
|
|
// packages/studio-panel/src/main.tsx
|
|
import React from 'react';
|
|
import ReactDOM from 'react-dom/client';
|
|
import App from './App';
|
|
|
|
// Importar estilos de Avanza UI
|
|
import 'avanza-ui/dist/index.css';
|
|
|
|
// Tus estilos personalizados
|
|
import './styles.css';
|
|
|
|
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
<React.StrictMode>
|
|
<App />
|
|
</React.StrictMode>
|
|
);
|
|
```
|
|
|
|
### 4. Ejemplo de Uso en Componentes
|
|
|
|
#### Header.tsx con Avanza UI
|
|
|
|
```tsx
|
|
// packages/studio-panel/src/components/Header.tsx
|
|
import React from 'react';
|
|
import {
|
|
Avatar,
|
|
Button,
|
|
Dropdown,
|
|
DropdownItem,
|
|
DropdownDivider,
|
|
Tooltip,
|
|
} from 'avanza-ui';
|
|
|
|
export const Header: React.FC = () => {
|
|
return (
|
|
<header style={{
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'space-between',
|
|
padding: '1rem 2rem',
|
|
backgroundColor: 'var(--au-surface)',
|
|
borderBottom: '1px solid var(--au-border-light)',
|
|
}}>
|
|
<div>Logo</div>
|
|
|
|
<div style={{ display: 'flex', gap: '1rem', alignItems: 'center' }}>
|
|
<Tooltip content="Invitar participantes">
|
|
<Button variant="secondary" size="sm">
|
|
Invitar
|
|
</Button>
|
|
</Tooltip>
|
|
|
|
<Dropdown
|
|
trigger={
|
|
<Avatar
|
|
src="/avatar.jpg"
|
|
alt="Usuario"
|
|
size="sm"
|
|
status="online"
|
|
/>
|
|
}
|
|
align="right"
|
|
>
|
|
<DropdownItem icon={<span>👤</span>}>Mi Perfil</DropdownItem>
|
|
<DropdownItem icon={<span>⚙️</span>}>Configuración</DropdownItem>
|
|
<DropdownDivider />
|
|
<DropdownItem danger icon={<span>🚪</span>}>
|
|
Cerrar Sesión
|
|
</DropdownItem>
|
|
</Dropdown>
|
|
</div>
|
|
</header>
|
|
);
|
|
};
|
|
```
|
|
|
|
#### Sidebar.tsx con Avanza UI
|
|
|
|
```tsx
|
|
// packages/studio-panel/src/components/Sidebar.tsx
|
|
import React from 'react';
|
|
import { Card, CardHeader, CardBody, Badge, Tooltip } from 'avanza-ui';
|
|
|
|
export const Sidebar: React.FC = () => {
|
|
return (
|
|
<aside style={{
|
|
width: '300px',
|
|
backgroundColor: 'var(--au-surface)',
|
|
borderRight: '1px solid var(--au-border-light)',
|
|
padding: '1rem',
|
|
}}>
|
|
<Card>
|
|
<CardHeader>
|
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
|
<h3>Participantes</h3>
|
|
<Badge variant="primary">3</Badge>
|
|
</div>
|
|
</CardHeader>
|
|
<CardBody>
|
|
{/* Lista de participantes */}
|
|
</CardBody>
|
|
</Card>
|
|
|
|
<Card style={{ marginTop: '1rem' }}>
|
|
<CardHeader>
|
|
<h3>Chat</h3>
|
|
</CardHeader>
|
|
<CardBody>
|
|
{/* Mensajes de chat */}
|
|
</CardBody>
|
|
</Card>
|
|
</aside>
|
|
);
|
|
};
|
|
```
|
|
|
|
#### StudioLayout.tsx con Avanza UI
|
|
|
|
```tsx
|
|
// packages/studio-panel/src/components/StudioLayout.tsx
|
|
import React, { useState } from 'react';
|
|
import {
|
|
Button,
|
|
Modal,
|
|
ModalHeader,
|
|
ModalBody,
|
|
ModalFooter,
|
|
Input,
|
|
Alert,
|
|
Spinner,
|
|
} from 'avanza-ui';
|
|
import { Header } from './Header';
|
|
import { Sidebar } from './Sidebar';
|
|
|
|
export const StudioLayout: React.FC = () => {
|
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
|
|
return (
|
|
<div style={{ height: '100vh', display: 'flex', flexDirection: 'column' }}>
|
|
<Header />
|
|
|
|
<div style={{ flex: 1, display: 'flex', overflow: 'hidden' }}>
|
|
<Sidebar />
|
|
|
|
<main style={{ flex: 1, padding: '2rem', overflowY: 'auto' }}>
|
|
<Alert
|
|
variant="info"
|
|
title="Bienvenido al Studio"
|
|
message="Configura tu transmisión en vivo"
|
|
closable
|
|
/>
|
|
|
|
<div style={{ marginTop: '2rem' }}>
|
|
<Button
|
|
variant="primary"
|
|
onClick={() => setIsModalOpen(true)}
|
|
leftIcon={<span>▶</span>}
|
|
>
|
|
Iniciar Transmisión
|
|
</Button>
|
|
</div>
|
|
|
|
{isLoading && (
|
|
<div style={{ marginTop: '2rem', textAlign: 'center' }}>
|
|
<Spinner size="lg" variant="primary" />
|
|
<p>Conectando...</p>
|
|
</div>
|
|
)}
|
|
</main>
|
|
</div>
|
|
|
|
{/* Modal de Configuración */}
|
|
<Modal
|
|
isOpen={isModalOpen}
|
|
onClose={() => setIsModalOpen(false)}
|
|
size="md"
|
|
>
|
|
<ModalHeader
|
|
title="Configurar Transmisión"
|
|
onClose={() => setIsModalOpen(false)}
|
|
/>
|
|
<ModalBody>
|
|
<Input
|
|
label="Título de la transmisión"
|
|
placeholder="Ingresa un título"
|
|
fullWidth
|
|
/>
|
|
<Input
|
|
label="Descripción"
|
|
placeholder="Descripción opcional"
|
|
fullWidth
|
|
style={{ marginTop: '1rem' }}
|
|
/>
|
|
</ModalBody>
|
|
<ModalFooter>
|
|
<Button variant="secondary" onClick={() => setIsModalOpen(false)}>
|
|
Cancelar
|
|
</Button>
|
|
<Button variant="primary">Comenzar</Button>
|
|
</ModalFooter>
|
|
</Modal>
|
|
</div>
|
|
);
|
|
};
|
|
```
|
|
|
|
## 🎨 Personalización del Tema
|
|
|
|
### Archivo de estilos personalizado (styles.css)
|
|
|
|
```css
|
|
/* packages/studio-panel/src/styles.css */
|
|
|
|
/* Personalizar colores primarios */
|
|
:root {
|
|
--au-primary-600: #6366f1; /* Tu color primario */
|
|
--au-primary-700: #4f46e5;
|
|
}
|
|
|
|
/* Dark theme personalizado */
|
|
[data-theme="dark"] {
|
|
--au-bg-primary: #0a0e1a;
|
|
--au-surface: #13192b;
|
|
}
|
|
|
|
/* Estilos adicionales específicos del studio */
|
|
.studio-video-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
gap: var(--au-spacing-4);
|
|
padding: var(--au-spacing-4);
|
|
}
|
|
```
|
|
|
|
### Toggle de Tema
|
|
|
|
```tsx
|
|
// packages/studio-panel/src/components/ThemeToggle.tsx
|
|
import React, { useState, useEffect } from 'react';
|
|
import { Button } from 'avanza-ui';
|
|
|
|
export const ThemeToggle: React.FC = () => {
|
|
const [theme, setTheme] = useState<'light' | 'dark'>('light');
|
|
|
|
useEffect(() => {
|
|
// Leer tema del localStorage
|
|
const savedTheme = localStorage.getItem('theme') as 'light' | 'dark' | null;
|
|
if (savedTheme) {
|
|
setTheme(savedTheme);
|
|
document.documentElement.setAttribute('data-theme', savedTheme);
|
|
}
|
|
}, []);
|
|
|
|
const toggleTheme = () => {
|
|
const newTheme = theme === 'light' ? 'dark' : 'light';
|
|
setTheme(newTheme);
|
|
document.documentElement.setAttribute('data-theme', newTheme);
|
|
localStorage.setItem('theme', newTheme);
|
|
};
|
|
|
|
return (
|
|
<Button variant="ghost" onClick={toggleTheme}>
|
|
{theme === 'light' ? '🌙' : '☀️'}
|
|
</Button>
|
|
);
|
|
};
|
|
```
|
|
|
|
## 📋 Checklist de Migración
|
|
|
|
- [ ] Instalar avanza-ui en package.json
|
|
- [ ] Importar estilos globales en main.tsx
|
|
- [ ] Reemplazar componentes existentes con Avanza UI
|
|
- [ ] Configurar tema dark/light
|
|
- [ ] Personalizar variables CSS si es necesario
|
|
- [ ] Probar en diferentes navegadores
|
|
- [ ] Verificar accesibilidad
|
|
|
|
## 🔄 Comparación con Vristo
|
|
|
|
| Vristo | Avanza UI | Beneficio |
|
|
|--------|-----------|-----------|
|
|
| Depende de Tailwind | CSS Modules | Sin conflictos de clases |
|
|
| require('react-popper') | Estado interno | Menos dependencias |
|
|
| Configuración compleja | Plug & Play | Más rápido de implementar |
|
|
| Múltiples estilos | Variables CSS | Personalización fácil |
|
|
|
|
## 🚀 Comandos Útiles
|
|
|
|
```bash
|
|
# Desarrollo
|
|
cd packages/ui-components && npm run dev
|
|
cd packages/studio-panel && npm run dev
|
|
|
|
# Build de producción
|
|
cd packages/ui-components && npm run build
|
|
cd packages/studio-panel && npm run build
|
|
|
|
# Actualizar biblioteca
|
|
cd packages/ui-components && npm run build
|
|
cd packages/studio-panel && npm install ../ui-components
|
|
```
|
|
|
|
---
|
|
|
|
¡Listo para usar Avanza UI en tu Studio Panel!
|
|
|