Un espacio para concentrarte
Las superficies y el espaciado crean una jerarquía clara.
VISOMI / FRONTEND UI
Clases Tailwind compartidas y controles nativos de Angular y Astro. Un mismo lenguaje visual que aprovecha el comportamiento del navegador.
37 familias de componentes
Los ejemplos usan datos ficticios. No se envía ni guarda información.
heading.classes()
<h2 appUI uiSize="lg">A clear hierarchy</h2><Heading as="h2" uiSize="lg">A clear hierarchy</Heading>import { heading } from '@visomi-stack/web-frontend-ui';
heading.classes();text.classes()
Una buena base deja espacio para tu contenido.
Una buena base deja espacio para tu contenido.
El texto de apoyo sigue siendo legible en ambos temas.
Una buena base deja espacio para tu contenido.
<p appUI uiSize="md">Good defaults.</p>
<p appUI tone="muted" uiSize="sm">Supporting text.</p><Text uiSize="md">Good defaults.</Text>
<Text tone="muted" uiSize="sm">Supporting text.</Text>import { text } from '@visomi-stack/web-frontend-ui';
text.classes();code.classes()
button.classes()const ready = true;
button.classes({ variant: 'primary', size: 'md' });<code appUI>button.classes()</code>
<pre><code appUI block>const ready = true;</code></pre><Code>button.classes()</Code>
<pre><Code block>const ready = true;</Code></pre>import { code } from '@visomi-stack/web-frontend-ui';
code.classes();link.classes()
<a appUI href="#forms">Learn more</a>
<a appUI variant="muted" underline="hover" href="#forms">Learn more</a>
<a appUI variant="inverse" href="#forms">Learn more</a><Link href="#forms">Learn more</Link>
<Link variant="muted" underline="hover" href="#forms">Learn more</Link>
<Link variant="inverse" href="#forms">Learn more</Link>import { link } from '@visomi-stack/web-frontend-ui';
link.classes();divider.classes()
<hr appUI />
<hr appUI soft /><Divider />
<Divider soft />import { divider } from '@visomi-stack/web-frontend-ui';
divider.classes();container.classes()
El contenido se centra con un ancho estándar de Tailwind.
<div appUI="container" width="sm">Content</div><Container width="sm">Content</Container>import { container } from '@visomi-stack/web-frontend-ui';
container.classes();card.classes()
Las superficies y el espaciado crean una jerarquía clara.
Las superficies y el espaciado crean una jerarquía clara.
Las superficies y el espaciado crean una jerarquía clara.
Las superficies y el espaciado crean una jerarquía clara.
Las superficies y el espaciado crean una jerarquía clara.
Superficie transparente
<article appUI tone="raised" padding="md">Content</article><Card tone="raised" padding="md">Content</Card>import { card } from '@visomi-stack/web-frontend-ui';
card.classes();pageHeader.classes()
Una cabecera reutilizable con acciones.
<header appUI><h2>Workspace settings</h2><button appUI>Save</button></header><PageHeader><Heading>Workspace settings</Heading><Button>Save</Button></PageHeader>import { pageHeader } from '@visomi-stack/web-frontend-ui';
pageHeader.classes();appShell.classes()
Barra lateral en escritorio e inferior en móvil. Enlaces nativos, estilos compartidos y sin runtime de layout.
Abrir el layout completo<app-shell contentId="main" skipLabel="Skip to content">
<app-sidebar label="Primary">...</app-sidebar>
<header app-topbar>...</header>
<h1>Workspace</h1>
<nav appUI="navbar" aria-label="Primary">...</nav>
</app-shell><AppShell contentId="main" skipLabel="Skip to content">
<Sidebar slot="sidebar" label="Primary">...</Sidebar>
<Topbar slot="header">...</Topbar>
<h1>Workspace</h1>
<Navbar slot="mobile" aria-label="Primary">...</Navbar>
</AppShell>import { appShell } from '@visomi-stack/web-frontend-ui';
appShell.classes();topbar.classes()
<header app-topbar>
<span data-slot="title">Workspace</span>
<button appUI>Save</button>
</header><Topbar>
<span slot="title">Workspace</span>
<Button>Save</Button>
</Topbar>import { topbar } from '@visomi-stack/web-frontend-ui';
topbar.classes();badge.classes()
<span appUI="badge" tone="success">Ready</span><Badge tone="success">Ready</Badge>import { badge } from '@visomi-stack/web-frontend-ui';
badge.classes();avatar.classes()
<span appUI="avatar" uiSize="md" role="img" aria-label="Morgan Lee">ML</span>
<img appUI src="/favicon.svg" alt="Demo workspace" /><Avatar label="Morgan Lee" uiSize="md">ML</Avatar>
<Avatar src="/favicon.svg" label="Demo workspace" />import { avatar } from '@visomi-stack/web-frontend-ui';
avatar.classes();table.classes()
Las filas se convierten en tarjetas con etiquetas antes de md. Las cabeceras siguen disponibles para tecnologías de asistencia.
| Espacio | Estado |
|---|---|
| Estudio | Listo |
| Pruebas | Borrador |
<table appUI mobileCards stickyHeaders role="table"><caption>Workspaces</caption>…</table>
<!-- Keep native header associations and explicit row/cell roles. Cell labels use <span data-slot="label" aria-hidden="true">…</span>. --><Table mobileCards stickyHeaders role="table"><caption>Workspaces</caption>…</Table>
<!-- Keep native header associations and explicit row/cell roles. Cell labels use <span data-slot="label" aria-hidden="true">…</span>. -->import { table } from '@visomi-stack/web-frontend-ui';
table.classes();descriptionList.classes()
<dl appUI><dt>Plan</dt><dd>Team</dd></dl><DescriptionList><dt>Plan</dt><dd>Team</dd></DescriptionList>import { descriptionList } from '@visomi-stack/web-frontend-ui';
descriptionList.classes();pagination.classes()
<nav appUI="pagination" aria-label="Pages"><a appUI="button" href="?page=2" aria-current="page">2</a></nav><Pagination aria-label="Pages"><LinkButton href="?page=2" aria-current="page">2</LinkButton></Pagination>import { pagination } from '@visomi-stack/web-frontend-ui';
pagination.classes();fieldset.classes()
<fieldset appUI><legend appUI>Preferences</legend><label appUI inline><input appUI type="checkbox" /> Updates</label></fieldset><Fieldset><Label as="legend">Preferences</Label><Label inline><Checkbox /> Updates</Label></Fieldset>import { fieldset } from '@visomi-stack/web-frontend-ui';
fieldset.classes();field.classes()
Visible en tu espacio de ejemplo.
<app-field #nameField="appField" controlId="name" label="Name" description="Visible name."><input appUI [id]="nameField.controlId()" [attr.aria-describedby]="nameField.describedBy()" /></app-field><Field controlId="name" label="Name" description="Visible name."><Input id="name" aria-describedby="name-help" /></Field>import { field } from '@visomi-stack/web-frontend-ui';
field.classes();label.classes()
<label appUI for="label-example">Name</label><input appUI id="label-example" /><Label for="label-example">Name</Label><Input id="label-example" />import { label } from '@visomi-stack/web-frontend-ui';
label.classes();description.classes()
Usa una dirección ficticia para este ejemplo.
<input appUI id="email" aria-label="Email" aria-describedby="email-help" /><p appUI="description" id="email-help">Use an example address.</p><Input id="email" aria-label="Email" aria-describedby="email-help" /><Description id="email-help">Use an example address.</Description>import { description } from '@visomi-stack/web-frontend-ui';
description.classes();errorMessage.classes()
Escribe una dirección de correo válida.
<input appUI id="email" aria-label="Email" aria-invalid="true" aria-describedby="email-error" /><p app-error id="email-error">Enter a valid address.</p><Input id="email" aria-label="Email" aria-invalid="true" aria-describedby="email-error" /><ErrorMessage id="email-error">Enter a valid address.</ErrorMessage>import { errorMessage } from '@visomi-stack/web-frontend-ui';
errorMessage.classes();input.classes()
Los errores se expanden al salir de un campo inválido o comprobar el formulario. Se ocultan al editar y cuando el campo es válido.
Usa una dirección ficticia para este ejemplo.
Escribe una dirección de correo válida.
<input appUI type="email" uiSize="sm" [size]="24" required /><Input type="email" uiSize="sm" size={24} required />import { input } from '@visomi-stack/web-frontend-ui';
input.classes();textarea.classes()
Escribe un mensaje breve de ejemplo.
<textarea appUI uiSize="md" id="message" rows="3" aria-label="Message"></textarea><Textarea uiSize="md" id="message" rows={3} aria-label="Message">Example text.</Textarea>import { textarea } from '@visomi-stack/web-frontend-ui';
textarea.classes();select.classes()
<select appUI uiSize="md" aria-label="Region"><option value="am">Americas</option></select><Select uiSize="md" aria-label="Region"><option value="am" selected>Americas</option></Select>import { select } from '@visomi-stack/web-frontend-ui';
select.classes();checkbox.classes()
<label appUI inline><input appUI type="checkbox" name="updates" /> Receive updates</label><Label inline><Checkbox name="updates" /> Receive updates</Label>import { checkbox } from '@visomi-stack/web-frontend-ui';
checkbox.classes();radio.classes()
<fieldset appUI><legend>Workspace type</legend><label appUI inline><input appUI type="radio" name="kind" value="personal" /> Personal</label></fieldset><Fieldset><legend>Workspace type</legend><Label inline><Radio name="kind" value="personal" /> Personal</Label></Fieldset>import { radio } from '@visomi-stack/web-frontend-ui';
radio.classes();toggle.classes()
<label appUI inline><input appUI="switch" type="checkbox" /> Enable notifications</label><Label inline><Toggle /> Enable notifications</Label>import { toggle } from '@visomi-stack/web-frontend-ui';
toggle.classes();radioCard.classes()
<label appUI="radio-card"><input appUI type="radio" name="plan" value="standard" /><span>Standard</span></label><RadioCard><Radio name="plan" value="standard" /><span>Standard</span></RadioCard>import { radioCard } from '@visomi-stack/web-frontend-ui';
radioCard.classes();inputGroup.classes()
<div appUI="input-group"><span data-slot="prefix" aria-hidden="true">$</span><input appUI aria-label="Amount" /></div><InputGroup><span data-slot="prefix" aria-hidden="true">$</span><Input aria-label="Amount" /></InputGroup>import { inputGroup } from '@visomi-stack/web-frontend-ui';
inputGroup.classes();alert.classes()
El estado tiene una etiqueta visible y no depende solo del color.
El estado tiene una etiqueta visible y no depende solo del color.
El estado tiene una etiqueta visible y no depende solo del color.
<div appUI="alert" tone="success" role="status"><strong>Ready</strong><p>Visible feedback.</p></div><Alert tone="success" role="status"><strong>Ready</strong><p>Visible feedback.</p></Alert>import { alert } from '@visomi-stack/web-frontend-ui';
alert.classes();loader.classes()
<span role="status"><span appUI="loader" aria-hidden="true"></span><span class="sr-only">Loading</span></span><Loader label="Loading example" />import { loader } from '@visomi-stack/web-frontend-ui';
loader.classes();disclosure.classes()
Comparten las clases tipadas. Cada aplicación conserva su HTML nativo, sus eventos y el comportamiento de los formularios.
<details appUI><summary>What is shared?</summary><p>The class recipes.</p></details><Disclosure summary="What is shared?"><p>The class recipes.</p></Disclosure>import { disclosure } from '@visomi-stack/web-frontend-ui';
disclosure.classes();dialog.classes()
<button appUI (click)="example.showModal()">Open dialog</button>
<dialog appUI #example="appUIDialog" aria-labelledby="dialog-title"><h2 id="dialog-title">Review</h2><form method="dialog"><button appUI type="submit">Close</button></form></dialog><Button disabled data-ui-dialog-open="example-dialog">Open dialog</Button>
<Dialog id="example-dialog" aria-labelledby="dialog-title"><h2 id="dialog-title">Review</h2><form method="dialog"><Button type="submit">Close</Button></form></Dialog>
<!-- The docs enhancement script calls showModal(). -->import { dialog } from '@visomi-stack/web-frontend-ui';
dialog.classes();