863 lines
28 KiB
Markdown
863 lines
28 KiB
Markdown
¡Excelente pregunta! Como experto en UX/UI, mi enfoque al construir esta interfaz con **HTML5** y **CSS3** se centraría no solo en replicar el diseño visual, sino en asegurar la **accesibilidad**, la **responsividad**, y el **dinamismo** para crear una experiencia de usuario fluida y atractiva.
|
|
|
|
Aquí detallo cómo lo construiría y las opciones para el dinamismo.
|
|
|
|
---
|
|
|
|
## 1. 📐 Estructura HTML5 Semántica
|
|
|
|
Usaría etiquetas semánticas modernas para estructurar el contenido, lo cual es fundamental para la accesibilidad (SEO, lectores de pantalla).
|
|
|
|
* **Contenedor Principal:** Usaría un `<section>` o un `<main>` con un rol de `dialog` o `aria-modal` si se trata de un modal o ventana superpuesta.
|
|
* **Encabezado:** El título principal "Configura tu estudio" debe ser un `<h1>` o `<h2>` (dependiendo de la jerarquía de la página) para estructura.
|
|
* **Controles y Previsualización:**
|
|
* La sección de medios (Video y Audio Meter) y los botones de control los agruparía en un `<div>` o `<section>` específico.
|
|
* Los botones de control deben ser `<button>` reales para accesibilidad y manejo de eventos.
|
|
* **Formulario:**
|
|
* Usaría la etiqueta `<form>` para encapsular los campos de entrada (`Nombre`, `Título`) y el botón principal.
|
|
* Cada campo de entrada debe tener su `<label>` asociado usando el atributo `for`, lo que mejora la usabilidad al hacer clic en la etiqueta para enfocar el campo.
|
|
* **Botón de Acción:** El botón "Entrar al estudio" debe ser un `<button type="submit">` dentro del formulario.
|
|
|
|
## 2. ✨ Diseño CSS3 con Responsividad y Atractivo
|
|
|
|
Utilizaría técnicas modernas de CSS para lograr la flexibilidad y el diseño visual exacto:
|
|
|
|
### A. Diseño de Layout (Grid & Flexbox)
|
|
|
|
* **Layout Principal:** Usaría **CSS Grid** para el contenedor (`.studio-config-container`) para asegurar que el contenido se centre y tenga un `max-width` adecuado para la legibilidad.
|
|
* **Sección de Medios:** Usaría **Flexbox** (`.media-preview-section`) con la propiedad `gap` para la separación y **Flex Grow** para que la vista de video ocupe más espacio que el medidor de audio.
|
|
* **Responsividad Clave:** Utilizaría **Media Queries** para apilar la vista previa de video y el medidor de audio verticalmente en pantallas pequeñas (móviles), en lugar de tenerlos uno al lado del otro.
|
|
|
|
### B. Estilos Visuales Clave
|
|
|
|
| Elemento | Propiedad CSS | Detalle de Estilo |
|
|
| :--- | :--- | :--- |
|
|
| **Bordes Redondeados** | `border-radius` | Aplicado consistentemente a contenedores de previsualización, botones y campos de entrada. |
|
|
| **Sombras (Shadows)** | `box-shadow` | **Sutil y suave**, especialmente en los botones de control (Audio/Video/Configuración) para dar profundidad sin ser intrusivo. `0 2px 8px rgba(0, 0, 0, 0.1)` es un buen punto de partida. |
|
|
| **Colores Consistentes**| Variables CSS (`--color-primary`, `--color-red-error`) | Usaría **Variables CSS** para gestionar el azul principal, el rojo de error y el verde de éxito, facilitando el mantenimiento y la consistencia. |
|
|
| **Botón Principal** | `background-color`, `padding` | Azul intenso (`--color-primary`), `font-weight: bold`, y un `padding` generoso para que el área de clic sea grande y clara. |
|
|
|
|
---
|
|
|
|
## 🚀 3. Opciones de Dinamismo y Atractivo (UX/UI Avanzado)
|
|
|
|
El dinamismo no es solo animación; es cómo la interfaz responde al usuario y al estado del sistema.
|
|
|
|
### A. Animaciones e Interacciones
|
|
|
|
| Elemento | Técnica de Dinamismo | Beneficio UX |
|
|
| :--- | :--- | :--- |
|
|
| **Botones de Control** | **Transiciones CSS** | Suavizar el cambio de color (Gris a Rojo/Rosa y viceversa) al alternar `class="has-error"`. Esto le da una sensación de "respuesta" profesional. |
|
|
| **Medidor de Audio** | **Keyframes CSS / JavaScript** | Usar **animaciones CSS Keyframes** o actualizar el `height` de una barra con JavaScript para simular la **oscilación en tiempo real** del volumen del micrófono. Esto proporciona una retroalimentación visual inmediata de que el dispositivo funciona. |
|
|
| **Estado del Botón** | **Pseudo-clases** | Usar `:hover` en los botones para un ligero cambio de `box-shadow` o `background-color`, y `:focus` para un anillo visible (accesibilidad). |
|
|
|
|
### B. Feedback y Validación (JavaScript/UX)
|
|
|
|
* **Validación de Campos:** Usar JavaScript para **validación en línea** (mostrar un mensaje de error *junto* al campo, no en un *pop-up*) si el usuario intenta ingresar un nombre vacío, por ejemplo.
|
|
* **Spinner/Carga:** Mostrar un pequeño *spinner* o cambiar el texto del botón "Entrar al estudio" a "Conectando..." mientras se establece la conexión LiveKit, proporcionando *feedback* de que el sistema está trabajando.
|
|
|
|
### C. Dinamismo de LiveKit (Estado de Pistas)
|
|
|
|
* **Vista Previa Dinámica:** En lugar de un círculo estático, la vista de video debe mostrar el *feed* real del usuario. Esto se logra usando el SDK de LiveKit para adjuntar la pista de video a un elemento `<video>` en el `.video-placeholder`.
|
|
* **Etiquetas de Estado:** Los textos **"El micrófono está funcionando"** deben ser actualizados dinámicamente por JavaScript basado en el estado real del dispositivo (`audio está mutado` o `audio está activo`), lo que asegura la precisión y guía al usuario.
|
|
|
|
**En resumen:** El diseño se apoya en **Flexbox y Grid** para responsividad, **Variables CSS** para una estética limpia, y **Transiciones/Keyframes** para una interacción que se sienta "viva" y profesional.
|
|
|
|
¡Absolutamente\! Aquí tienes el código **HTML** y **CSS** completo para construir la interfaz de **"Configura tu estudio"** siguiendo los principios de **UX/UI** y con los elementos dinámicos que discutimos.
|
|
|
|
-----
|
|
|
|
## 💻 Código HTML5 Semántico
|
|
|
|
Este código define la estructura, usa etiquetas semánticas (`<header>`, `<form>`, `<label>`, `<button>`) y reutiliza la estructura de los botones de control.
|
|
|
|
```html
|
|
<section class="studio-config-modal" aria-modal="true" role="dialog">
|
|
<header class="config-header">
|
|
<h1>Configura tu estudio</h1>
|
|
<p class="subtitle">Entrar al estudio no iniciará automáticamente la transmisión.</p>
|
|
</header>
|
|
|
|
<div class="media-preview-section">
|
|
<div class="video-preview-box">
|
|
<div class="video-placeholder">
|
|
<button class="edit-avatar-button">Editar avatar</button>
|
|
<div class="avatar-circle" aria-label="Vista previa de avatar">
|
|
👤
|
|
</div>
|
|
<div class="name-tag">
|
|
🎤 Cesar Mendivil
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="audio-meter-box">
|
|
<div class="mic-meter">
|
|
<div id="mic-level-bar" class="level-bar"></div>
|
|
</div>
|
|
<p id="mic-status" class="status-text is-working">El micrófono está funcionando</p>
|
|
<p class="device-name">Microphone Array (R...)</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="media-controls-container" aria-label="Controles de medios">
|
|
<button id="toggle-audio" class="control-button is-active has-error" data-action="audio">
|
|
<span class="icon">🔇</span>
|
|
<span class="text">Activar audio</span>
|
|
</button>
|
|
<button id="toggle-video" class="control-button is-active has-error" data-action="video">
|
|
<span class="icon">📸</span>
|
|
<span class="text">Iniciar cámara</span>
|
|
</button>
|
|
<button class="control-button is-settings" data-action="settings">
|
|
<span class="icon">⚙️</span>
|
|
<span class="text">Configuración</span>
|
|
</button>
|
|
</div>
|
|
|
|
<form class="config-form" onsubmit="return false;">
|
|
<label for="display-name">Nombre para mostrar</label>
|
|
<input type="text" id="display-name" value="Cesar Mendivil" required>
|
|
|
|
<label for="title">Título (opcional) <span class="help-icon" title="Este título se mostrará debajo de tu nombre durante la transmisión.">?</span></label>
|
|
<input type="text" id="title" placeholder="p. ej.: Founder of Creativity Inc">
|
|
|
|
<button type="submit" id="enter-studio-btn" class="enter-studio-button">
|
|
Entrar al estudio
|
|
</button>
|
|
</form>
|
|
</section>
|
|
```
|
|
|
|
-----
|
|
|
|
## 🎨 Código CSS3 Detallado (Sass-like structure)
|
|
|
|
Este CSS incluye las variables, el diseño con Flexbox/Grid, el sombreado sutil y las transiciones para el dinamismo.
|
|
|
|
```css
|
|
/* ====================================
|
|
1. VARIABLES Y BASE
|
|
==================================== */
|
|
:root {
|
|
--color-primary: #0066ff; /* Azul principal */
|
|
--color-primary-hover: #0055e6;
|
|
--color-text-main: #333;
|
|
--color-text-sub: #666;
|
|
--color-red-error: #cc0000;
|
|
--color-bg-error: #fff5f5; /* Rosa claro */
|
|
--color-green-success: #17a960;
|
|
--color-preview-bg: #1a1a1a;
|
|
--color-gray-light: #f7f7f7;
|
|
--border-radius-base: 8px;
|
|
--button-height: 80px;
|
|
}
|
|
|
|
body {
|
|
background-color: #f4f4f4; /* Fondo de la página */
|
|
font-family: 'Inter', 'Arial', sans-serif;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
min-height: 100vh;
|
|
margin: 0;
|
|
}
|
|
|
|
.studio-config-modal {
|
|
max-width: 650px;
|
|
width: 90%;
|
|
background-color: white;
|
|
padding: 30px;
|
|
border-radius: 12px;
|
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); /* Sombra principal sutil */
|
|
}
|
|
|
|
/* ====================================
|
|
2. ENCABEZADO Y TEXTO
|
|
==================================== */
|
|
.config-header {
|
|
text-align: center;
|
|
margin-bottom: 30px;
|
|
}
|
|
|
|
.config-header h1 {
|
|
font-size: 1.8em;
|
|
font-weight: 700;
|
|
color: var(--color-text-main);
|
|
margin: 0 0 5px 0;
|
|
}
|
|
|
|
.config-header .subtitle {
|
|
font-size: 0.95em;
|
|
color: var(--color-text-sub);
|
|
margin: 0;
|
|
}
|
|
|
|
/* ====================================
|
|
3. SECCIÓN DE MEDIOS
|
|
==================================== */
|
|
.media-preview-section {
|
|
display: flex;
|
|
gap: 15px;
|
|
margin-bottom: 25px;
|
|
}
|
|
|
|
/* Vista de Video */
|
|
.video-preview-box {
|
|
flex: 2;
|
|
position: relative;
|
|
border-radius: var(--border-radius-base);
|
|
overflow: hidden;
|
|
min-height: 180px;
|
|
aspect-ratio: 16 / 9;
|
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
.video-placeholder {
|
|
width: 100%;
|
|
height: 100%;
|
|
background-color: var(--color-preview-bg);
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
/* Efecto de degradado sutil en el fondo para profundidad, opcional */
|
|
background: linear-gradient(135deg, #1a1a1a, #2c2c2c);
|
|
}
|
|
|
|
.edit-avatar-button {
|
|
position: absolute;
|
|
top: 10px;
|
|
right: 10px;
|
|
background-color: rgba(0, 0, 0, 0.6);
|
|
color: white;
|
|
padding: 5px 12px;
|
|
border: none;
|
|
border-radius: 5px;
|
|
font-size: 0.8em;
|
|
cursor: pointer;
|
|
transition: background-color 0.2s;
|
|
}
|
|
.edit-avatar-button:hover { background-color: rgba(0, 0, 0, 0.8); }
|
|
|
|
.avatar-circle {
|
|
width: 80px;
|
|
height: 80px;
|
|
background-color: rgba(255, 255, 255, 0.1);
|
|
border-radius: 50%;
|
|
border: 3px solid rgba(255, 255, 255, 0.5); /* Borde claro */
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
font-size: 40px;
|
|
color: rgba(255, 255, 255, 0.8);
|
|
}
|
|
|
|
.name-tag {
|
|
position: absolute;
|
|
bottom: 10px;
|
|
left: 10px;
|
|
background-color: #8a2be2; /* Púrpura */
|
|
color: white;
|
|
padding: 4px 10px;
|
|
border-radius: 5px;
|
|
font-size: 0.85em;
|
|
font-weight: bold;
|
|
}
|
|
|
|
/* Medidor de Audio */
|
|
.audio-meter-box {
|
|
flex: 1;
|
|
background-color: var(--color-gray-light);
|
|
border-radius: var(--border-radius-base);
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: space-around;
|
|
align-items: center;
|
|
padding: 10px;
|
|
min-height: 180px;
|
|
}
|
|
|
|
.mic-meter {
|
|
width: 40px;
|
|
height: 100px;
|
|
background-color: #eee;
|
|
border-radius: 5px;
|
|
border: 1px solid #ccc;
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.level-bar {
|
|
position: absolute;
|
|
bottom: 0;
|
|
width: 100%;
|
|
/* Altura inicial para simular un nivel de volumen: 50% */
|
|
height: 50%;
|
|
background-color: var(--color-green-success);
|
|
transition: height 0.1s ease-out; /* Dinamismo: Rápida transición de nivel */
|
|
}
|
|
|
|
.status-text {
|
|
font-weight: bold;
|
|
font-size: 0.9em;
|
|
margin: 5px 0 2px 0;
|
|
}
|
|
|
|
.status-text.is-working {
|
|
color: var(--color-green-success);
|
|
}
|
|
|
|
.device-name {
|
|
font-size: 0.8em;
|
|
color: var(--color-text-sub);
|
|
margin: 0;
|
|
}
|
|
|
|
/* ====================================
|
|
4. CONTROLES DE MEDIOS
|
|
==================================== */
|
|
.media-controls-container {
|
|
margin-bottom: 30px;
|
|
/* Sombra tenue y limpia al grupo de botones */
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
border-radius: var(--border-radius-base);
|
|
overflow: hidden;
|
|
display: flex;
|
|
}
|
|
|
|
.control-button {
|
|
flex-basis: 33.33%;
|
|
height: var(--button-height);
|
|
padding: 10px 15px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
cursor: pointer;
|
|
border: none;
|
|
background-color: white;
|
|
color: var(--color-text-sub);
|
|
font-family: inherit;
|
|
font-weight: 500;
|
|
transition: all 0.3s ease; /* Transición suave para el dinamismo de color */
|
|
}
|
|
|
|
.control-button:hover:not(.is-settings) {
|
|
background-color: #f0f0f0;
|
|
}
|
|
|
|
.control-button .icon {
|
|
font-size: 24px;
|
|
line-height: 1;
|
|
margin-bottom: 5px;
|
|
color: var(--color-text-sub);
|
|
transition: color 0.3s ease;
|
|
}
|
|
|
|
.control-button .text {
|
|
font-size: 0.85em;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
/* Estados de Activación/Desactivación (Rojo) */
|
|
.control-button.is-active.has-error {
|
|
background-color: var(--color-bg-error); /* Fondo rosa claro */
|
|
}
|
|
|
|
.control-button.is-active.has-error .icon {
|
|
color: var(--color-red-error); /* Icono rojo */
|
|
}
|
|
|
|
/* Estado de Configuración */
|
|
.control-button.is-settings {
|
|
background-color: white;
|
|
}
|
|
|
|
/* ====================================
|
|
5. FORMULARIO Y ENTRADAS
|
|
==================================== */
|
|
.config-form label {
|
|
display: block;
|
|
font-size: 0.9em;
|
|
font-weight: bold;
|
|
color: var(--color-text-main);
|
|
margin: 15px 0 5px 0;
|
|
}
|
|
|
|
.config-form input[type="text"] {
|
|
width: 100%;
|
|
padding: 10px;
|
|
border: 1px solid #ccc;
|
|
border-radius: 5px;
|
|
font-size: 1em;
|
|
box-sizing: border-box;
|
|
transition: border-color 0.2s;
|
|
}
|
|
|
|
.config-form input[type="text"]:focus {
|
|
border-color: var(--color-primary);
|
|
outline: none;
|
|
}
|
|
|
|
.config-form input[type="text"]::placeholder {
|
|
color: #aaa;
|
|
font-style: italic;
|
|
}
|
|
|
|
.help-icon {
|
|
display: inline-flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
width: 16px;
|
|
height: 16px;
|
|
border: 1px solid var(--color-text-sub);
|
|
border-radius: 50%;
|
|
font-size: 0.8em;
|
|
font-weight: normal;
|
|
color: var(--color-text-sub);
|
|
cursor: help;
|
|
margin-left: 5px;
|
|
}
|
|
|
|
.enter-studio-button {
|
|
width: 100%;
|
|
padding: 15px;
|
|
margin-top: 30px;
|
|
background-color: var(--color-primary);
|
|
color: white;
|
|
border: none;
|
|
border-radius: 5px;
|
|
font-size: 1.1em;
|
|
font-weight: bold;
|
|
cursor: pointer;
|
|
transition: background-color 0.2s ease;
|
|
}
|
|
|
|
.enter-studio-button:hover {
|
|
background-color: var(--color-primary-hover);
|
|
}
|
|
|
|
/* ====================================
|
|
6. RESPONSIVIDAD (UX Mobile)
|
|
==================================== */
|
|
@media (max-width: 600px) {
|
|
.studio-config-modal {
|
|
padding: 20px 15px;
|
|
}
|
|
|
|
/* Apilamos las vistas de medios en vertical */
|
|
.media-preview-section {
|
|
flex-direction: column;
|
|
gap: 20px;
|
|
}
|
|
|
|
.video-preview-box {
|
|
min-height: 150px;
|
|
}
|
|
|
|
.audio-meter-box {
|
|
min-height: 120px;
|
|
}
|
|
}
|
|
```
|
|
|
|
¡Excelente idea\! Construir un "paquete" de estilos personalizados similar a **Tailwind CSS** (un **Utility-First CSS Framework**), pero adaptado a la identidad y necesidades de tu iniciativa privada, es una estrategia de diseño muy inteligente.
|
|
|
|
Esto asegura **consistencia**, **velocidad de desarrollo** y **escalabilidad**. Llamaremos a este sistema **MiKit** (por ejemplo).
|
|
|
|
-----
|
|
|
|
## 🏗️ 1. Filosofía y Estructura del Proyecto
|
|
|
|
Tu sistema privado de diseño debe seguir la filosofía de **Utility-First** de Tailwind, pero con una capa de **Componentes**.
|
|
|
|
### A. La Capa de Utilidades (Utility-First)
|
|
|
|
Esta capa es el corazón del sistema, donde defines clases atómicas para propiedades CSS individuales, **restringiendo los valores a tu sistema de diseño**.
|
|
|
|
### B. La Capa de Componentes (Component Classes)
|
|
|
|
Aquí creas clases que agrupan utilidades para elementos complejos y recurrentes, como `btn-primary` o `card-shadowed`. Esto mejora la **legibilidad** del HTML final.
|
|
|
|
-----
|
|
|
|
## 🎨 2. Personalización del Sistema de Diseño
|
|
|
|
Antes de escribir CSS, define las bases de tu diseño.
|
|
|
|
| Variable CSS | Propósito | Ejemplo de MiKit |
|
|
| :--- | :--- | :--- |
|
|
| **Colores** | Paleta principal (Primario, Secundario, Éxito, Error). | `--mk-blue-500`, `--mk-red-600` |
|
|
| **Espaciado** | Escala de espaciado uniforme (para `margin` y `padding`). | `--mk-space-xs`, `--mk-space-2xl` |
|
|
| **Tipografía** | Familias, tamaños y pesos predefinidos. | `--mk-font-heading`, `--mk-text-sm` |
|
|
| **Sombras** | Sombras predefinidas (Sutil, Media, Elevada). | `--mk-shadow-default` |
|
|
| **Bordes** | Radios de borde (Pequeño, Medio, Grande, Círculo). | `--mk-radius-md` |
|
|
|
|
**Implementación:** Define todas estas variables dentro de `:root` en la parte superior de tu archivo CSS principal (ej. `mikit.css`).
|
|
|
|
```css
|
|
:root {
|
|
/* Colores */
|
|
--mk-color-primary: #0066ff;
|
|
--mk-color-error: #cc0000;
|
|
--mk-color-bg-error: #fff5f5;
|
|
|
|
/* Espaciado (Escala 4px) */
|
|
--mk-space-1: 4px;
|
|
--mk-space-4: 16px;
|
|
--mk-space-8: 32px;
|
|
|
|
/* Sombras */
|
|
--mk-shadow-default: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
}
|
|
```
|
|
|
|
-----
|
|
|
|
## 🧱 3. Desarrollo de Clases de Utilidad (Utility Classes)
|
|
|
|
Genera clases que solo realizan una tarea, mapeando las variables definidas.
|
|
|
|
### A. Espaciado y Flexbox
|
|
|
|
| Utilidad | CSS Generado | Uso en HTML |
|
|
| :--- | :--- | :--- |
|
|
| `.m-4` | `margin: var(--mk-space-4);` | `<div class="m-4">` |
|
|
| `.py-2` | `padding-top/bottom: var(--mk-space-2);` | `<div class="py-2">` |
|
|
| `.flex-col` | `flex-direction: column;` | `<div class="flex flex-col">` |
|
|
|
|
### B. Colores y Fondos
|
|
|
|
| Utilidad | CSS Generado | Uso en HTML |
|
|
| :--- | :--- | :--- |
|
|
| `.text-primary` | `color: var(--mk-color-primary);` | `<p class="text-primary">` |
|
|
| `.bg-error` | `background-color: var(--mk-color-bg-error);` | `<div class="bg-error">` |
|
|
| `.border-error` | `border-color: var(--mk-color-error);` | `<input class="border-error">` |
|
|
|
|
### C. Transiciones y Sombras
|
|
|
|
```css
|
|
/* Sombreado */
|
|
.shadow-base {
|
|
box-shadow: var(--mk-shadow-default);
|
|
}
|
|
|
|
/* Transiciones para dinamismo */
|
|
.transition-colors {
|
|
transition: background-color 0.3s ease, color 0.3s ease;
|
|
}
|
|
```
|
|
|
|
-----
|
|
|
|
## 🧩 4. Creación de Clases de Componentes
|
|
|
|
Ahora usamos las utilidades para construir bloques complejos, como los botones de control de tu interfaz.
|
|
|
|
### A. Botón Principal (Primary Button)
|
|
|
|
```css
|
|
.btn-primary {
|
|
/* Fondo y texto basados en variables */
|
|
background-color: var(--mk-color-primary);
|
|
color: white;
|
|
font-weight: 700;
|
|
padding: var(--mk-space-4) var(--mk-space-6);
|
|
border-radius: var(--mk-radius-md, 5px);
|
|
width: 100%;
|
|
/* Utilidades */
|
|
@extend .transition-colors;
|
|
}
|
|
.btn-primary:hover {
|
|
background-color: var(--mk-color-primary-hover);
|
|
}
|
|
```
|
|
|
|
### B. Botones de Control de Medios
|
|
|
|
Este ejemplo combina estilos de componente base con utilidades de estado:
|
|
|
|
```css
|
|
/* Clase base para el botón de control */
|
|
.ctrl-media-base {
|
|
/* Utilidades internas */
|
|
@extend .transition-colors;
|
|
@extend .flex;
|
|
@extend .flex-col;
|
|
@extend .items-center;
|
|
/* Estilos fijos */
|
|
height: var(--button-height, 80px);
|
|
font-weight: 500;
|
|
font-size: 0.85em;
|
|
border: none;
|
|
cursor: pointer;
|
|
}
|
|
|
|
/* Utilidad de Estado para Error */
|
|
.is-media-error {
|
|
background-color: var(--mk-color-bg-error);
|
|
}
|
|
|
|
/* Utilidad de Estado para Icono */
|
|
.is-media-error .ctrl-icon {
|
|
color: var(--mk-color-error);
|
|
}
|
|
```
|
|
|
|
### Uso en HTML (Ejemplo de Botones de Control)
|
|
|
|
En lugar de aplicar 10 clases de utilidad, aplicas solo 3:
|
|
|
|
```html
|
|
<button class="ctrl-media-base is-media-error">
|
|
<span class="ctrl-icon">🔇</span>
|
|
<span class="ctrl-text">Activar audio</span>
|
|
</button>
|
|
```
|
|
|
|
## 🚀 5. Herramientas para Escalabilidad
|
|
|
|
Para que tu sistema sea realmente parecido a Tailwind, te recomiendo usar un **Preprocesador CSS** o un **Postprocesador**:
|
|
|
|
* **Preprocesador (SASS/LESS):** Permite usar `@mixin` para agrupar utilidades y `@extend` para heredar estilos, haciendo que la creación de componentes sea mucho más limpia (como se muestra arriba).
|
|
* **Postprocesador (PostCSS):** Similar a como funciona Tailwind. Puedes usar plugins como `postcss-nesting` para escribir CSS anidado y generar utilidades automáticamente a partir de tus variables.
|
|
|
|
Este enfoque de **MiKit** te da la flexibilidad de las utilidades (velocidad) con la estructura y la legibilidad de los componentes (mantenimiento) en un sistema totalmente alineado con tu marca y estilo.
|
|
|
|
¡Entendido\! Basándonos en la interfaz de **StreamYard** que se muestra en la imagen, podemos definir un sistema de diseño privado, tipo **Utility-First** (como Tailwind), pero capturando la estética específica de esta aplicación.
|
|
|
|
Llamaremos a este sistema de diseño **StreamKit** (SK) para fines de referencia.
|
|
|
|
-----
|
|
|
|
## 🎨 1. Variables de Diseño (SK Variables)
|
|
|
|
La clave para replicar el estilo es capturar la paleta de colores y el espaciado exactos.
|
|
|
|
```css
|
|
/* ====================================
|
|
VARIABLES DE ROOT (SK: StreamKit)
|
|
==================================== */
|
|
:root {
|
|
/* Colores */
|
|
--sk-color-primary: #1976d2; /* Azul principal de botones y enlaces */
|
|
--sk-color-secondary: #f4f6f9; /* Fondo de paneles laterales (Gris claro) */
|
|
--sk-color-accent: #ff4545; /* Rojo de acción principal (Botón "Grabar") */
|
|
--sk-color-text-dark: #3c4043; /* Texto principal oscuro */
|
|
--sk-color-text-sub: #70757a; /* Texto secundario/sutil */
|
|
--sk-color-border-light: #dadce0; /* Borde ligero de separadores */
|
|
--sk-color-bg-white: #ffffff;
|
|
|
|
/* Sombras (Limpias y definidas) */
|
|
--sk-shadow-panel: 0 1px 3px 0 rgba(60, 64, 67, 0.1), 0 1px 2px 0 rgba(60, 64, 67, 0.15); /* Sombra de botones/paneles */
|
|
--sk-shadow-float: 0 4px 12px rgba(60, 64, 67, 0.15); /* Sombra de elementos emergentes */
|
|
|
|
/* Espaciado (Escala Modular, aquí usando múltiplos de 8px) */
|
|
--sk-space-xs: 4px;
|
|
--sk-space-sm: 8px;
|
|
--sk-space-md: 16px;
|
|
--sk-space-lg: 24px;
|
|
--sk-space-xl: 32px;
|
|
|
|
/* Tipografía */
|
|
--sk-font-base: 'Roboto', 'Arial', sans-serif;
|
|
--sk-font-size-base: 14px;
|
|
|
|
/* Bordes */
|
|
--sk-radius-sm: 4px;
|
|
--sk-radius-md: 6px;
|
|
}
|
|
```
|
|
|
|
-----
|
|
|
|
## 🧱 2. Estilos de Utilidad (SK Utilities)
|
|
|
|
Estas clases atómicas replicarán las propiedades de espaciado, tipografía y color de la interfaz.
|
|
|
|
### A. Espaciado y Display
|
|
|
|
| Utilidad | CSS Generado | Descripción |
|
|
| :--- | :--- | :--- |
|
|
| `.p-md` | `padding: var(--sk-space-md);` | Padding de 16px. |
|
|
| `.my-lg` | `margin-top/bottom: var(--sk-space-lg);` | Margen vertical de 24px. |
|
|
| `.flex-y-center` | `align-items: center;` | Alineación vertical común. |
|
|
| `.flex-col-gap-sm` | `flex-direction: column; gap: var(--sk-space-sm);` | Columna con espaciado de 8px. |
|
|
|
|
```css
|
|
/* Utilidades de Espaciado */
|
|
.p-md { padding: var(--sk-space-md); }
|
|
.py-sm { padding-top: var(--sk-space-sm); padding-bottom: var(--sk-space-sm); }
|
|
.mx-auto { margin-left: auto; margin-right: auto; }
|
|
|
|
/* Utilidades de Flexbox */
|
|
.flex { display: flex; }
|
|
.flex-col { flex-direction: column; }
|
|
.justify-between { justify-content: space-between; }
|
|
.items-center { align-items: center; }
|
|
|
|
/* Utilidades de Borde/Sombra */
|
|
.border-light { border: 1px solid var(--sk-color-border-light); }
|
|
.shadow-panel { box-shadow: var(--sk-shadow-panel); }
|
|
.rounded-md { border-radius: var(--sk-radius-md); }
|
|
```
|
|
|
|
### B. Colores y Texto
|
|
|
|
```css
|
|
/* Colores de Fondo */
|
|
.bg-white { background-color: var(--sk-color-bg-white); }
|
|
.bg-secondary { background-color: var(--sk-color-secondary); }
|
|
|
|
/* Colores de Texto */
|
|
.text-dark { color: var(--sk-color-text-dark); }
|
|
.text-sub { color: var(--sk-color-text-sub); }
|
|
.text-primary { color: var(--sk-color-primary); }
|
|
|
|
/* Estilos de Texto */
|
|
.text-sm { font-size: 0.9em; }
|
|
.text-lg { font-size: 1.1em; }
|
|
.font-bold { font-weight: 700; }
|
|
.font-medium { font-weight: 500; }
|
|
```
|
|
|
|
-----
|
|
|
|
## 🧩 3. Clases de Componentes Específicos (SK Components)
|
|
|
|
Estos estilos agrupan utilidades y estilos fijos para los elementos recurrentes de la interfaz de StreamYard.
|
|
|
|
### A. Barra de Navegación Lateral (Side Nav / Sidebar)
|
|
|
|
La barra de la izquierda y la derecha tienen un fondo gris muy claro o blanco, con líneas de división sutiles y texto denso.
|
|
|
|
```css
|
|
.sk-panel-left {
|
|
width: 200px; /* Ancho fijo para el panel izquierdo */
|
|
background-color: var(--sk-color-bg-white);
|
|
border-right: 1px solid var(--sk-color-border-light);
|
|
height: 100vh;
|
|
padding-top: var(--sk-space-md);
|
|
}
|
|
|
|
.sk-panel-right {
|
|
width: 250px; /* Ancho fijo para el panel derecho */
|
|
background-color: var(--sk-color-bg-white);
|
|
border-left: 1px solid var(--sk-color-border-light);
|
|
padding: var(--sk-space-md);
|
|
height: 100vh;
|
|
}
|
|
|
|
/* Estilo para los elementos de navegación (Mis Escenas, Comentarios, etc.) */
|
|
.sk-nav-item {
|
|
@extend .py-sm;
|
|
@extend .px-md;
|
|
@extend .text-sm;
|
|
color: var(--sk-color-text-dark);
|
|
cursor: pointer;
|
|
transition: background-color 0.2s;
|
|
}
|
|
|
|
.sk-nav-item:hover {
|
|
background-color: var(--sk-color-secondary); /* Resaltado muy ligero al pasar el mouse */
|
|
}
|
|
|
|
/* Estado Activo (Demo Scene 2) */
|
|
.sk-nav-item.is-active {
|
|
background-color: var(--sk-color-primary);
|
|
color: white;
|
|
font-weight: 500;
|
|
}
|
|
```
|
|
|
|
### B. Botones de Acción Global
|
|
|
|
Hay dos tipos de botones principales: Azul (Primario) y Rojo (Accento/Grabar).
|
|
|
|
```css
|
|
/* Botón Primario: "Agregar destino" / "Presentar o invitar" */
|
|
.sk-btn-primary {
|
|
background-color: var(--sk-color-primary);
|
|
color: white;
|
|
padding: 8px 16px;
|
|
border: none;
|
|
border-radius: var(--sk-radius-md);
|
|
font-size: var(--sk-font-size-base);
|
|
font-weight: 500;
|
|
cursor: pointer;
|
|
box-shadow: var(--sk-shadow-panel);
|
|
transition: background-color 0.2s;
|
|
}
|
|
|
|
.sk-btn-primary:hover {
|
|
background-color: #1565c0; /* Azul ligeramente más oscuro */
|
|
}
|
|
|
|
/* Botón de Énfasis: "Grabar" / Botón de Salir (Rojo) */
|
|
.sk-btn-accent {
|
|
background-color: var(--sk-color-accent);
|
|
color: white;
|
|
padding: 10px 20px;
|
|
border: none;
|
|
border-radius: var(--sk-radius-md);
|
|
font-size: 16px;
|
|
font-weight: 700;
|
|
cursor: pointer;
|
|
transition: background-color 0.2s;
|
|
}
|
|
|
|
.sk-btn-accent:hover {
|
|
background-color: #d83c3c; /* Rojo ligeramente más oscuro */
|
|
}
|
|
```
|
|
|
|
### C. Contenedor de Previsualización de Escena
|
|
|
|
El área central negra debe tener un borde y una sombra suaves.
|
|
|
|
```css
|
|
.sk-preview-main {
|
|
background-color: black;
|
|
color: white;
|
|
aspect-ratio: 16 / 9; /* Mantener la proporción de video */
|
|
width: 100%;
|
|
margin-bottom: var(--sk-space-md);
|
|
border-radius: var(--sk-radius-md);
|
|
box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* El elemento del borde/fondo blanco bajo el video */
|
|
.sk-bottom-controls-bar {
|
|
background-color: var(--sk-color-bg-white);
|
|
padding: var(--sk-space-md);
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
border-radius: var(--sk-radius-md);
|
|
box-shadow: var(--sk-shadow-panel);
|
|
}
|
|
```
|
|
|
|
## 📝 4. Ejemplo de Uso en HTML
|
|
|
|
Así usarías las clases de **StreamKit** para construir la interfaz (simulando los botones de la derecha):
|
|
|
|
```html
|
|
<aside class="sk-panel-right flex-col-gap-sm">
|
|
<div class="sk-comment-panel p-md shadow-panel rounded-md bg-secondary">
|
|
<p class="font-bold text-dark">StreamYard</p>
|
|
<p class="text-sub text-sm">Los comentarios de los espectadores...</p>
|
|
</div>
|
|
|
|
<nav class="flex-col-gap-sm">
|
|
<button class="sk-tool-btn items-center flex-y-center p-md">
|
|
<span class="sk-tool-icon">💬</span> Comentarios
|
|
</button>
|
|
<button class="sk-tool-btn items-center flex-y-center p-md">
|
|
<span class="sk-tool-icon">🖼️</span> Banners
|
|
</button>
|
|
</nav>
|
|
</aside>
|
|
``` |