# no-arbitrary-value

Regla de oxlint que reporta valores arbitrarios de Tailwind CSS como `w-[200px]` o `bg-[#ff0000]`,
para que salgan de tu theme; una allow list cubre excepciones.

## De un vistazo

| Autofix | Sugerencias en el editor | Design system                         | Opciones                                |
| ------- | ------------------------ | ------------------------------------- | --------------------------------------- |
| No      | No                       | Opcional — se usa si hay `entryPoint` | `allow`, `allowVariables`, `entryPoint` |

## Qué hace esta regla

Marca cualquier utility de Tailwind que use un arbitrary value — la escotilla — para forzar al
equipo a usar un token del design system o extender el theme en vez de literales sueltos. Cualquier
cosa que el parser reconozca como arbitrary value califica: dimensiones (`w-[200px]`,
`text-[14px]`), colores (`bg-[#ff0000]`), expresiones calc (`p-[calc(1rem+2px)]`), gradients, y lo
mismo dentro de variants (`hover:w-[200px]`) o con el modificador `!` (`!w-[200px]`, `w-[200px]!`).

**Las dos formas cuentan.** `bg-(--brand)` es el azúcar de Tailwind v4 para `bg-[var(--brand)]` — el
mismo arbitrary value, escrito de dos maneras — y antes solo se reportaba la forma con corchetes.
Eso convertía a [`enforce-consistent-variable-syntax`](./enforce-consistent-variable-syntax) en un
lavadero: con su ajuste por defecto `shorthand`, su autofix reescribía la forma reportada en la no
reportada y la violación desaparecía sin que el código cambiara en el fondo.

DS-opcional — no necesitas `entryPoint`: saber si una clase es un arbitrary value es un chequeo
sintáctico, barato en repos grandes. Con uno configurado, el reporte además nombra el arreglo — los
pasos y tokens más cercanos de tu theme, con sus valores, y el archivo donde agregar un token:

```text
"w-[203px]" uses an arbitrary value. Closest in your theme: w-50.5 (202px) or w-51 (204px).
If none fits, add a token to src/styles.css.
```

Un paso o token exacto se ofrece solo (`h-[26px]` → `h-6.5 (26px)`); si no, el más cercano por
debajo y por arriba. Un valor que no es una longitud (un color, un `calc()`) recibe solo el archivo.
El design system se carga en la primera violación, nunca para un archivo limpio;
`allowVariables: 'runtime'` también lo usa, para saber qué variables CSS define tu stylesheet. No
hay autofix: reemplazar un arbitrary value por un token requiere criterio humano, así que la regla
solo reporta.

Los _variants_ arbitrarios (`[&>svg]:w-4`) no son _values_ arbitrarios y la regla los deja
tranquilos. Mira el lado del valor de la utility, no el prefijo de selector.

## Opciones

### `allow`

`string[]`, default `[]`.

Una lista de prefijos de utilities donde los arbitrary values están tolerados. El match es un
`String.prototype.startsWith` literal contra la forma bare de la utility (después de sacar `!` y los
variants), así que entradas como `"grid-cols-"` permiten `grid-cols-[18rem_1fr]` sin habilitar
`grid-rows-[...]`. Candidatos típicos: container queries (`@container`), grid templates
(`grid-cols-`, `grid-rows-`), y transforms genuinamente a medida (`bg-[url(`).

```jsonc
{
  "tailwindcss/no-arbitrary-value": ["error", {
    "allow": ["grid-cols-", "grid-rows-", "bg-[url("]
  }]
}
```

Tip: empieza con `[]` para ver dónde tu codebase realmente necesita escapes, después promueve los
legítimos a `allow` en vez de desactivar la regla entera.

### `allowVariables`

`'none' | 'runtime' | 'all'`, default `'none'`.

Qué hacer con un valor que no es más que una variable CSS — `w-(--sidebar-width)`,
`h-[var(--radix-select-trigger-height)]`, `text-(length:--size)`, con o sin fallback o modificador
de opacidad:

- `'none'` las reporta, como cualquier arbitrary value.
- `'runtime'` permite las variables que **ningún CSS de tu design system define** — las que
  JavaScript o un `style` inline definen en runtime, como las `--radix-*` de Radix o el
  `--sidebar-width` de un sidebar, para las que no existe un token. Una variable que define tu
  stylesheet (`--primary`) se sigue reportando: existe una utilidad con nombre para ella (mira
  [`prefer-theme-tokens`](./prefer-theme-tokens)). Este modo lee el design system; sin `entryPoint`
  no se puede probar que una variable no esté definida, así que las referencias se reportan.
- `'all'` permite toda referencia pura a una variable.

Un valor que hace algo más que leer una variable — `w-[calc(var(--x)*2)]` — es un arbitrary value en
todos los modos.

```jsonc
{ "tailwindcss/no-arbitrary-value": ["warn", { "allowVariables": "runtime" }] }
```

### `entryPoint`

`string`, opcional. Override por regla de `settings.tailwindcss.entryPoint`, que solo lee
`allowVariables: 'runtime'`.

## Ejemplos

### ✗ Incorrecto

```tsx
// Dimensión one-off en vez de un token de spacing
<div className="w-[200px] p-[10px]" />

// Literal hex en vez de un color del theme
<div className="bg-[#ff0000] text-white" />

// El variant no cambia el veredicto
<div className="hover:w-[200px]" />

// El modificador `!` tampoco
<div className="!w-[200px]" />

// El shorthand de v4 es el mismo arbitrary value
<div className="bg-(--brand) border-(length:--stroke)" />
```

### ✓ Correcto

```tsx
// Usa tokens de spacing
<div className="w-64 p-2.5" />

// Usa un color de theme declarado en @theme
<div className="bg-brand text-white" />

// Los variants arbitrarios están bien — apuntan a selectores, no a valores
<div className="[&>svg]:w-4" />

// Permitido vía `allow: ["grid-cols-"]`
// options: { "allow": ["grid-cols-"] }
<div className="grid grid-cols-[18rem_1fr]" />
```

## Interacciones con otras reglas

- **`no-hardcoded-colors`**: un subset estricto enfocado en utilities de color (`bg-[#ff0]`,
  `text-[rgb(...)]`). Activa esa si quieres el mensaje granular específico de colores; activa ambas
  para enforcement por capas. Las dos van a disparar sobre la misma clase, lo cual suele ser
  deseable durante una migración.
- **`no-unnecessary-arbitrary-value`**: esta regla prohibe los arbitrary values directamente;
  `no-unnecessary-arbitrary-value` es más suave — solo marca arbitraries que tienen equivalente
  nombrado exacto (`w-[100%]` → `w-full`). Pueden coexistir: la suave autofixea los casos triviales
  y esta atrapa lo que queda.
- **`prefer-theme-tokens`**: misma intención, pero DS-dependiente. `prefer-theme-tokens` consulta tu
  `@theme` y sugiere el token que coincide. Combínalas: esta regla es tu freno de mano cuando
  todavía no existe el token.
- **`enforce-consistent-variable-syntax`**: convierte entre `bg-[var(--x)]` y `bg-(--x)`. Como las
  dos formas se reportan aquí, correrla — en cualquier dirección — no puede sacar una clase del
  alcance de esta regla.

## Cuándo desactivarla

- **Prototipos / branches de spike** donde la velocidad le gana a la disciplina. Reactívala antes de
  integrar.
- **Archivos que genuinamente necesitan un arbitrary value** (landing pages one-off, shims de
  CSS-in-JS dinámico). Prefiere `allow` con una lista corta de prefijos, o desactiva por línea con
  `// oxlint-disable-next-line tailwindcss/no-arbitrary-value`.
- **Librerías que publican utilities de Tailwind que el consumidor re-skinea**: a veces la forma
  arbitraria es el contrato más limpio. Documenta la decisión y desactiva la regla en ese paquete.
