Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Aura UI
Interfaces nativas aceleradas por GPU para macOS, Windows, Linux, Android e iOS con un solo código en Rust. Estilo encadenado con los nombres de Tailwind, componentes tipo shadcn, sombras por capas y animaciones, pensado para gastar poco: poca RAM, casi nada de CPU en reposo y binarios pequeños.
Un solo crate con un módulo por capa: aura_ui::core (entidades, tareas, geometría, color, animación y capa de
sistema), ::gpu (renderizador), ::view (elementos, estilo, recetas y layout), ::widgets (componentes y
estructura de pantalla), ::app (ventana y bucle) y ::ai (agentes de IA; feature ai, activa por defecto:
default-features = false la quita).
use *;
// Genera `main` en escritorio e iOS y `android_main` en Android.
app!;
La vista raíz ocupa el ancho, respeta el área segura y hereda el tema: .page() la estira también al alto y no
hacen falta bg ni text_color. View devuelve cualquier elemento (sin cerrar con .into_element()) y app!
monta la vista directamente; para preparar el keymap o entidades compartidas sigue valiendo
main!(opciones, |window| window.set_root(vista)) o AppOptions::run(vista). Render sigue existiendo: una vista
Render funciona sin cambios en todo lo que acepta View.
Tailwind
Los nombres son los de Tailwind en snake_case y todos son métodos de Styled: con use aura_ui::prelude::*; basta.
Cada uno solo fija un campo; no hay trabajo en tiempo de ejecución ni memoria extra hasta que se usan.
| Familia | Utilidades |
|---|---|
| Espaciado y tamaño (escala completa, 1 = 4 px) | p_4 px_2 pt_0_5 m_8 mx_auto gap_x_2 w_64 h_1_2 size_10 min_w_0 max_w_full inset_0 top_px |
| Flex | flex_row flex_col_reverse flex_wrap grow shrink_0 flex_1 flex_auto items_baseline justify_evenly self_end content_between |
| Cuadrícula | grid_cols_3 grid_rows_2 col_span_2 col_start_2 row_span_3 grid_flow_col + gap_* |
| Color | blue(500) slate(900) rose(50) del módulo palette, con .with_alpha(0.5); degradados bg_gradient_to_r(a, b) |
| Texto | text_xs … text_9xl font_thin … font_black text_center leading_tight tracking_wide truncate line_clamp_3 uppercase line_through font_mono |
| Bordes | border border_t_2 border_x_0 rounded_lg rounded_t_xl rounded_bl_full ring_2 ring_color(..) |
| Efectos | shadow_md glow opacity_50 |
| Transformaciones | rotate_45 neg_rotate_12 scale_105 scale_x_50 translate_x_4 neg_translate_y_1_2 skew_x_6 (giran y escalan desde el centro; no cambian el layout) |
| Filtros | blur_sm blur_md backdrop_blur_xl backdrop_blur_px(6.0) |
| Apilado | z_10 z_50 neg_z_10 z(7) entre hermanos, también para el ratón |
| Overflow | overflow_hidden overflow_x_scroll overflow_auto |
| Estados | hover active focus group_hover drag_over |
| Variantes | sm md lg xl xxl (según el ancho de la ventana, primero móvil), dark light |
div
.flex_col.gap_4.p_6.rounded_xl.border.border_color
.md
.dark
.child
.child
Matices
backdrop_blur_*difumina lo que hay detrás del elemento (cristal esmerilado).blur_*difumina el elemento y sus hijos, pero se aplica sobre toda su caja: también suaviza el fondo que tenga debajo y no se extiende más allá del borde.- Un desenfoque dentro de un elemento girado usa el rectángulo que envuelve al giro (no hay desenfoque girado).
- Sin GPU (el rasterizador por CPU) las transformaciones sin giro funcionan; un giro o una inclinación se pinta sin girar. Las hitboxes de un elemento transformado son el rectángulo que envuelve a la figura.
- Un desenfoque pinta el frame en una textura propia y suelta su memoria al rato de no usarse.
Todavía no existe: divide-* y space-*, cursor-* más allá de los de CursorStyle, select-none,
pointer-events-none, object-fit, mix-blend, sticky, otros filtros (brightness, grayscale…), valores
arbitrarios (w-[137px]; usa .w(px(137.0))) y las variantes disabled: y focus-within:.
Recetas
Las combinaciones que toda app repite tienen nombre y salen del tema. Son un trait, así que valen también para
Button, Badge y Style:
| Receta | Equivale a |
|---|---|
.page() |
pantalla completa, en columna, con fondo y texto del tema |
.card() |
superficie elevada, borde, rounded_xl, sombra suave y p_4 |
.panel() |
superficie plana con borde tenue (barras laterales, docks) |
.hstack() · .vstack() · .center() |
flex_row + items_center · flex_col · centrado en ambos ejes |
.muted() · .caption() |
texto secundario · texto pequeño secundario |
.heading() · .subheading() |
título de pantalla · título de sección |
.scroll_y() · .flexible() |
scroll vertical que encoge · flex_1 con min_w_0 |
Para estructura hay funciones que devuelven un Div ya compuesto:
page_header
section
setting_row
field
empty_state
Sombras y animaciones
div.shadow_lg // presets xs, sm, md, lg, xl, 2xl
div.shadow // capas
div.glow // resplandor de color
let x = cx.transition;
let t = cx.animate;
let c = cx.animate_between;
Curvas: Linear, EaseIn, EaseOut, EaseInOut, CubicBezier(..) (como CSS) y Spring { bounce }. Con retraso,
repetición y ida y vuelta. Una animación solo pide frames mientras corre.
Eficiencia
Medido en macOS arm64 con el ejemplo contador, build release:
| Memoria (huella) | 25 MB |
| CPU en reposo | 0,00 s en 20 s |
| Binario | 7,0 MB (macOS) · 6,1 MB (iOS) · 4,2 MB (iOS con opt-level = "s" y LTO completo) |
Cómo lo logra: el bucle duerme hasta que hay entrada, un temporizador o una animación; no pinta si no se ve; usa la GPU de bajo consumo con un solo frame en cola; suelta cachés al pasar a segundo plano o ante un aviso de poca memoria; las sombras son una sola primitiva analítica en el shader, sin pasadas de desenfoque.
Perfil recomendado para tus apps móviles:
[]
= "s"
= "fat"
= 1
= "abort"
= "symbols"
Menos código repetido
Todo viene de use aura_ui::prelude::*;, sin importar nada más.
Lo que la librería hace sola: la vista raíz ocupa el ancho y el área segura y el tema pinta el fondo y el color de
texto por defecto (.page() la estira también al alto); los atajos de los widgets (TextInput, Picker, menús) ya
están registrados; y cualquier cambio hecho dentro de un manejador redibuja (el update de la entidad marca la
ventana), así que un listener no necesita cx.notify(). Las recetas (.page(), .card(), .hstack()…) y las
piezas de estructura (section, setting_row…) quitan las cadenas de estilo que se copiaban de una pantalla a otra.
// Clics: sin `|this: &mut V, _: &ClickEvent, cx|` ni `cx.notify()` (se avisa solo)
.on_click
.on_click // invierte un bool
.on_click // asigna un valor
.on_click // emite un evento a quien se suscriba
// Segundo plano: sin hilo propio, canal ni `sender.update`; vuelve a la vista y redibuja
cx.job;
self.search.run; // `Latest`: solo vale la última
cx.job_blocking;
// Configuración: JSON en ~/.config/<app> (APPDATA en Windows), escritura atómica
let store = new.unwrap;
let theme = store.load.str_or.to_owned;
store.update?;
// Controles y animación que toda app acaba copiando
div.pressable // mano + hover + active
tool_button
chip // etiqueta pulsable
switch
let t = cx.phase; // segundos; `wave(t, 2.0, 0.0)` da una onda de 0 a 1
let a = cx.fade_in;
// Arranque: la vista directa, sin cierre ni `set_root`
new.size.run?;
Por qué cuesta poco: cx.job reutiliza el pool de la app (en vez de un hilo del sistema por tarea) y un trabajo
cancelado no llega a tocar la UI; guardar es un temporal más un renombrado; nada de esto despierta el bucle
cuando no hay trabajo.
Novedades en 0.2.2
Todo es aditivo: el código de 0.2.1 compila sin cambios.
- Nueva forma corta de vista:
impl View { fn view(..) -> impl IntoElement }, sin.into_element(). Toda vistaRenderes tambiénView, así que no hay que migrar nada. - Nuevo
app!para montar una vista directa:app!(opciones, vista).main!(opciones, |window| …)sigue igual; para preparar el keymap o entidades compartidas, usamain!oAppOptions::run(vista). - Atajos automáticos: la ventana registra los de
TextInput,Pickery menús al crearse.bind_widget_keyssigue disponible y los atajos de la app siguen teniendo prioridad. - Recetas y estructura:
.page(),.card(),.hstack()… ysection,setting_row,empty_state… La raíz hereda tema y ancho;.page()la estira también al alto (antes erasize_full+bg+text_color).
Móvil
Ver docs/movil.md del repositorio. Resumen: iOS compila para aarch64-apple-ios y el simulador; Android
para aarch64-linux-android con NativeActivity. Toque, deslizar con inercia, pulsación larga, teclado del sistema y
área segura están implementados. En iOS, añade el manifiesto UIScene al Info.plist (plantilla en docs/ios/Info.plist;
lo exige el SDK de iOS 27). Probado en el simulador de iPhone; aún no en un iPhone ni un Android físicos.
Licencia
Aura UI tiene doble licencia, a tu elección (crates.io muestra la primera; la segunda va incluida en el paquete):
- AGPL-3.0-only (
LICENSE-AGPL, https://www.gnu.org/licenses/agpl-3.0.html): gratis. Si la usas, tu app completa debe publicarse bajo AGPL-3.0 con su código fuente. - Licencia comercial (
LICENSE-COMMERCIAL.md): para apps de código cerrado. Regalías del 10 % de los ingresos brutos de cada producto que use Aura UI. Para obtenerla escribe a camiloghs1@gmail.com.
Si no tienes la licencia comercial, aplica la AGPL-3.0. Los iconos de src/widgets/svg son de Lucide (ISC), con su
aviso en src/widgets/svg/LICENSE-lucide.
Copyright (C) 2026 Camilo Grajales Holguín.