Components

Input

Inputs take a short line of text. In Flint, an input always lives in a form field with a visible label, optional helper text and an error message.

CSS

For Astro, EJS and plain HTML. These rules read only component tokens.

HTML
<label for="nights">Nights</label>
<input id="nights" class="flint-input" type="text"
  aria-invalid="true" aria-describedby="nights-error" />
<span id="nights-error">Enter a number from 1 to 14.</span>
CSS
.flint-input {
  box-sizing: border-box; width: 100%; height: var(--input-height); padding: 0 var(--space-12);
  border: 1px solid var(--input-border); border-radius: var(--input-radius);
  background: var(--input-bg); color: var(--input-fg); font: 400 var(--font-size-md) / 1.5 var(--font-sans);
}
.flint-input::placeholder { color: var(--input-placeholder); opacity: 1; }
.flint-input:hover { border-color: var(--input-border-hover); }
.flint-input:focus-visible { border-color: var(--input-border-focus); outline: var(--focus-ring-width) solid var(--focus-ring-color); outline-offset: var(--focus-ring-offset); }
.flint-input[aria-invalid="true"] { border-color: var(--input-border-error); }
.flint-input:disabled { background: var(--color-action-disabled-bg); color: var(--color-action-disabled); border-color: var(--color-border-disabled); }

MUI

React (MUI)
import TextField from '@mui/material/TextField';

<TextField label="Nights" error helperText="Enter a number from 1 to 14." />

Known gap

The MUI theme leaves the outlined input edge at MUI's default, about 1.6:1 (under 3:1), and its placeholder is dimmer than Flint's (ASDS-44).

shadcn/ui

The Flint version of the shadcn component. Same API as upstream; every value reads a Flint token.

components/ui/input.jsx
// shadcn/ui Input, restyled to Flint input tokens. Error state follows aria-invalid, as upstream.
// Gap: Flint has no input.disabled tokens yet, so disabled reads the semantic disabled colors.
import { cn } from '../cn';

export function Input({ className, type = 'text', ...props }) {
  return (
    <input
      type={type}
      data-slot="input"
      className={cn(
        'flex h-[var(--input-height)] w-full min-w-0 rounded-[var(--input-radius)] border border-[var(--input-border)] bg-[var(--input-bg)] px-3 text-base text-[var(--input-fg)] placeholder:text-[var(--input-placeholder)] hover:border-[var(--input-border-hover)] outline-none focus-visible:border-[var(--input-border-focus)] focus-visible:[outline:var(--focus-ring-width)_solid_var(--focus-ring-color)] focus-visible:[outline-offset:var(--focus-ring-offset)] aria-[invalid=true]:border-[var(--input-border-error)] disabled:cursor-not-allowed disabled:border-[var(--color-border-disabled)] disabled:bg-[var(--color-action-disabled-bg)] disabled:text-[var(--color-action-disabled)]',
        className,
      )}
      {...props}
    />
  );
}

SwiftUI

SwiftUI
TextField("Nights", text: $nights)
  .flintText(Flint.Typography.bodyMd)
  .padding(.horizontal, Flint.Space.s12)
  .frame(minHeight: Flint.Target.touch)
  .overlay(RoundedRectangle(cornerRadius: Flint.Component.inputRadius)
    .strokeBorder(hasError ? Flint.Component.inputBorderError : Flint.Component.inputBorder))

A ready-made SwiftUI input is moving into the Flint package (ASDS-38). Until then, build it from the component tokens as above.