Primitives
08

Field

Labelled text input. The label is wired to the input with a generated id when you do not supply one.

plain markup — no library on the page
rendered by aura-react
rendered by aura-vue
rendered by aura-svelte
built from aura-angular's own class helpers
Lowercase letters and dashes.
We never share this. That is not an email address.
Type to see the controlled value.
Lowercase letters and dashes.
We never share this.That is not an email address.
Type to see the controlled value.
Lowercase letters and dashes.
We never share this. That is not an email address.
Type to see the controlled value.
Lowercase letters and dashes.
We never share this.That is not an email address.
Type to see the controlled value.
Lowercase letters and dashes.
We never share this.That is not an email address.
Type to see the controlled value.

Code

index.html
<div class="aura-stack" style="--aura-dir:column;--aura-gap:var(--space-3);min-width:260px;">
  <div class="aura-field-group">
    <label class="aura-label" for="aura-field-1">Workspace name</label>
    <input id="aura-field-1" class="aura-field" value placeholder="Acme" aria-describedby="aura-field-1-hint">
    <span class="aura-field-hint" id="aura-field-1-hint">Lowercase letters and dashes.</span>
  </div>
  <div class="aura-field-group">
    <label class="aura-label" for="owner">Owner email</label>
    <input id="owner" class="aura-field" value="ann@" aria-invalid="true" aria-describedby="owner-hint owner-error">
    <span class="aura-field-hint" id="owner-hint">We never share this.</span>
    <span class="aura-field-error" id="owner-error">That is not an email address.</span>
  </div>
  <span class="aura-text aura-text--caption aura-text--muted" style="">Type to see the controlled value.</span>
</div>
Demo.tsx
import { useState } from 'react';
import { Field, Stack, Typography } from '@ilomee/aura-react';

export default function Demo() {
  const [name, setName] = useState('');

  return (
    <Stack gap={3} style={{ minWidth: 260 }}>
      <Field
        label="Workspace name"
        value={name}
        onValueChange={setName}
        placeholder="Acme"
        hint="Lowercase letters and dashes."
      />
      {/* Both messages, to show they coexist: a hint is a standing instruction and an error is
          what is wrong now, so hiding the first when the second appears removes the sentence
          that was helping. `id` is pinned only because the stacks are diffed against each
          other — left out, each framework generates its own. */}
      <Field label="Owner email" id="owner" defaultValue="ann@" hint="We never share this." error="That is not an email address." />
      <Typography variant="caption" tone="muted">
        {name ? `Hello, ${name}` : 'Type to see the controlled value.'}
      </Typography>
    </Stack>
  );
}

The generated id comes from useId(), so it is stable across SSR and hydration.

Demo.vue
<script setup lang="ts">
import { ref } from 'vue';
import { Field } from '@ilomee/aura-vue';

const name = ref('');
</script>

<template>
  <Field label="Name" v-model="name" />
</template>

The generated id comes from the framework itself, so it is stable across SSR and hydration.

Demo.svelte
<script lang="ts">
  import { Field } from '@ilomee/aura-svelte';

  let name = $state('');
</script>

<Field label="Name" bind:value={name} />

The generated id comes from the framework itself, so it is stable across SSR and hydration.

Used as aura-field.

demo.component.ts
import { AuraField } from '@ilomee/aura-angular';

@Component({
  standalone: true,
  imports: [AuraField],
  template: `<aura-field label="Name" [(value)]="name"></aura-field>`,
})
export class DemoComponent {
  name = '';
}

The generated id comes from a root-provided counter. Angular builds a fresh root injector per request, so it restarts with each SSR render and agrees with the client.

Props

Plain markup has no props — the classes below are the whole API. The four packages do nothing more than set these same classes for you.
NameTypeDefaultNotes
labelstring
hintstringStanding help under the control, always shown.
errorstringWhat is wrong right now. Sets aria-invalid on the control and adds the message to its aria-describedby, after the hint. No live region: role="alert" announces on mount, so a server-rendered form with three errors would interrupt three times before the reader reached the first field.
valuestringControlled value.
defaultValuestringUncontrolled seed.
onValueChange(value: string) => void
inputClassNamestringClass for the input itself (className targets the wrapper).
…InputHTMLAttributesattrsInputHTMLAttributes<HTMLInputElement>Forwarded to the input.
NameTypeDefaultNotes
labelstring
hintstringStanding help under the control, always shown.
errorstringWhat is wrong right now. Sets aria-invalid on the control and adds the message to its aria-describedby, after the hint. No live region: role="alert" announces on mount, so a server-rendered form with three errors would interrupt three times before the reader reached the first field.
modelValuetwo-waystringUse with v-model.
defaultValuestringUncontrolled seed.
idstring
update:modelValueevent(value: string) => void
…attrsattrsInputHTMLAttributesForwarded to the input.
NameTypeDefaultNotes
labelstring
hintstringStanding help under the control, always shown.
errorstringWhat is wrong right now. Sets aria-invalid on the control and adds the message to its aria-describedby, after the hint. No live region: role="alert" announces on mount, so a server-rendered form with three errors would interrupt three times before the reader reached the first field.
valuetwo-waystring''$bindable — use bind:value.
idstring
…restattrsHTMLInputAttributesForwarded to the input.
NameTypeDefaultNotes
labelstring
hintstringStanding help under the control, always shown.
errorstringWhat is wrong right now. Sets aria-invalid on the control and adds the message to its aria-describedby, after the hint. No live region: role="alert" announces on mount, so a server-rendered form with three errors would interrupt three times before the reader reached the first field.
valuetwo-waystring''Two-way via [(value)].
idstring
valueChangeeventEventEmitter<string>
…attributesattrsHTMLInputElementAttributes set on <aura-field> are moved onto the inner <input>.

Emitted classes

Every framework emits the same classes — that is what makes the four libraries look identical. You can use them directly, without any component library.

ClassRoleNotes
.aura-labelbaseRequired. A modifier does nothing without it.
.aura-fieldbaseRequired. A modifier does nothing without it.
.aura-field-hintbaseRequired. A modifier does nothing without it.
.aura-field-errorbaseRequired. A modifier does nothing without it.

Tokens and rules

components.css
height
var(--control-h)
padding
0 var(--control-px)
border
var(--field-border)
radius
var(--field-radius)
background
var(--surface)
focus
var(--accent) + var(--focus-ring)
invalid
var(--danger-border-hover) + var(--danger) ring
hint / error
500 13px · var(--text-muted) / var(--danger-text)
placeholder
var(--text-faint)
label gap
var(--label-gap)