ComponentsFeedback

Inline message

One short line next to the control it is about: a field, or a table cell. The smallest of three levels, under the section message and the banner.

Playground

Change the controls to try each prop. The code under the preview updates as you go and lists only the props you changed; copy it into your page.

import { InlineMessage } from '@/ui/inline-message';<InlineMessage>  Add the domain, like sara@halcyon.com</InlineMessage>

Under a field

An error shows on blur or submit, never while typing, and also turns the field's edge red. A confirmation shows only after a server check, such as a free workspace URL, and leaves the edge alone. Point the field at the message with aria-describedby.

Available
import { InlineMessage } from '@/ui/inline-message';

// The field here is a plain input; in a form it is the Form page's Field.
const input =
  'h-7 w-full rounded-large bg-surface px-100 text-body text-text shadow-[inset_0_0_0_1px_var(--color-border-input)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-solid focus-visible:outline-border-focused aria-invalid:shadow-[inset_0_0_0_1px_var(--color-danger)]';

export default function InlineMessageField() {
  return (
    <div className="flex flex-wrap gap-400">
      <div className="flex w-70 flex-col gap-075">
        <label htmlFor="client-email" className="text-body-small leading-body-small font-medium">
          Client email
        </label>
        <input id="client-email" className={input} defaultValue="sara@halcyon" aria-invalid="true" aria-describedby="client-email-message" />
        <InlineMessage id="client-email-message">Add the domain, like sara@halcyon.com</InlineMessage>
      </div>
      <div className="flex w-70 flex-col gap-075">
        <label htmlFor="workspace-url" className="text-body-small leading-body-small font-medium">
          Workspace URL
        </label>
        <input id="workspace-url" className={input} defaultValue="northbridge" aria-describedby="workspace-url-message" />
        <InlineMessage id="workspace-url-message" appearance="confirmation">
          Available
        </InlineMessage>
      </div>
    </div>
  );
}

Under a table cell

A cell has no room below it, so the message floats as a small card 4px under the cell, which keeps its 2px red edge. Near the bottom of the table, pass placement="above".

maya.chen@
import { InlineMessage } from '@/ui/inline-message';

// A table cell has no room below it, so the message floats 4px under the cell.
export default function InlineMessageCell() {
  return (
    <div className="pb-14">
      <div className="relative flex h-9 w-60 items-center px-150 text-body font-medium shadow-[inset_0_0_0_2px_var(--color-danger)]">
        maya.chen@
        <InlineMessage placement="below">Enter a full email address</InlineMessage>
      </div>
    </div>
  );
}

Icon button

InlineMessageButton puts a short explanation behind a 24px icon next to a column name or heading. Hover shows the title; a click or Enter opens the detail in a popup, and Escape closes it.

Match
Last contacted
import { InlineMessageButton } from '@/ui/inline-message';

export default function InlineMessageButtonExample() {
  return (
    <div className="flex items-center gap-300">
      <div className="flex items-center gap-050 text-body font-medium text-text-subtle">
        Match
        <InlineMessageButton
          title="How Match is worked out"
          secondaryText="Skills, seniority and location against the Job's must-haves. 100 means every must-have is met."
        />
      </div>
      <div className="flex items-center gap-050 text-body font-medium text-text-subtle">
        Last contacted
        <InlineMessageButton
          appearance="warning"
          title="Some dates are missing"
          secondaryText="Calls logged before you connected your calendar have no date."
        />
      </div>
    </div>
  );
}

On this page