@devground/ui-conventions 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +55 -0
- package/package.json +41 -0
- package/setup.js +89 -0
- package/skills/ui-conventions/SKILL.md +50 -0
- package/skills/ui-conventions/references/base.md +118 -0
- package/skills/ui-conventions/references/mining-prompt.md +38 -0
- package/skills/ui-conventions/references/overlay-template.md +52 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 devground contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# @devground/ui-conventions
|
|
2
|
+
|
|
3
|
+
**UI convention skill for Claude Code.** Loads a project's frontend conventions — own
|
|
4
|
+
components vs. browser primitives, es-CL input formatting for RUT/phone/currency,
|
|
5
|
+
accessibility and focus, error/loading states, microinteractions — as context **before**
|
|
6
|
+
generating or editing UI, instead of relying on a design audit to catch inconsistencies
|
|
7
|
+
after the fact.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
Into the current project:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx @devground/ui-conventions
|
|
15
|
+
# -> .claude/skills/ui-conventions
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
For all your projects (user-level):
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npx @devground/ui-conventions --global
|
|
22
|
+
# -> ~/.claude/skills/ui-conventions
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Existing files are never overwritten — re-run after an upgrade to pull in new reference
|
|
26
|
+
files while keeping your local edits.
|
|
27
|
+
|
|
28
|
+
## How it triggers
|
|
29
|
+
|
|
30
|
+
The skill fires before you generate or modify any frontend UI — forms, inputs, modals,
|
|
31
|
+
buttons, pages, React/Next.js/Tailwind components — even if you don't name the skill
|
|
32
|
+
explicitly.
|
|
33
|
+
|
|
34
|
+
## Base → overlay → mining
|
|
35
|
+
|
|
36
|
+
1. It always loads the universal base layer (`references/base.md`): rules that hold across
|
|
37
|
+
any stack or design system.
|
|
38
|
+
2. It looks for a project-specific overlay at `docs/ui-conventions.md` in the repo you're
|
|
39
|
+
working in. If one exists, it loads it, and on conflict the overlay wins over the base
|
|
40
|
+
— concrete tokens, own components, and helpers replace the generic rule.
|
|
41
|
+
3. If no overlay exists yet, it offers to mine one from your actual code (never without
|
|
42
|
+
asking) using `references/mining-prompt.md`, producing a `docs/ui-conventions.md` in the
|
|
43
|
+
format of `references/overlay-template.md`.
|
|
44
|
+
|
|
45
|
+
## Relationship with design-taste / design-audit
|
|
46
|
+
|
|
47
|
+
`@devground/design-taste` owns aesthetics — layout, typography, motion, spacing taste.
|
|
48
|
+
`ui-conventions` is a different layer: correctness and consistency (input semantics,
|
|
49
|
+
focus management, error states) applied while the code is being written. A later
|
|
50
|
+
design-audit remains a safety net, but with this skill loaded up front there should be
|
|
51
|
+
little left for it to catch.
|
|
52
|
+
|
|
53
|
+
## License
|
|
54
|
+
|
|
55
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@devground/ui-conventions",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "UI convention skill for Claude Code — loads a project's frontend conventions (own components vs browser primitives, es-CL input formatting for RUT/phone/currency, accessibility and focus, error/loading states, microinteractions) as context BEFORE generating or editing UI, with an optional per-project overlay.",
|
|
5
|
+
"bin": {
|
|
6
|
+
"devground-ui-conventions": "./setup.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"setup.js",
|
|
10
|
+
"skills/"
|
|
11
|
+
],
|
|
12
|
+
"keywords": [
|
|
13
|
+
"ui",
|
|
14
|
+
"conventions",
|
|
15
|
+
"frontend",
|
|
16
|
+
"accessibility",
|
|
17
|
+
"chile",
|
|
18
|
+
"es-cl",
|
|
19
|
+
"rut",
|
|
20
|
+
"claude-code",
|
|
21
|
+
"skill",
|
|
22
|
+
"devground"
|
|
23
|
+
],
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=20"
|
|
27
|
+
},
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "https://github.com/elkisdm/devground.git",
|
|
34
|
+
"directory": "packages/ui-conventions"
|
|
35
|
+
},
|
|
36
|
+
"homepage": "https://github.com/elkisdm/devground/tree/main/packages/ui-conventions#readme",
|
|
37
|
+
"bugs": {
|
|
38
|
+
"url": "https://github.com/elkisdm/devground/issues"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {}
|
|
41
|
+
}
|
package/setup.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Installs the ui-conventions skill into a Claude Code skills directory.
|
|
5
|
+
*
|
|
6
|
+
* npx @devground/ui-conventions -> <cwd>/.claude/skills/ (this project)
|
|
7
|
+
* npx @devground/ui-conventions --global -> ~/.claude/skills/ (all projects)
|
|
8
|
+
*
|
|
9
|
+
* Each skill lands in its own directory (matching its frontmatter `name`).
|
|
10
|
+
* Existing files are never overwritten — your local edits to a skill are
|
|
11
|
+
* preserved, only missing files are added (re-run after upgrading to pull in
|
|
12
|
+
* new skills or reference files).
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const fs = require('node:fs');
|
|
16
|
+
const path = require('node:path');
|
|
17
|
+
const os = require('node:os');
|
|
18
|
+
|
|
19
|
+
function log(msg) {
|
|
20
|
+
console.log(` \x1b[32m✓\x1b[0m ${msg}`);
|
|
21
|
+
}
|
|
22
|
+
function warn(msg) {
|
|
23
|
+
console.log(` \x1b[33m!\x1b[0m ${msg}`);
|
|
24
|
+
}
|
|
25
|
+
function info(msg) {
|
|
26
|
+
console.log(` \x1b[36m→\x1b[0m ${msg}`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Copies a tree, skipping files that already exist at the destination. */
|
|
30
|
+
function copyDirGuarded(src, dst) {
|
|
31
|
+
fs.mkdirSync(dst, { recursive: true });
|
|
32
|
+
let written = 0;
|
|
33
|
+
let skipped = 0;
|
|
34
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
35
|
+
const srcPath = path.join(src, entry.name);
|
|
36
|
+
const dstPath = path.join(dst, entry.name);
|
|
37
|
+
if (entry.isDirectory()) {
|
|
38
|
+
const sub = copyDirGuarded(srcPath, dstPath);
|
|
39
|
+
written += sub.written;
|
|
40
|
+
skipped += sub.skipped;
|
|
41
|
+
} else if (entry.isFile()) {
|
|
42
|
+
if (fs.existsSync(dstPath)) {
|
|
43
|
+
skipped++;
|
|
44
|
+
} else {
|
|
45
|
+
fs.copyFileSync(srcPath, dstPath);
|
|
46
|
+
written++;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return { written, skipped };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const global = process.argv.includes('--global');
|
|
54
|
+
const baseDir = global ? os.homedir() : process.cwd();
|
|
55
|
+
const src = path.join(__dirname, 'skills');
|
|
56
|
+
const dstRoot = path.join(baseDir, '.claude', 'skills');
|
|
57
|
+
|
|
58
|
+
if (!fs.existsSync(src)) {
|
|
59
|
+
console.error('\x1b[31m✗\x1b[0m skills/ not found in package. Aborting.');
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Only directories under skills/ are actual skills; loose files
|
|
64
|
+
// would be packaging metadata, not skills.
|
|
65
|
+
const skillDirs = fs
|
|
66
|
+
.readdirSync(src, { withFileTypes: true })
|
|
67
|
+
.filter((e) => e.isDirectory())
|
|
68
|
+
.map((e) => e.name);
|
|
69
|
+
|
|
70
|
+
let written = 0;
|
|
71
|
+
let skipped = 0;
|
|
72
|
+
const installed = [];
|
|
73
|
+
for (const name of skillDirs) {
|
|
74
|
+
const res = copyDirGuarded(path.join(src, name), path.join(dstRoot, name));
|
|
75
|
+
written += res.written;
|
|
76
|
+
skipped += res.skipped;
|
|
77
|
+
if (res.written > 0) installed.push(name);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const scope = global ? 'global (~/.claude/skills)' : 'project (.claude/skills)';
|
|
81
|
+
if (written > 0) {
|
|
82
|
+
log(`ui-conventions installed — ${scope} — ${written} file(s)`);
|
|
83
|
+
info(`skills: ${installed.join(', ')}`);
|
|
84
|
+
}
|
|
85
|
+
if (skipped > 0) warn(`${skipped} file(s) already existed (kept your version)`);
|
|
86
|
+
if (written === 0 && skipped > 0) info('Already up to date.');
|
|
87
|
+
|
|
88
|
+
info('Loads before you generate UI: universal conventions + your project overlay if');
|
|
89
|
+
info('docs/ui-conventions.md exists.');
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ui-conventions
|
|
3
|
+
description: Fires BEFORE generating or modifying any frontend UI — forms, inputs, modals, buttons, pages, React/Next.js/Tailwind components — even if the user does not name the skill; loads the project's UI conventions so code is correct and consistent on the first pass instead of fixed by a later audit; especially for Chilean (es-CL) apps: RUT, phone +56, currency/UF formatting.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# UI Conventions
|
|
7
|
+
|
|
8
|
+
## 1. Purpose / when this fires
|
|
9
|
+
|
|
10
|
+
This skill acts **before** UI code is written, not after. It is a correctness/consistency
|
|
11
|
+
layer: own components vs. browser primitives, input formatting, accessibility and focus,
|
|
12
|
+
error/loading states, and microinteractions — plus region-specific rules for Chile (es-CL)
|
|
13
|
+
such as RUT, phone, and currency formatting.
|
|
14
|
+
|
|
15
|
+
Trigger it whenever you are about to generate or edit a form, input, modal, button, page,
|
|
16
|
+
or any React/Next.js/Tailwind component — even if the user's request does not mention this
|
|
17
|
+
skill by name.
|
|
18
|
+
|
|
19
|
+
## 2. Load order (mandatory)
|
|
20
|
+
|
|
21
|
+
1. **Always** load `references/base.md` first. It is the universal layer: rules that apply
|
|
22
|
+
to any project regardless of stack or design system.
|
|
23
|
+
2. **Look for a project overlay** at `docs/ui-conventions.md` in the repo you are working in.
|
|
24
|
+
- If it exists, load it. On conflict, **the overlay wins over base.md** — its concrete
|
|
25
|
+
tokens, own components, and helpers replace the generic rule.
|
|
26
|
+
- If it does **not** exist, continue with the base layer alone and **offer** to mine one,
|
|
27
|
+
pointing at `references/mining-prompt.md`. Do not mine it unless the user asks for it.
|
|
28
|
+
|
|
29
|
+
## 3. Apply during generation, not after
|
|
30
|
+
|
|
31
|
+
Apply these conventions while writing the code — the first draft should already follow
|
|
32
|
+
them. This skill is not a linter that runs afterward; it is context loaded up front so the
|
|
33
|
+
correction pass a design-audit would otherwise require becomes unnecessary.
|
|
34
|
+
|
|
35
|
+
## 4. Relationship with other skills
|
|
36
|
+
|
|
37
|
+
`design-taste` / `frontend-design` own aesthetics — layout, typography, motion, spacing
|
|
38
|
+
taste. This skill is a different layer: correctness and consistency (does the input have
|
|
39
|
+
the right `type`/`inputMode`, does the modal trap focus, is the RUT validated). A later
|
|
40
|
+
design-audit still acts as a safety net, but with this skill loaded up front there should
|
|
41
|
+
be little left for it to catch.
|
|
42
|
+
|
|
43
|
+
## 5. Maintain the overlay
|
|
44
|
+
|
|
45
|
+
When you generate UI and establish a new pattern the overlay does not yet capture, pay down a
|
|
46
|
+
row from its "Deuda conocida" table, or discover that `docs/ui-conventions.md` contradicts the
|
|
47
|
+
real code, update the overlay in the **same** change — do not leave it stale. Same principle as
|
|
48
|
+
spec-flow's codemap: whoever uses the overlay maintains it. If the repo has no overlay yet and
|
|
49
|
+
you just wrote UI worth codifying, offer to mine one (`references/mining-prompt.md`); never
|
|
50
|
+
rewrite the overlay silently — surface the diff so the human can confirm it.
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Convenciones de UI — capa base
|
|
2
|
+
|
|
3
|
+
## 0. Cómo usar este documento
|
|
4
|
+
|
|
5
|
+
Esta es la capa universal: reglas válidas para cualquier proyecto, independientemente del
|
|
6
|
+
stack o sistema de diseño. Si el proyecto tiene un overlay (`docs/ui-conventions.md`), ese
|
|
7
|
+
overlay tiene precedencia sobre lo que dice aquí.
|
|
8
|
+
|
|
9
|
+
## 1. Componentes propios vs. primitivas del navegador
|
|
10
|
+
|
|
11
|
+
- Usa siempre el componente propio del proyecto (botón, input, modal) en vez de HTML nativo
|
|
12
|
+
estilizado a mano. Un `<button>` o `<input>` nativo con clases sueltas reimplementa algo
|
|
13
|
+
que el sistema de componentes ya resuelve, y diverge con el tiempo.
|
|
14
|
+
- Combina clases con el helper de composición de clases del proyecto (equivalente a
|
|
15
|
+
`cn`/`twMerge`), nunca concatenando template strings. Antipatrón: `` `btn ${variant} ${size}` ``
|
|
16
|
+
en vez de `cn('btn', variant, size)`.
|
|
17
|
+
- No introduzcas una librería nueva (toaster, motion, date-picker) sin una decisión
|
|
18
|
+
explícita (ADR o equivalente). Si el proyecto no tiene toaster, usa feedback inline; si
|
|
19
|
+
no tiene motion, usa transiciones CSS.
|
|
20
|
+
- Reutiliza el modal/dialog del proyecto para overlays — ya resuelve el trap de foco, el
|
|
21
|
+
cierre con Escape y el bloqueo de scroll. No reimplementes esa lógica con un portal
|
|
22
|
+
ad-hoc por componente.
|
|
23
|
+
|
|
24
|
+
## 2. Formateo de inputs (semántica universal)
|
|
25
|
+
|
|
26
|
+
- Usa `type`, `inputMode` y `autoComplete` semánticos según el campo:
|
|
27
|
+
- Email → `type="email"` `inputMode="email"` `autoComplete="email"` `spellCheck={false}`
|
|
28
|
+
`autoCapitalize="none"`.
|
|
29
|
+
- Teléfono → `type="tel"` `inputMode="tel"` `autoComplete="tel"`.
|
|
30
|
+
- Montos o identificadores numéricos de texto libre → `inputMode="numeric"`, sin
|
|
31
|
+
`type="number"` (que introduce spinners y bloquea el formateo visual).
|
|
32
|
+
- Para campos con formato visual (RUT, teléfono, montos), aplica la máscara en el
|
|
33
|
+
`onChange` pero persiste siempre el valor limpio o normalizado, no el string
|
|
34
|
+
formateado. Ejemplo genérico:
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
function handleChange(raw: string) {
|
|
38
|
+
const formatted = formatForDisplay(raw);
|
|
39
|
+
setDisplayValue(formatted);
|
|
40
|
+
setCleanValue(clean(raw));
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
- Valida en el boundary con un schema (p. ej. zod), no con lógica inline dentro del
|
|
45
|
+
componente. El componente muestra el error; no decide si el valor es válido.
|
|
46
|
+
|
|
47
|
+
## 3. Accesibilidad y estados de foco
|
|
48
|
+
|
|
49
|
+
- Todo botón icon-only lleva `aria-label` (dinámico si el estado que representa cambia,
|
|
50
|
+
p. ej. "Expandir menú" / "Minimizar menú").
|
|
51
|
+
- Todo campo tiene `label` asociado con `htmlFor` + `id` (usa un generador de id estable,
|
|
52
|
+
como `useId()`, en componentes reutilizables para no colisionar entre instancias).
|
|
53
|
+
- Los errores de un campo se asocian con `aria-invalid` + `aria-describedby` apuntando al
|
|
54
|
+
id del mensaje de error, y el mensaje lleva `role="alert"` o `role="status"` para que un
|
|
55
|
+
lector de pantalla lo anuncie.
|
|
56
|
+
- El anillo de foco usa el token de foco del proyecto y se dispara con `focus-visible`, no
|
|
57
|
+
con `focus:` a secas (que también dispara con click de mouse) ni con un color
|
|
58
|
+
hardcodeado.
|
|
59
|
+
- Los overlays (modal, dropdown, dialog) cierran con Escape, atrapan el foco dentro
|
|
60
|
+
mientras están abiertos, y restauran el foco al elemento que los abrió al cerrarse.
|
|
61
|
+
- Los SVG puramente decorativos llevan `aria-hidden="true"`.
|
|
62
|
+
- Los colores se aplican por token semántico del proyecto, nunca como clase de color cruda
|
|
63
|
+
(`gray-*`, `red-*`) ni hex suelto en el JSX.
|
|
64
|
+
|
|
65
|
+
## 4. Manejo de errores y carga
|
|
66
|
+
|
|
67
|
+
- Las rutas con carga asíncrona muestran un skeleton fiel al layout real (mismo header,
|
|
68
|
+
mismas filas o secciones), nunca un spinner de página completa.
|
|
69
|
+
- Durante el envío de un formulario: el botón queda `disabled`, muestra un spinner, y su
|
|
70
|
+
label cambia a gerundio ("Enviando…", "Guardando…").
|
|
71
|
+
- Los errores de formulario se muestran inline junto al campo que falló, no solo en un
|
|
72
|
+
banner genérico, y se anuncian por ARIA. En formularios largos, mueve el foco al primer
|
|
73
|
+
mensaje de error tras un submit fallido.
|
|
74
|
+
- Nunca silencies un error de red o de submit: siempre mapéalo a un mensaje legible para
|
|
75
|
+
el usuario y regístralo (`console.error` o equivalente). Un `catch` vacío o que solo
|
|
76
|
+
cambia estado sin loguear es un antipatrón.
|
|
77
|
+
- Los estados vacíos (empty states) son un componente dedicado con copy accionable, no un
|
|
78
|
+
`null` o una tabla sin filas sin explicación.
|
|
79
|
+
- Los estados de éxito son una vista o tarjeta dedicada, no solo la desaparición del
|
|
80
|
+
formulario.
|
|
81
|
+
- Toda ruta que hace fetching que puede fallar tiene un error boundary (`error.tsx` o
|
|
82
|
+
equivalente del framework) con una acción de reintento.
|
|
83
|
+
|
|
84
|
+
## 5. Microinteracciones
|
|
85
|
+
|
|
86
|
+
- El hover y el active de un control viven en la primitiva (el componente base), no se
|
|
87
|
+
duplican en cada lugar que lo usa.
|
|
88
|
+
- `prefers-reduced-motion` se respeta siempre: si la animación es CSS, usa el prefijo o
|
|
89
|
+
gate correspondiente (`motion-safe:` o un override global en `prefers-reduced-motion:
|
|
90
|
+
reduce`); si la animación es JS/imperativa, verifica la preferencia del sistema antes de
|
|
91
|
+
animar (equivalente a `useReducedMotion()`).
|
|
92
|
+
- El cierre animado de un overlay dispara el `onClose` real cuando termina la animación de
|
|
93
|
+
salida (`onAnimationEnd` o equivalente), nunca antes — si no, el contenido desaparece
|
|
94
|
+
antes de que termine la transición.
|
|
95
|
+
- Para acciones tipo "copiar al portapapeles": intercambia el label a un estado de
|
|
96
|
+
confirmación ("¡Copiado!") por ~2 segundos y envuelve la llamada al portapapeles en
|
|
97
|
+
`try/catch` (el acceso al portapapeles puede estar bloqueado por el navegador).
|
|
98
|
+
- Las animaciones en cascada (listas, grids) usan un delay proporcional al índice del
|
|
99
|
+
elemento, no todos animan al mismo tiempo.
|
|
100
|
+
- Los keyframes nuevos se declaran en el theme o en el CSS global del proyecto, no inline
|
|
101
|
+
por componente.
|
|
102
|
+
|
|
103
|
+
## 6. Región: Chile (es-CL)
|
|
104
|
+
|
|
105
|
+
> Si el proyecto no tiene helpers propios de RUT/teléfono/moneda, usa o instala
|
|
106
|
+
> `@devground/chile-formats` en vez de reimplementarlos; si ya tiene un helper, respétalo.
|
|
107
|
+
|
|
108
|
+
- **RUT**: usa un único helper de formateo (puntos y guion) y de validación (módulo 11);
|
|
109
|
+
aplica la máscara en el `onChange` pero persiste siempre el valor limpio, sin puntos ni
|
|
110
|
+
guion. El mensaje de error debe mencionar el dígito verificador ("RUT inválido, verifica
|
|
111
|
+
el dígito verificador"). Nunca reimplementes el algoritmo de módulo 11 dentro de un
|
|
112
|
+
componente.
|
|
113
|
+
- **Teléfono**: muestra el formato visual `+56 9 XXXX XXXX`, con `inputMode="tel"` y
|
|
114
|
+
`autoComplete="tel"`; normaliza el valor antes de persistirlo (no guardes el string tal
|
|
115
|
+
como el usuario lo tipeó).
|
|
116
|
+
- **Moneda, UF y fechas**: usa `Intl.NumberFormat("es-CL")` e `Intl.DateTimeFormat("es-CL")`
|
|
117
|
+
centralizados en un único helper compartido del proyecto. Nunca uses `toLocaleString` ad
|
|
118
|
+
hoc dentro de un componente, ni reimplementes el formateador en más de un lugar.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Prompt de minado — convenciones de UI de un repo
|
|
2
|
+
|
|
3
|
+
Este prompt es reutilizable: pégalo en cualquier repo cuando quieras generar su overlay de
|
|
4
|
+
convenciones de UI (`docs/ui-conventions.md`), el archivo que la skill `ui-conventions`
|
|
5
|
+
carga después con precedencia sobre la capa base.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
Actúa como un auditor de convenciones de interfaz. Recorre el frontend del repo actual (no
|
|
10
|
+
solo el README) y extrae los patrones recurrentes reales del código, organizados en estas
|
|
11
|
+
categorías:
|
|
12
|
+
|
|
13
|
+
1. Componentes propios vs. primitivas del navegador.
|
|
14
|
+
2. Formateo de inputs.
|
|
15
|
+
3. Accesibilidad y estados de foco.
|
|
16
|
+
4. Manejo de errores y carga.
|
|
17
|
+
5. Microinteracciones.
|
|
18
|
+
6. Regional: Chile (es-CL) si aplica — RUT, teléfono, moneda/UF, fechas.
|
|
19
|
+
|
|
20
|
+
Para cada patrón que documentes:
|
|
21
|
+
|
|
22
|
+
- Escribe la regla como un enunciado imperativo, no como una descripción.
|
|
23
|
+
- Cita un ejemplo correcto real del repo con `ruta/al/archivo.ext:línea`.
|
|
24
|
+
- Cita un antipatrón real si existe, con su propia ruta:línea. Los antipatrones citados son
|
|
25
|
+
deuda conocida documentada, no licencia para repetirlos en código nuevo.
|
|
26
|
+
|
|
27
|
+
Verifica el stack real contra el código (versión de framework, versión de Tailwind,
|
|
28
|
+
sistema de componentes, si hay toaster o librería de motion) — no confíes en el README ni
|
|
29
|
+
en archivos de configuración desactualizados si el código dice otra cosa.
|
|
30
|
+
|
|
31
|
+
Genera `docs/ui-conventions.md` en la raíz del repo auditado, usando el formato de
|
|
32
|
+
`references/overlay-template.md` de esta skill: mismo orden de secciones que la base
|
|
33
|
+
(0 a 6), mismo formato de patrón (Regla · Ejemplo correcto · Antipatrón), y cerrando con
|
|
34
|
+
una tabla de deuda conocida.
|
|
35
|
+
|
|
36
|
+
Ese archivo (`docs/ui-conventions.md`) es el overlay que la skill `ui-conventions` cargará
|
|
37
|
+
automáticamente la próxima vez que se genere o edite UI en este repo, y sus reglas
|
|
38
|
+
concretas prevalecerán sobre la capa base genérica en caso de conflicto.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Convenciones de interfaz — [nombre del proyecto]
|
|
2
|
+
|
|
3
|
+
> Lo definido en este archivo sustituye a la regla genérica de `base.md` en caso de
|
|
4
|
+
> conflicto.
|
|
5
|
+
|
|
6
|
+
**Stack:** [framework + versión] · [versión de Tailwind u otro CSS] · [sistema de
|
|
7
|
+
componentes: shadcn, design system propio, ninguno] · [toast: sí/no, cuál] · [motion:
|
|
8
|
+
librería o CSS puro, ninguna]
|
|
9
|
+
|
|
10
|
+
## 1. Componentes propios vs. primitivas del navegador
|
|
11
|
+
|
|
12
|
+
- **Regla:** [enunciado imperativo]
|
|
13
|
+
**Ejemplo correcto:** `ruta/al/archivo.ext:línea`
|
|
14
|
+
**Antipatrón:** [qué evita]
|
|
15
|
+
|
|
16
|
+
## 2. Formateo de inputs
|
|
17
|
+
|
|
18
|
+
- **Regla:** [enunciado imperativo]
|
|
19
|
+
**Ejemplo correcto:** `ruta/al/archivo.ext:línea`
|
|
20
|
+
**Antipatrón:** [qué evita]
|
|
21
|
+
|
|
22
|
+
## 3. Accesibilidad y estados de foco
|
|
23
|
+
|
|
24
|
+
- **Regla:** [enunciado imperativo]
|
|
25
|
+
**Ejemplo correcto:** `ruta/al/archivo.ext:línea`
|
|
26
|
+
**Antipatrón:** [qué evita]
|
|
27
|
+
|
|
28
|
+
## 4. Manejo de errores y carga
|
|
29
|
+
|
|
30
|
+
- **Regla:** [enunciado imperativo]
|
|
31
|
+
**Ejemplo correcto:** `ruta/al/archivo.ext:línea`
|
|
32
|
+
**Antipatrón:** [qué evita]
|
|
33
|
+
|
|
34
|
+
## 5. Microinteracciones
|
|
35
|
+
|
|
36
|
+
- **Regla:** [enunciado imperativo]
|
|
37
|
+
**Ejemplo correcto:** `ruta/al/archivo.ext:línea`
|
|
38
|
+
**Antipatrón:** [qué evita]
|
|
39
|
+
|
|
40
|
+
## 6. Regional: Chile (es-CL)
|
|
41
|
+
|
|
42
|
+
- **Regla:** [enunciado imperativo]
|
|
43
|
+
**Ejemplo correcto:** `ruta/al/archivo.ext:línea`
|
|
44
|
+
**Antipatrón:** [qué evita]
|
|
45
|
+
|
|
46
|
+
> Helper preferente si el repo no tiene uno propio: @devground/chile-formats.
|
|
47
|
+
|
|
48
|
+
## Deuda conocida
|
|
49
|
+
|
|
50
|
+
| Deuda | Ubicación | Patrón correcto |
|
|
51
|
+
| --- | --- | --- |
|
|
52
|
+
| [descripción] | `ruta/al/archivo.ext:línea` | [qué debería usarse en su lugar] |
|