Início Boas práticas Tema Idiomas e RTL App e cabeçalho Layout Tipografia Abas Menu e âncora Dropdown e popover Command e toggles Botão Campos Seleção e valores Combobox e menções Datas e calendário Árvore e cascata Transfer Upload Filtros Tabela Planilha KPI e estatística Badge e tag Listas e detalhes Gráficos Imagem e carrossel Ícones Diagramas Alertas e estados Progresso e passos Diálogo e toast Drawer e notificação Utilitários Overview Work queue Report Report com htmx Form / request Tabela administrativa Página de detalhe Formulário em diálogo Gráfico com dados do servidor Buscar… llms.txt Tema Tema Restaurar Copiar prompt Copiar snippet Prompt: para as instruções de um agente. Snippet: direto no templates/base.html. v0.11.0 Componentes prontos para Abstra Pages Uma linha de <script>, zero build. Web Components com tema da sua marca, estados de carregando, vazio e erro embutidos, e dados vindos direto do Python. Ver componentes Boas práticas Leia https://design.abstra.io/llms.txt antes de gerar uma Page: ele tem as regras, o snippet de import e o link para a API completa (llms-full.txt, catalog.json). <link rel="stylesheet" href="https://design.abstra.io/v0/abstra-ds.css"> <script type="module" src="https://design.abstra.io/v0/abstra-ds.js"></script> ComponentesAgrupados como na barra lateral. Cada página tem exemplos e a API completa. App e cabeçalhoab-appab-page-headerab-breadcrumb Layoutab-stackab-gridab-clusterab-splitab-card Tipografiaab-titleab-textab-paragraphab-linkab-proseab-code Abasab-tabsab-tab-panel Menu e âncoraab-menuab-menu-itemab-menu-groupab-submenuab-anchor Dropdown, tooltip e popoverab-dropdownab-tooltipab-popoverab-popconfirm Botãoab-button Camposab-inputab-selectab-date-rangeab-field Seleção e valoresab-checkboxab-checkbox-groupab-radio-groupab-radioab-switchab-segmentedab-sliderab-number-inputab-rateab-color-picker Combobox e mençõesab-comboboxab-mentions Datas e calendárioab-date-pickerab-time-pickerab-calendar Árvore e cascataab-treeab-tree-selectab-cascader Transferab-transfer Uploadab-upload Filtrosab-filter-bar Tabelaab-tableab-pagination Planilhaab-spreadsheet KPI e estatísticaab-kpiab-statistic Badge e tagab-badgeab-tag Listas e detalhesab-avatarab-avatar-groupab-descriptionsab-listab-timelineab-timeline-itemab-collapseab-collapse-itemab-divider Gráficosab-chartab-sparkline Imagem e carrosselab-imageab-carousel Íconesab-icon Diagramas: árvores, fluxos e modelosab-diagramab-nodeab-edge Alertas e estadosab-alertab-emptyab-skeletonab-spinner Progresso, passos e resultadoab-progressab-stepsab-result Diálogo e toastab-dialog Drawer e notificaçãoab-drawer Command, context menu e togglesab-commandab-context-menuab-toggleab-toggle-groupab-button-groupab-input-otpab-scroll-areaab-aspect-ratioab-hover-cardab-kbd Utilitáriosab-qrcodeab-tourab-watermarkab-affixab-float-buttonab-splitterab-splitter-panel Receitas de páginaLayouts completos, um por tipo de tarefa. Setup (once, in templates/base.html) <!DOCTYPE html> <html lang="pt-BR"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>{{ title }} · Acme</title> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"> <link rel="stylesheet" href="https://design.abstra.io/v0/abstra-ds.css"> <script type="module" src="https://design.abstra.io/v0/abstra-ds.js"></script> <style> /* The project's whole theme. Only --ab-* tokens. Setting --ab-accent alone is enough. */ :root { --ab-accent: #C04657; /* optional: --ab-font-sans: "DM Sans", system-ui, sans-serif; (and load the font <link>) */ } </style> </head> <body> <ab-app brand-name="Acme" user-email="{{ user.email if user else '' }}"> <a slot="nav" href="/dashboard" {% if active == 'dashboard' %}aria-current="page"{% endif %}>Dashboard</a> <a slot="nav" href="/orders" {% if active == 'orders' %}aria-current="page"{% endif %}>Pedidos</a> {% block body %}{% endblock %} </ab-app> {% block scripts %}{% endblock %} </body> </html>Rules
  1. New projects: no Tailwind, no CSS framework, no page CSS. A project built on this library does not load Tailwind or other UI kits. Layout comes from ab-stack, ab-grid, ab-cluster, ab-split, ab-card; spacing from gap="1".."8". If you need a <style> block for anything other than :root { --ab-*: … }, you are probably missing a component. Existing projects keep their styling. A project that already has a look (Tailwind, its own CSS) is never migrated unless the user asks. Its new parts may use ab-* components next to the existing markup: add only the <script type="module" src="https://design.abstra.io/v0/abstra-ds.js"> to its base.html (not the CSS file, whose global base styles would restyle the existing pages) and map the project's theme in :root: --ab-accent to its accent color, --ab-font-sans to its font. Style ab-* components only through attributes and --ab-* tokens, never utility classes on their insides.

  2. Theme only through --ab-* tokens in one :root block in base.html. Brand: take main_color → --ab-accent, font_family → --ab-font-sans (load the font), logo_url → <ab-app brand-logo>. Never invent brand colors.

  3. Data from Python goes into components as JS properties, never as HTML strings: table.rows = await get_rows(). HTML attributes are kebab-case and JS properties camelCase (empty-text ↔ table.emptyText); every component's API table lists both. Arrays and objects (rows, columns, items, data) are set as properties, or as JSON in the attribute from Jinja. Setting properties before a component has loaded is safe; set them again to update; null values show "—". Values are always rendered as text (no XSS). Never build markup with innerHTML + template strings.

  4. Call Python with the generated functions or abCall("fn_name", {params}). abCall speaks the same protocol, works before the generated globals exist, and throws an Error with the server message.

  5. Load data with abLoad(component, () => python_fn(args)), never with hand-written loading/try/catch. It sets loading (data already on screen stays visible), clears and shows error with a readable message (tables and charts get "Tentar de novo", which re-runs the same call), falls back to a toast for components without an error state, logs technical details to the console, and drops stale responses when a newer load starts (fast filter changes). The data goes to the component's data property (rows, data, value, items, code); an ab-table also accepts { rows, total, page } from a paginated Python function. One call for several components: abLoad([kpi1, kpi2, table], get_overview, { apply: (data, el) => … }). Errors from actions (save, delete): abToast(await abErrorMessage(error), { tone: "danger" }) inside an async handler. The public abErrorMessage helper returns Promise<string>; always await it before assigning text or showing a toast, even after the library has loaded. Rely on the built-in empty state (empty-text); never leave a blank panel.

  6. Never use alert(), confirm() or prompt(). Use await abConfirm({ title, message, tone: "danger" }), abToast("Salvo"), <ab-alert> or error="…" on a field.

  7. Tables paginate on the server: select(limit=, offset=) + count(); set total, listen to ab-page-change. Use client-sort only for small, fully-loaded lists.

  8. Formatting is built in: column/kpi type = currency (BRL), number, percent (ratio 0.12 → 12%), date ("YYYY-MM-DD" is a local date), datetime. Don't pre-format numbers in Python.

  9. Status = ab-badge with a tone (ok, warn, danger, info, accent, neutral); in tables use type: "badge", tones: { Pago: "ok" }.

  10. Layout follows the task (see recipes): Overview, Work queue, Record, Report, Form, Process. At most 4 KPIs, only numbers people track.

  11. Icons: <ab-icon name="…"> or the icon attribute of components. Built-in names (house, magnifying-glass, listed in catalog.json icons) render instantly; any other icon uses set:name, loaded on demand: lucide:camera, mdi:bank, ph:house-fill, fa6-brands:github, simple-icons:nubank. Sets: ph, lucide, tabler, mdi, heroicons, ri, bi, fa6-solid, fa6-regular, fa6-brands, carbon, fluent, simple-icons (list: https://design.abstra.io/icons/sets.json; names per set: /icons/<set>/index.json; search: https://design.abstra.io/components/icons/). Prefer one set per page. Only names that exist (a wrong name renders nothing and warns). No emoji icons.

  12. Check the console after run_page: misuse is reported as [abstra-ds] <ab-…> … warnings. Fix all of them.

  13. Lazy components: only the core (layout, shell, buttons, fields, table, dialog, tabs, KPI, feedback) is in abstra-ds.js; every other ab-* loads automatically the first time its tag is in the page. Setting properties is always safe (chart.data = rows works before it loads), but before calling a method at page load (upload.setStatus(), drawer.show(), tour.start()…) do await customElements.whenDefined("ab-drawer"). In event handlers (clicks) it is already loaded.

  14. htmx works out of the box (htmx 2 and 4). ab-* form controls are native form fields, so <form hx-post> / hx-include send their values (ab-date-range sends <name>_from and <name>_to; multi-value controls repeat the name). Fragments returned by the server can contain any ab-* tag, including lazy ones. For components that take data (ab-table columns/rows/row-actions, ab-chart data, ab-tree data, ab-steps items, ab-transfer data, ab-cascader options, ab-command items…) render it as a JSON attribute from Jinja: rows='{{ rows|tojson }}' (single quotes outside). Component events are valid hx-triggers and their detail is sent as parameters automatically: hx-trigger="ab-page-change, ab-sort-change" sends page, pageSize / sort, dir; ab-filter-change sends each filter (<name>_from/<name>_to for date ranges); ab-tab-change sends value. Built in when htmx is present: the ab-button that triggered a request shows its loading state, hx-confirm opens abConfirm (never the browser's confirm), and HTTP errors show an abToast (turn off with <meta name="ab-htmx-errors" content="off"> if the page shows its own error). See the "Report com htmx" recipe.

  15. Spacing and nesting: siblings always sit in an ab-stack, ab-grid or ab-cluster (never two blocks in a plain <div> or <form>: they touch). slot="…" works only on a component's direct children: a <form> with a card wraps the card (<form><ab-stack><ab-card>…</ab-card><ab-cluster justify="end">…submit…</ab-cluster></ab-stack></form>), never the other way round with slot="footer" inside the form. No card in a card: ab-kpi, ab-table and ab-chart go directly in the page; inside an ab-card use ab-statistic for a number. The console warns about misplaced slots and KPIs inside cards.

  16. Diagrams: ab-diagram with ab-node children (any content) and ab-edge from to (or parent on the node): layout="tree" for org charts and group structures (collapsible, edge-label), layout="layered" for flowcharts, processes and data models (shape="diamond"/"circle", data-port + from-port/to-port, marker-end="many"), layout="manual" + draggable for free canvases. Never draw diagrams by hand in SVG.

  17. Language and direction follow <html lang dir>. Built-in texts (pagination, empty/error states, dialog buttons, calendar, upload…) are Brazilian Portuguese for pt* or no lang, English for any other language; numbers and dates format with the real lang. For another language, put the page's texts in <script type="application/json" id="ab-strings">{ "next": "Weiter", "pageOf": "Seite {page} von {pages}", "items": { "one": "{n} Eintrag", "other": "{n} Einträge" }, "date": { "today": "Heute" } }</script> in <head> (or window.abStrings = {…}, or abSetStrings({…}) at any time): partial is fine, missing keys fall back to English. Values go in {name} placeholders, plurals as { one, other, … } objects (Intl.PluralRules), no functions. Every key with its placeholders: https://design.abstra.io/strings/en.json (await abStringsTemplate() in JS). With dir="rtl" layout, directional icons (caret-left, arrow-right, sign-out…), floating panels, submenus, arrow keys, carousels and toasts mirror; <ab-icon no-flip> opts out; ab-drawer placement="start|end" follows the direction. The date picker grid is always Gregorian; other dates use the language's default calendar (Persian for fa): lang="fa-u-ca-gregory" makes them Gregorian. Not mirrored yet: ab-slider, ab-spreadsheet, ab-diagram, chart axes. Details: https://design.abstra.io/i18n/

Events (all bubble, detail in event.detail)

ab-filter-change {values} · ab-sort-change {key, dir} · ab-page-change {page, pageSize} · ab-row-click {row, index} · ab-row-action {action, row} · ab-retry · ab-tab-change {value} · ab-close {returnValue} · ab-dismiss · native input / change on form controls.