orn-ui

Diseño atómico

Atom, molecule and organism represented as circles that nest into progressively larger clusters
Fuente: Uxcel: uxcel.com/glossary/atomic-design

El diseño atómico organiza una interfaz en unas pocas capas que se construyen una sobre otra: las piezas pequeñas se combinan en piezas más grandes, y nada depende nunca de algo que esté por encima. orn-ui se publica en esas capas, y la misma estructura sirve en cualquier código de frontend, sea React Native o no.

Por qué se creó orn-ui

La mayoría de las librerías de componentes intentan cubrir web y móvil desde un solo código. Ese alcance se paga en el teléfono: capas de abstracción adicionales, dependencias pensadas para web que viajan hasta el bundle, motores de estilos que resuelven en tiempo de ejecución. Se paga por una portabilidad que no se está usando.

orn-ui toma el camino contrario. Es 100% React Native, con cero dependencias en tiempo de ejecución: react y react-native son los únicos peers. Nada que compilar, ningún motor de estilos que configurar, ningún plugin que agregar al bundler.

  • Se instala un componente, no una librería

    npx orn-ui add button copia el código fuente de ese componente dentro de tu proyecto. No agrega un paquete al package.json ni una versión que mantener: el código es tuyo y puedes editarlo.

    npx orn-ui add button
  • O se instala el paquete y aun así solo se publica lo que se usa

    pnpm add orn-ui no tiene side effects y exporta por subpath, así que importar Button trae Button. Los componentes que nunca se importan nunca llegan al bundle.

    pnpm add orn-ui
  • La configuración es un solo wrapper

    Al envolver tu app en UIProvider, todos los componentes ya tienen theme, íconos, insets y labels. Ese es el paso de configuración completo.

    Primeros pasos →

El objetivo es la velocidad: maquetar pantallas reales sin rehacer un Button por quinta vez, y sin gastar el contexto de un agente escribiendo desde cero primitivas que ya existen, probadas, en la capa de abajo.

Las tres capas

El modelo original de Brad Frost tiene cinco niveles: átomos, moléculas, organismos, templates y páginas. Una librería de componentes solo puede ser dueña de los tres primeros, porque los templates y las páginas describen tu producto, no un paquete reutilizable. Por eso orn-ui llega hasta organismos y las últimas dos capas quedan en tu app.

Átomos

La pieza útil más pequeña. Sin composición ni lógica de negocio: renderiza lo que recibe y avisa lo que hizo la persona usuaria.

En orn-ui
Button, Input, Badge, Avatar, Body
Regla práctica
Si se divide, no queda nada utilizable.

Moléculas

Unos pocos átomos conectados para un trabajo concreto. Puede tener estado local de UI, pero nunca sabe de dónde vinieron los datos.

En orn-ui
InfoRow, SegmentedControl, Stepper, OptionCard
Regla práctica
Un solo trabajo, describible en una frase corta sin usar la palabra “y”.

Organismos

Una sección autónoma de una pantalla. Compone moléculas y átomos, es dueña del flujo de interacción y es la primera capa que puede tocar datos o navegación.

En orn-ui
Modal, List, SearchList, NavigationBar, Wizard
Regla práctica
Puesto solo en una pantalla vacía, sigue teniendo sentido.
Las dependencias apuntan siempre hacia abajo: los organismos pueden importar moléculas y átomos, las moléculas pueden importar átomos, y los átomos no importan nada de las capas superiores. Al romper esa dirección una sola vez, las capas dejan de significar algo.
// organisms/UserCard.tsx — may import both layers below
import { InfoRow } from '../molecules/InfoRow';
import { Avatar } from '../atoms/Avatar';

// molecules/InfoRow.tsx — may import atoms
import { Body, Caption } from '../atoms/Text';

// atoms/Avatar.tsx — imports nothing from the layers above
import { InfoRow } from '../molecules/InfoRow'; // never

Para qué sirve

  • Nombrar deja de ser una discusión

    El lugar de un componente nuevo lo decide de qué depende, no el gusto de cada persona. Eso elimina una de las discusiones más repetidas en un código que crece.

  • La duplicación se vuelve visible

    Cuando cada primitiva vive en una sola carpeta, el segundo Button escrito dentro de una pantalla salta a la vista en lugar de sobrevivir un año.

  • Los refactors quedan acotados

    Como las dependencias van en una sola dirección, cambiar un organismo nunca puede romper un átomo. El alcance de un cambio queda limitado a la capa que se tocó.

  • Encaja con el tree-shaking

    Las capas en un solo sentido son exactamente lo que un bundler necesita para descartar código sin usar. En orn-ui, importar un átomo trae ese átomo y nada más.

  • Las personas nuevas producen el primer día

    “Va en moléculas” es una respuesta completa. Alguien que nunca vio el repositorio puede ubicar un componente en el lugar correcto.

Cómo aplicarlo en cualquier proyecto

Nada de esto es específico de React Native. Las mismas tres carpetas funcionan en Next.js, Vue, SwiftUI o CSS modules a secas.

  1. Crear las carpetas

    Tres directorios dentro de components/, más el lugar donde ya viven tus rutas. Los templates y las páginas son tus pantallas actuales: no hace falta inventarles un lugar nuevo.

    src/
      components/
        atoms/        Button, Input, Badge, Avatar…
        molecules/    SearchField, OptionCard, InfoRow…
        organisms/    Modal, List, NavigationBar…
      screens/        templates + pages (your routes)
  2. Escribir la única regla

    Los imports apuntan solo hacia abajo. Conviene hacerlo cumplir de forma mecánica: import/no-restricted-paths en ESLint, o dependency-cruiser, rompen el build en lugar de depender de que alguien lo note en el review.

  3. Empezar por la pantalla, no por la teoría

    No conviene diseñar un catálogo de átomos por adelantado. Es mejor armar una pantalla real y después extraer lo que se repite. Lo que aparece en tres lugares se ganó bajar de capa.

  4. Que la capa decida quién tiene el estado

    Los átomos no tienen estado y se manejan por props. Las moléculas pueden tener estado local de UI: abierto/cerrado, índice enfocado. El fetch de datos, los stores y la navegación empiezan en los organismos, nunca más abajo.

  5. Templates simples, páginas inteligentes

    Un template es un layout con huecos; una página llena esos huecos con datos reales. Esa separación es lo que permite previsualizar cualquier layout sin backend.

Tres formas de hacerlo mal

  • Clasificar por tamaño en lugar de por dependencia. Un componente pequeño que lee de un store es un organismo, por pocas líneas que tenga.
  • Atomizar de más. Envolver cada Text en un átomo propio deja cien archivos de una línea que nadie recuerda. Conviene promover en la tercera repetición, no en la primera.
  • Carpetas sin la regla. Tres directorios con imports yendo en todas las direcciones son el mismo desorden de antes con nombres nuevos: la dirección de las dependencias es toda la metodología.

Cómo está organizada orn-ui

22 átomos, 8 moléculas y 18 organismos, cada uno con su propia página con props, variantes y una grabación del simulador. Todos se instalan por separado.

Ver los componentes →

Fuentes

La metodología es de Brad Frost, publicada en 2013 y ampliada en un libro que se puede leer gratis en línea. El resto son las herramientas mencionadas más arriba y el código de orn-ui, de donde salen los conteos de componentes de esta página.

  1. Brad Frost — “Atomic Design”bradfrost.com, 10 Jun 2013

    El artículo de 2013 que introdujo la analogía con la química y las cinco etapas.

  2. Brad Frost — Atomic Design, ch. 2: “Atomic Design Methodology”atomicdesign.bradfrost.com

    La definición completa del libro sobre átomos, moléculas, organismos, templates y páginas.

  3. eslint-plugin-import — import/no-restricted-pathsgithub.com/import-js

    Regla de ESLint que se usa para hacer cumplir la dirección de los imports entre capas.

  4. dependency-cruisergithub.com/sverweij

    Valida y visualiza dependencias; la otra forma de romper el build ante un import en la dirección equivocada.

  5. orn-uigithub.com/DavidTrujillo123

    La librería misma; las capas descritas aquí son las carpetas que publica.