Skip to content

AI Label

Disclosing that content was generated or assisted by a model, and giving the reader a way to find out how.

Also called AI Badge, AI Slug, Generated by AI — in this system all of them are AI Label.

Live preview

Everything below is the real component. Change the controls, tab through it, and turn on Inspector Mode to read any value off the screen.

Playground
Press it — the explainer is the point
Incident summary

The health check failed in eu-west-2 at 14:32 after the connection pool saturated. The retry budget was exhausted before the circuit opened, so requests queued rather than failing fast. Rolling back to build 4019 restored the service in about eight seconds.

Check before relying on it

The explainer is the point

The mark says something happened; the popover says what. Provenance, review status, and a way to report that it got something wrong.

Press the label to open the explainer.

Review status changes the claim

"AI-generated" and "AI-drafted, reviewed by Ada" say different things about who is accountable. One badge for both misrepresents each of them.

Unreviewed
Incident summary

The health check failed in eu-west-2 at 14:32 after the connection pool saturated. The retry budget was exhausted before the circuit opened, so requests queued rather than failing fast. Rolling back to build 4019 restored the service in about eight seconds.

Check before relying on it
Reviewed
Incident summaryReviewed by Ada

The health check failed in eu-west-2 at 14:32 after the connection pool saturated. The retry budget was exhausted before the circuit opened, so requests queued rather than failing fast. Rolling back to build 4019 restored the service in about eight seconds.

Where it goes

Beside the heading of the region it applies to, not floating in the corner of the page. Its scope should be obvious from its position alone.

Scoped
SummaryAI

Generated paragraph…

Logs

Raw log output…

UnscopedWhich part?
Deployment 4021AI

Generated paragraph…

Raw log output…

One per region, not one per sentence

A label on every generated element becomes wallpaper and stops being read. Disclose at the region level and say so once.

Once
Suggested tagsAI
infrarollbackeu-west-2
Per item
infraAI
rollbackAI
eu-west-2AI

Interaction states

Every state a user can put this component into, rendered side by side. If a state is missing here, it is missing in production too.

AI
Default
AI
Small
AI-generated
Worded
Interactive
Reviewed by Ada
Reviewed
AI draft — unreviewed
Draft
Summary AI
Inline
Written by a model from the deployment logs. Not reviewed by a person.
Explainer
Feedback

Anatomy

Every part, every measurement, and the reason it is that number.

Incident summary

The health check failed in eu-west-2 at 14:32 after the connection pool saturated. The retry budget was exhausted before the circuit opened, so requests queued rather than failing fast. Rolling back to build 4019 restored the service in about eight seconds.

Check before relying on it

A pill carrying a sparkle and a word, pressable, opening an explainer with provenance, review status and a feedback control.

  1. Height22px (18px small)

    Badge scale. It sits beside a heading without competing with it — a disclosure should be visible and quiet at the same time.

  2. Glyph11px sparkle

    The sparkle has become the shared convention across the industry. Inventing a different symbol costs recognition for no gain.

  3. Word"AI" or "AI-generated"

    The glyph alone is not a disclosure. Space permitting, spell it out — "AI-generated" is unambiguous where a sparkle is not.

  4. ToneAccent, not status

    Accent-tinted. Using a status colour would claim the content is good, bad or risky, which the label is not saying.

  5. PressableOpens the explainer

    What turns a mark into a disclosure. A label that cannot be interrogated tells the reader a fact they cannot act on.

  6. ExplainerProvenance + review + feedback

    What the model saw, whether a person checked it, and a way to report that it got something wrong.

  7. PlacementBeside the region heading

    Its scope should be readable from its position. A mark floating in a page corner labels nothing in particular.

Design tokens used

Values are read live from the running stylesheet, so this table can never drift from the code. Click any value to copy it.

Color

TokenValueUsed for
--ds-accent-subtle—Label fill
--ds-accent-border—Label border
--ds-accent-text—Label text and sparkle
--ds-success-subtle—A human-reviewed variant
--ds-warning-subtle—An unreviewed draft, where the risk is worth marking
--ds-surface-overlay—The explainer panel
--ds-fg-secondary—Explainer body text

Spacing

TokenValueUsed for
padding-xLabel padding

Radius

TokenValueUsed for
full—Pill shape, shared with Badge

Typography

TokenValueUsed for
11px / 500—Label text

Recommended sizes

Pick a size from this table. Do not invent a new one — a fourth height is how a design system starts dying.

SizeHeightPaddingIconTypeMin widthMax widthTouch targetWhen to use
Small18px0 6px9px10px———Inline in a table cell or beside a small heading.
Medium22px0 8px11px11px——44px when pressableThe default. Beside a section or card heading.
Explainer————15rem18rem—Provenance, review status and feedback. Short enough to read in one pass.
Region banner————100%——When a whole view is generated, one Banner at the top beats a label per element.

Do

Make the label open an explainerThe mark says something happened. The explainer says what the model saw and whether anyone checked it — which is the part the reader can act on.
AI-generatedAI
Spell it out where there is roomA sparkle alone is not a disclosure. "AI-generated" is unambiguous; a glyph relies on the reader already knowing the convention.
AIReviewed by Ada
Distinguish reviewed from unreviewedThey are different claims about who is accountable. Collapsing them into one badge overstates the unreviewed case and undersells the reviewed one.
Was this useful?
Collect feedback in the explainerThe moment a reader notices something wrong is the moment they will report it. Anywhere else and the report never happens.

Don't

Deploy faster✨ Now with AI
Do not use it as a feature badgeA disclosure mark used for marketing stops being read as a disclosure. Once "AI" means "new feature" in one place, it means nothing anywhere.
infraAI
rollbackAI
eu-west-2AI
Do not label every elementA mark on each of twelve suggested tags is twelve marks nobody reads. Disclose once at the region level and say what it covers.
✨ AI✨ AI
Do not use a status colourGreen claims the content is good and amber claims it is risky. The label is saying who produced it, not whether it is right.
summary text with a hover-only “generated” hint
Do not hide it in a tooltipHover does not exist on touch, and a disclosure that half your users cannot reach is not a disclosure. The mark itself must be visible.

Accessibility

Not a checklist to run at the end. These are the requirements the component was built from.

1.4.1Use of ColorA1.4.3Contrast (Minimum)AA2.1.1KeyboardA2.5.8Target Size (Minimum)AA4.1.2Name, Role, ValueA

Contrast

  • The label text owes 4.5:1 at 11px. It is a disclosure, and small quiet text is exactly where that gets skipped.
  • The word carries the meaning, never the sparkle or the tint alone — colour-only disclosure fails 1.4.1 outright.
  • The border owes 3:1: it is what separates the label from the heading beside it.
  • The reviewed and unreviewed variants must differ by wording as well as colour.

Keyboard

TabReaches the label when it opens an explainer. A static mark is not focusable.
Enter / SpaceOpens the explainer and moves focus into it.
EscCloses it and returns focus to the label.
TabReaches the feedback controls inside the explainer.

Screen readers

  • The disclosure must be announced with the content it applies to, not left as a visual mark beside it. aria-describedby on the region is what does that.
  • Announce the scope: "AI-generated summary" tells the user which part; "AI" tells them nothing.
  • Never rely on the sparkle. It is decorative and aria-hidden; the word is the entire disclosure for a non-visual reader.

Focus & touch

  • A static label is not focusable; a pressable one is a real button that returns focus on close. In a list of generated items, the label must not become a tab stop per row — disclose once for the region instead.
  • A pressable label needs a 44px target, which means padding around a 22px pill rather than a larger pill. Hover-only disclosure does not exist on touch, so the mark itself must always be visible — and on a phone the explainer is usually better as a bottom Drawer than as a floating panel.
AttributeApplied toNotes
aria-labelThe pressable label"AI generated — what does this mean?". A bare "AI" announces two letters with no context.
aria-hiddenThe sparkleDecoration. The word is the disclosure.
aria-haspopup="dialog"The labelWith aria-expanded, so the explainer is discoverable rather than a surprise.
aria-describedbyThe labelled regionPointing at the disclosure, so the provenance is announced with the content rather than only beside it.
role="note"A region-level disclosureFor a banner covering a whole generated view.

Code

Example usage

tsx
1import { AiLabel } from '@/ui/Display'23// The label opens the explainer — that is what makes it a disclosure rather4// than a decoration.5<Row>6  <h3>Incident summary</h3>7  <AiLabel8    provenance="Written from the deployment logs and the linked incident."9    reviewed={summary.reviewedBy}10    onFeedback={(useful) => track('ai_feedback', { id: summary.id, useful })}11  />12</Row>1314// The disclosure must be announced WITH the content, not merely beside it.15<section aria-describedby="ai-disclosure">16  <p id="ai-disclosure" className="sr-only">17    This summary was generated by a language model and has not been reviewed.18  </p>19  <p>{summary.text}</p>20</section>2122// Review status is a different claim about who is accountable.23{summary.reviewedBy ? (24  <Badge tone="success">Reviewed by {summary.reviewedBy}</Badge>25) : (26  <AiLabel />27)}2829// One disclosure per region. Twelve labels on twelve suggested tags is30// twelve marks nobody reads.31<Row>32  <h4>Suggested tags</h4>33  <AiLabel size="sm" />34</Row>35{tags.map((t) => <Badge key={t}>{t}</Badge>)}

Framework-free HTML

html
<div class="ds-section">
  <h3 id="summary-heading">Incident summary</h3>

  <!-- The sparkle is decoration; the word is the disclosure. -->
  <button
    type="button"
    class="ds-ai-label"
    aria-label="AI generated — what does this mean?"
    aria-haspopup="dialog"
    aria-expanded="false"
  >
    <svg aria-hidden="true">…</svg>
    AI
  </button>

  <!-- Announced WITH the content, not merely beside it. -->
  <p id="ai-disclosure" class="sr-only">
    This summary was generated by a language model and has not been
    reviewed by a person.
  </p>

  <p aria-describedby="ai-disclosure">
    The health check failed in eu-west-2 at 14:32…
  </p>
</div>

<div role="dialog" aria-label="AI-generated summary">
  <p>Written by a language model from the deployment logs.</p>
  <button type="button">Useful</button>
  <button type="button">Not useful</button>
</div>

CSS

css
.ds-ai-label {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  block-size: 22px;                  /* badge scale: visible and quiet */
  padding-inline: 8px;
  border: 1px solid var(--ds-accent-border);
  border-radius: 999px;
  /* Accent, never a status colour: green would claim the content is good,
     amber that it is risky. The label says neither. */
  background: var(--ds-accent-subtle);
  color: var(--ds-accent-text);
  font-size: 11px;
  font-weight: 500;
}

.ds-ai-label:focus-visible {
  outline: 2px solid var(--ds-focus-ring);
  outline-offset: 2px;
}

/* Review status is a different claim, so it gets a different mark. */
.ds-ai-label--reviewed {
  border-color: var(--ds-success-border);
  background: var(--ds-success-subtle);
  color: var(--ds-success-text);
}

/* The tint is gone here, so the word and border must carry it alone. */
@media (forced-colors: active) {
  .ds-ai-label { border: 1px solid; }
}

/* Padding, not a bigger pill. */
@media (pointer: coarse) {
  .ds-ai-label { padding-block: 11px; margin-block: -11px; }
}

Component API

AiLabel

PropTypeDefaultDescription
provenance*string—What the model was given and what it produced. This is the disclosure; the pill is the entry point.
reviewedstring | falsefalseThe reviewer’s name. A reviewed item is a different claim and gets a different mark.
textstring'AI'"AI-generated" wherever there is room. A glyph alone is not a disclosure.
size'sm' | 'md''md'Badge scale. Small for inline use in a table cell.
onFeedback(useful: boolean) => void—Collected in the explainer, where the reader already is when they notice a problem.
describesstring—The id of the region it applies to, so the disclosure is announced with the content.

Notes

Professional tips

  • Write the provenance in plain language. "Written from the deployment logs and the linked incident" is a real answer; "powered by advanced AI" is marketing.
  • Keep one mark, one wording, one placement across the whole product. Consistency is what turns a badge into a signal.
  • Link to the sources the model used where you can. Provenance the reader can check is worth far more than provenance they have to take on trust.
  • Record feedback against the specific generation, not the feature. Aggregate thumbs-down tells you nothing about which output was wrong.
  • Revisit the label when a human edits generated content. Once a person has changed it, they are the author, and the mark should reflect that.

Performance

  • Render the label statically and mount the explainer only when it opens. A list of fifty generated rows should not carry fifty hidden popovers.
  • One shared explainer instance re-pointed at the active label is enough — the content differs only by the provenance string.
  • Do not animate the sparkle. A permanently shimmering disclosure reads as decoration, which is exactly what it must not be.

Common mistakes

  • Using the mark to advertise a feature, which destroys its meaning as a disclosure.
  • A sparkle with no word, relying on a convention the reader may not know.
  • A label per element instead of one per region.
  • A status colour, claiming the content is good or risky.
  • Hover-only disclosure, invisible on touch.
  • No explainer, so the reader learns something happened but not what.
  • Not distinguishing reviewed from unreviewed content.
  • The disclosure visible but never announced, leaving screen-reader users unaware.

Real-world recommendations

  • Disclosure requirements are tightening in several jurisdictions. Building the mark and the provenance record now is far cheaper than retrofitting them across a product later.
  • Users calibrate quickly once a product is consistent: they learn the mark, learn what it predicts about quality, and adjust their trust accordingly. That is the mechanism working.
  • Over-labelling is the more common failure. A product that marks every ranked list and every autocomplete has trained its users to ignore the mark by the time it matters.
  • The feedback control in the explainer is the highest-signal quality data most teams have. It arrives at the moment the reader noticed the problem, attached to the exact output.