Repository navigation
Tutoriales
English · Español
Cada una de las cuatro pantallas (Deck, Diseñar, Biblioteca, Jugar) tiene un recorrido guiado corto: oscurece la ventana menos una zona, la rodea y la explica en una tarjeta a su lado, paso a paso. Se abre solo la primera vez que el usuario entra en una pantalla y el botón de ayuda de la barra superior lo repite. Es solo de la pantalla (src/features/tutorial/): ni comandos de Rust, ni red, ni nada guardado en el deck.
| Fichero | Qué hace |
|---|---|
src/features/tutorial/pasos.ts |
type Paso = { ancla?, titulo, texto } y PASOS: Record<Vista, Paso[]>, los pasos de cada pantalla. |
src/features/tutorial/tutorial.tsx |
Tutorial (montado una vez), su Recorrido interno (la capa y la tarjeta), useTutorialInicial() (la apertura de la primera visita) y las ayudas zona (medir un ancla) y sitioTarjeta (colocar la tarjeta). |
src/stores/ui-store.ts |
tutorial: Vista | null (el recorrido abierto), abrirTutorial(v) y la preferencia guardada tutorialesVistos: Vista[]. Véase Stores de estado. |
src/features/shell/app-shell.tsx |
El botón de ayuda (icono CircleHelp, tooltip «Tutorial de esta pantalla»), <Tutorial /> y la llamada a useTutorialInicial(). Véase Ajustes y shell. |
src/i18n/<código>/tutorial.json |
Las cadenas del recorrido, un área de i18n propia en los 15 idiomas. Véase Internacionalización. |
src/index.css |
[data-slot="tutorial-tarjeta"] comparte la regla de los modales opacos. Véase Temas y skins. |
Un paso señala una zona con un ancla: el valor de un atributo data-tutorial en el elemento que se rodea. El recorrido lo busca con document.querySelector('[data-tutorial="…"]'), así que las pantallas no importan nada del tutorial ni el tutorial importa ningún componente de pantalla; mover un panel solo exige que el atributo se mueva con él. Un paso sin ancla (la presentación de cada recorrido) enseña su tarjeta centrada sobre la ventana oscurecida entera. titulo y texto son cadenas fuente en español envueltas en paraTraducir (la tabla vive fuera de React) y traducidas con t() al pintarse.
Pantalla (Vista) |
Ancla | Título | Elemento (fichero) |
|---|---|---|---|
deck |
ninguna | Te damos la bienvenida a Proxy Builder | |
pestanas |
Cuatro pantallas | el ToggleGroup de vistas (shell/app-shell.tsx) |
|
nombre-deck |
El nombre del deck | el campo NombreDeck (shell/app-shell.tsx) |
|
lista-cuadro |
La lista de cartas | el panel del editor de la lista (decklist/decklist-panel.tsx) |
|
lista-opciones |
Importar y opciones | el panel de opciones (decklist/decklist-panel.tsx) |
|
vista-barra |
La barra de la vista previa | la barra (preview/preview-pane.tsx) |
|
vista-hojas |
Las hojas | la zona de las hojas (preview/preview-pane.tsx) |
|
exportar-boton |
Exportar | la cabecera y el botón de exportar (export/export-panel.tsx) |
|
exportar-ajustes |
Cómo sale el papel | las secciones de ajustes (export/export-panel.tsx) |
|
ajustes |
Ajustes | el botón de Ajustes (shell/app-shell.tsx) |
|
ayuda |
Para repasar | el botón de ayuda (shell/app-shell.tsx) |
|
disenar |
ninguna | Diseñar: el editor de cartas | |
disenar-lista |
Las cartas del deck |
ListaCartas (disenar/lista-cartas.tsx) |
|
disenar-barra |
Herramientas del deck | la barra de arriba (disenar/disenar-screen.tsx) |
|
disenar-vista |
La vista previa |
VistaPrevia (disenar/vista-previa.tsx) |
|
disenar-incidencias |
Avisos |
Incidencias (disenar/incidencias.tsx) |
|
disenar-formulario |
Lo que se puede cambiar | las Tabs del formulario (disenar/formulario.tsx) |
|
disenar-pie |
Guardar | el pie para guardar (disenar/disenar-screen.tsx) |
|
biblioteca |
ninguna | La biblioteca | |
biblioteca-barra |
Buscar y ordenar |
BarraHerramientas (library/barra-herramientas.tsx) |
|
biblioteca-acciones |
Nuevo, importar y espacio | su hueco de acciones (library/barra-herramientas.tsx) |
|
biblioteca-lateral |
Etiquetas y favoritos |
BarraLateral (library/barra-lateral.tsx) |
|
biblioteca-decks |
Tus decks | la zona de los decks (library/library-screen.tsx) |
|
mesa |
ninguna | La mesa de juego | |
mesa-entrada |
Elige deck y formato | la entrada (mesa/entrada.tsx) |
|
mesa-solitario |
Solitario | el botón «Solitario» (mesa/entrada.tsx) |
|
mesa-barra |
La barra de la mesa |
BarraMesa (mesa/barra-mesa.tsx) |
|
mesa-campo |
El campo | la capa del campo (mesa/tablero.tsx) |
|
mesa-mano |
La mano | el rótulo de la mano (mesa/tablero.tsx) |
|
mesa-biblioteca |
La biblioteca | la zona de la biblioteca (mesa/tablero.tsx) |
|
mesa-vida |
Tu vida |
VidaJugador (mesa/vida-jugador.tsx) |
|
mesa-tablero |
Atajos | el tablero entero (mesa/tablero.tsx) |
Los textos cuentan lo que hace cada zona en la versión actual (por ejemplo los tamaños de carta en «Cómo sale el papel», o que las partidas, las Secuelas y las de doble cara tienen una ilustración por parte en el paso de la vista previa de Diseñar), así que un cambio que altere una zona también debe poner al día su paso.
El recorrido de Jugar mezcla dos pantallas: la entrada (sin partida abierta) y la mesa (con una partida abierta). Solo existen las anclas de la que se ve, así que las demás salen centradas; el recorrido se abre solo la primera vez que se entra en «Jugar», que normalmente es la entrada. Hay más anclas en la mesa para pasos futuros o para reutilizarlas (mesa-lista, el selector de lista para jugar de la entrada, mesa-pila, mesa-fantasma, mesa-pasar, mesa-cementerio, mesa-exilio, mesa-mando, mesa-banquillo). Las piezas de la mesa se describen en Mesa de juego.
flowchart LR
A["useUi().tutorial = vista"] --> B["Tutorial: Recorrido key=vista"]
B --> C["zona(ancla): getBoundingClientRect"]
C -->|está, al menos 4 x 4 px| D["anillo + box-shadow oscurece el resto"]
C -->|no está o no se ve| E["todo oscuro, tarjeta centrada"]
D --> F["sitioTarjeta: derecha, izquierda, debajo, encima, si no centro"]
E --> F
-
Portal en
document.body: una capafixed inset-0 z-[100](data-tutorial-capa) que tapa la ventana, así que los clics fuera de la tarjeta no hacen nada. -
Resalte: una caja sin interacción 6 px (
AIRE) más grande que la zona, con un anillo del color primario y una sombra negra de0 0 0 9999pxal 60 % que oscurece todo lo demás. Sin zona, una capa negra lisa al 60 %. -
Tarjeta (
data-slot="tutorial-tarjeta",role="dialog",aria-modal, rotulada por su título): 320 px de ancho (ANCHO).sitioTarjetaprueba, por orden, a la derecha de la zona, a la izquierda, debajo y encima, a 14 px (HUECO) y al menos a 16 px de los bordes de la ventana (MARGEN), ajustada en el otro eje; si no cabe en ningún lado, centrada. Su alto se mide tras cada pintado para colocarla con su tamaño real. -
Volver a medir: en cada cambio de paso, con un
ResizeObserversobre el elemento del ancla y con el eventoresizede la ventana, así que al arrastrar los paneles redimensionables o cambiar el tamaño de la ventana el resalte y la tarjeta se mueven con ellos. - Ancla que falta: si el elemento no está en el DOM o mide menos de 4 x 4 px (por ejemplo un panel de Diseñar que no se pinta mientras no hay carta elegida), el paso sale igual, centrado.
- Controles: un contador «Paso {a} de {b}», Anterior (desde el paso 2), Siguiente (Terminar en el último) y una X («Cerrar el tutorial»). El botón principal toma el foco en cada paso, así que Intro avanza.
-
Teclado: un
keydownenwindowen fase de captura atiende Escape (cerrar), flecha derecha (siguiente, o cerrar en el último paso) y flecha izquierda (anterior), y llama apreventDefault+stopPropagationcon ellas. Por qué en captura: las pantallas tienen sus propias flechas (Alt+flechas en Diseñar, la selección en las hojas) y no deben reaccionar con el recorrido abierto. Las demás teclas pasan sin tocarse. -
TutorialpintaRecorridoconkey={vista}, así que abrir el recorrido de otra pantalla empieza en el paso 1.
-
abrirTutorial(v)ponetutorialy, sivno es nulo y aún no está entutorialesVistos, lo añade; luego guarda las preferencias. Por eso un recorrido cuenta como visto en cuanto se abre, aunque el usuario lo cierre en el primer paso: se ofrece una vez, sin insistir.abrirTutorial(null)lo cierra. -
tutorialesVistosse guarda con las demás preferencias enlocalStorage["proxybuilder.preferencias"]; el recorrido abierto (tutorial) es solo de la sesión. -
useTutorialInicial()(lo llamaAppShell) vigilauseUi().vista. Si esa pantalla no está entutorialesVistosy no hay un recorrido abierto, espera 700 ms (para que la pantalla esté pintada y sus anclas se puedan medir) y lo abre, pero solo si el usuario sigue en esa pantalla, no se ha abierto otro recorrido entretanto,useUi().dialogoestá vacío y no hay ningún[role="dialog"]/[role="alertdialog"]en el DOM. Un recorrido nunca se abre encima de un diálogo; si había uno, se vuelve a ofrecer la próxima vez que el usuario entre en esa pantalla. - El botón de ayuda llama a
abrirTutorial(vista)con la pantalla actual en cualquier momento.
-
Paso nuevo: añadir
data-tutorial="<id>"al elemento, añadir unPasoaPASOS[vista]en su sitio y las dos cadenas atutorial.jsonen los 15 idiomas (si no,pnpm idiomasfalla). Conviene que el ancla esté en un elemento que siempre se pinte en esa pantalla, o aceptar que el paso salga centrado. -
Pantalla nueva (
Vista):PASOSes unRecord<Vista, Paso[]>, así que TypeScript exige sus pasos;useTutorialInicialy el botón de ayuda funcionan sin cambios. - La tarjeta debe seguir opaca: depende de la regla de modales opacos de
src/index.css, que también cubre los diálogos.
src/stores/__tests__/ui-store.test.ts: abrir un recorrido lo apunta como visto una sola vez y la lista se guarda, mientras que el recorrido abierto no (abrir un tutorial lo apunta como visto (una vez) y se recuerda; el abierto no), y las claves de preferencias guardadas incluyen tutorialesVistos. La capa no tiene test automático (depende de medidas de maquetación que el entorno node de Vitest no tiene).
Use and build · Uso y desarrollo
- User-Guide · Guía de usuario
- Development-Setup · Preparación del entorno de desarrollo
- Testing-and-CI · Tests y CI
- Releases-and-Auto-Updates · Versiones y actualizaciones automáticas
- Conventions · Convenciones
Architecture · Arquitectura
- Architecture · Arquitectura
- IPC-and-Error-Handling · IPC y manejo de errores
- Rust-App-Layer · Capa de aplicación Rust
Data · Datos
- Deck-Model · Modelo del mazo
- Storage-and-Blobs · Almacenamiento y blobs
- Deck-Package-Format · Formato del paquete de mazo
- Deck-Library · Biblioteca de mazos
Getting cards · Conseguir cartas
- Decklist-Parsing · Parseo de la lista del mazo
- Scryfall-Integration · Integración con Scryfall
- External-Sources · Fuentes externas
- Card-Identification-and-OCR · Identificación de cartas y OCR
Layout, images, PDF · Maquetación, imagen y PDF
- Layout-Engine · Motor de maquetación
- Imaging-and-PDF · Imagen y PDF
- Export · Exportación
- Live-Preview · Vista previa en vivo
- Statistics · Estadísticas
Card designer · Diseñador de cartas
- Designer-Overview · Visión general del diseñador
- Designer-Engine · Motor del diseñador
- Designer-Composition · Composición del diseñador
- Frame-Packs · Packs de marcos
- Designer-App-Layer · Capa de aplicación del diseñador
- Designer-UI · Interfaz del diseñador
- Card-Editor-Dialog · Diálogo Editar carta
Game table · Mesa de juego
Frontend · Frontend
- Frontend-Architecture · Arquitectura del frontend
- State-Stores · Stores de estado
- Internationalization · Internacionalización
- Themes-and-Skins · Temas y skins
- Settings-and-Shell · Ajustes y shell
- Tutorials · Tutoriales
- Decklist-Panel · Panel de la lista del mazo
- Add-Card-and-Variants · Añadir carta y variantes
- Set-Browser · Explorador de sets
Reference · Referencia