Skip to content
AI

Entry points

Where an assistant lives, and how a person starts one without spending a model call by accident.

The side panel

The work surface

Stays live and stays visible. Nothing is dimmed, nothing is trapped.

A region, not a dialog — role=complementary, no focus trap, no scrim, no inert background. A person is meant to click a parcel while it is open, which is the whole point. GdDialog's own rule says a map app cannot afford to bury the map; an assistant is the strongest case of that rule, not an exception to it.
Code
<GdAiPanel
  scope="Reads this project's four layers and Terra's toolbox. It cannot see the map."
  @close="open = false"
>
  <GdAiThread :revision="rev"> … </GdAiThread>
  <template #composer>
    <GdAiComposer v-model="draft" @send="ask" />
  </template>
</GdAiPanel>

In a button

Drawn as a quiet outline rather than a filled accent: an assistant is offered, not demanded, and a filled indigo pill beside a filled indigo “Assess” would make the two look equally like the thing you came to do. The mark is the caller's — an icon button already holds one glyph, and a second would be two marks in a 28px square.
Code
<!-- the mark goes in #leading, never the default slot -->
<GdButton variant="ai">
  <template #leading><GdAiMark /></template>
  Ask GRIDD AI
</GdButton>

<!-- an ICON button has no label, so the default slot is right -->
<GdButton variant="ai" icon size="sm" label="Ask about this lot">
  <GdAiMark />
</GdButton>

Any control that will spend a model call carries the mark. That is the rule, and it is about cost and consent rather than branding: a generation takes seconds and money, and a person is entitled to know which button starts one.

Inline and empty states

Ask about this project

It reads your layers and Terra's toolbox. It cannot see the map, and it will say so rather than guess.

Terra's self-knowledge is COMPILED from the toolbox, the shelf and the vocabulary, so the product already knows what it can do. The empty state is where that gets said — as real questions, not as feature names.
Code
<GdAiThread>
  <template #empty>
    <GdEmptyState title="Ask about this project" …>
      <GdButton variant="ai" size="sm" v-for="q in SUGGESTED">…</GdButton>
    </GdEmptyState>
  </template>
</GdAiThread>

API

GdAiPanel

Props

PropTypeDefault
titlestring"GRIDD AI"

The panel's name, in the header and as its accessible name.

scopestring—

One line saying what this assistant can read. The honest replacement for a disclaimer — see Why this way.

generatingboolean—

A model is producing an answer somewhere in the thread.

Slots

default

The body — normally a GdAiThread, which is also the container the contents adapt to.

composer

Pinned below the body. Separate from the default slot so the thread scrolls and the composer does not.

tools

Header controls left of the close button — a history picker, a model badge, a clear action.

The panel does not own where it sits, how wide it is, or whether it is open. One that positioned itself would fight GdSidePanel on the map and the rail in Terra, which are different frames with different rules. It is a column that fills what it is given.

Behavior & Anatomy

Scope beats disclaimer

"May produce inaccurate information" tells a planner nothing they can act on. "Reads this project's layers and Terra's toolbox — it cannot see the map" tells them exactly which questions are worth asking and which are not, which is the same information stated usefully. So the panel takes a scope line, in the header, permanently — not a dismissible banner that is gone by the second session.

A variant, not a GdAiButton

This system has one button and a list of things it can look like, and adding to that list is cheaper than adding to the component count: everything a button already is — the element, the size ladder, the focus ring, the loading swap, the icon slot — would have to be rebuilt by a parallel component to change a colour and add a glyph.

Navigate

Esc