Skip to content
KONIGI Patterns

AI Assistants / Help within apps / AI entry point

1 of 5 ›

AI entry point

People need to find the AI feature and understand what it can do.

Updated September 12, 2026

Problem

People may miss an AI feature if they can’t find it or tell what it does. It needs to fit into the app without getting in the way of tools they already use.

Solution

Put the AI button near the content it works on. Show a rewrite option when someone selects text. Put a document summary button in the document header. This placement helps people understand what the button does.

Label the button with an action, such as “Rewrite” or “Summarize.” A sparkle icon alone doesn’t explain what will happen. If there’s no room for a label, provide a tooltip and a clear name for screen readers.

Choose when the button appears based on the task. An option that appears when someone selects text keeps the toolbar clear. A permanent button is easier to find when people need the assistant throughout the app.

Show suggestions when they’re relevant to what someone is doing. Let people dismiss them.

Use when

AI helps people complete a task within an existing app.

Don’t use when

The assistant is the product. There the entry point is the whole screen, and a sparkle is decoration on a surface that’s nothing to compete with.

Trade-offs

Buttons that appear only in certain situations save space, but people may miss them. A permanent button is easier to find but takes up toolbar space even when it isn’t needed. Automatic suggestions can help people discover a feature, but they can also interrupt their work.

Checklist

  • Is the entry point next to the object it acts on?
  • Does it carry a verb, or only an icon?
  • What’s its accessible name, and does it describe the action?
  • Does it appear unprompted, and on what signal?
  • Can it be dismissed, and does the dismissal stick?
  • What permanent space does it occupy, and what did that space cost?
  • Is there a keyboard path for people who never use the button?
  • Does it appear in contexts where the assistant cannot help?
  • Does it look the same across the product when it does different things?
  • Can someone who does not want it turn it off?

Compare

Notion puts the entry at the cursor and on selection rather than in the chrome, so invocation happens where the writing is and no toolbar slot is spent. Figma attaches its equivalent to the canvas selection, where the object is a frame and the available actions follow from what is selected. Microsoft Copilot takes the opposite approach with a persistent ribbon presence across applications, buying consistency and constant visibility at the price of a permanent slot in the most contested toolbar in software. Raycast removes the surface entirely and makes the entry point a global keystroke. For anyone who learns it that’s the cheapest invocation there is. For everyone else it may as well not exist.

Inline assist lets people work with AI directly in their content. An assistant sidebar provides space for a longer conversation. A command menu gives people a keyboard shortcut to AI actions.

Prompt starters help people decide what to ask after opening the assistant. Ghost text shows suggestions as they type, without requiring them to open it.

AI entry point anatomy Three placements compared: a control attached to a text selection, one in a document header, and a permanent button in the global toolbar, with the sparkle icon shown alone and again paired with a verb. Next to the object, or nowhere in particular File Edit View AI Q3 review summarise rewrite this the icon alone says that something is AI, not what it does a permanent button spends the most contested space in the product 1 2 3 4 1 AT THE SELECTION Proximity does the explaining that an icon cannot, and spends no toolbar slot. 2 AT THE DOCUMENT For actions on the whole thing, where the object is the page rather than a passage. 3 IN THE CHROME Always findable, always slightly in the way, and it implies one uniform behaviour. 4 PAIR THE ICON WITH A VERB The sparkle became a genre marker in two years and stopped carrying meaning. Contextual entry points are found at the moment of need and never learned the rest of the time.
Wireframe — the pattern's anatomy, not any one product's version of it

Implementation

A button that sits next to the object it acts on and pairs the sparkle with a verb. The verb and the object are required props, because the icon alone says that something is AI without saying what it does, and the accessible name has to describe the action rather than the brand.

shadcn
npx shadcn@latest add button
npm
lucide-react
Tokens
--card--card-foreground--muted-foreground--border--input--chart-1
FileEditView

Q3 review

Revenue for the quarter came in at £1.84m, three percent ahead of plan, with services carrying most of the beat. Costs were higher than we had budgeted for on account of the fact that hiring ran ahead of the plan in the second half of the quarter. Cash at the end of the period stood at £6.2m.

AiEntryPoint.tsxSparkle plus verb, an accessible name built from the verb and its object, and a placement that marks a selection-attached control as belonging to the passage.

import { Sparkle } from "lucide-react";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";

/**
 * An entry point is a button that sits next to the thing it acts on and says
 * what it does. Both halves are props the caller cannot leave out. `verb`,
 * because the sparkle became a genre marker in about two years and now says
 * that something is AI rather than what it does. `object`, because the
 * accessible name has to describe the action on the thing, and a screen
 * reader hearing the product's name learns nothing.
 *
 * Where it goes is the caller's job, and the point: at the selection for a
 * passage, in the header for the document, beside the table for the data.
 * A permanent slot in the global toolbar is the one placement this component
 * does not offer a style for.
 */
export type Placement = "document" | "selection";

type Props = {
  /** What pressing it does, as an imperative: "summarise", "rewrite this". */
  verb: string;
  /** What it acts on. Only the accessible name carries it; the button beside
   *  the object does not need to repeat what the eye can see. */
  object: string;
  /** "document" waits quietly in the header. "selection" rode in on a signal
   *  the viewer made, so it is marked as belonging to the passage. */
  placement: Placement;
  onInvoke: () => void;
  /** The keyboard path, for people who never reach for the button. */
  shortcut?: string;
};

export function AiEntryPoint({ verb, object, placement, onInvoke, shortcut }: Props) {
  const name = `${verb}: ${object}`;
  return (
    <Button
      variant="outline"
      size="sm"
      onClick={onInvoke}
      aria-label={name}
      aria-keyshortcuts={shortcut}
      title={shortcut ? `${name} (${shortcut})` : name}
      className={cn(
        "h-7 gap-1.5 px-2.5 text-[11px] font-normal",
        placement === "selection" && "border-chart-1 text-chart-1 hover:text-chart-1",
      )}
    >
      <Sparkle className="!size-3 fill-chart-1 text-chart-1" aria-hidden="true" />
      {verb}
    </Button>
  );
}

demo.tsxHow it is called: summarise in the document header, rewrite this at a selected sentence. Rewriting replaces the sentence and takes the control away with the selection.

import { useState } from "react";
import { AiEntryPoint } from "./AiEntryPoint";

/**
 * A document with two entry points, each next to its object. "summarise" waits
 * in the header because its object is the whole page. "rewrite this" appeared
 * because a sentence was selected, and goes away with the selection.
 */
const BEFORE = "Revenue for the quarter came in at £1.84m, three percent ahead of plan, with services carrying most of the beat. ";
const SELECTED = "Costs were higher than we had budgeted for on account of the fact that hiring ran ahead of the plan in the second half of the quarter.";
const AFTER = " Cash at the end of the period stood at £6.2m.";
const REWRITTEN = "Costs ran over budget because hiring outpaced the plan in the second half.";

export default function Demo() {
  const [selected, setSelected] = useState(true);
  const [sentence, setSentence] = useState(SELECTED);
  const [summary, setSummary] = useState<string>();

  const rewrite = () => {
    setSentence(REWRITTEN);
    setSelected(false);
  };

  return (
    <div className="rounded-lg border bg-card">
      <div className="flex gap-5 border-b px-4 py-2.5 text-[11px] text-muted-foreground">
        <span>File</span><span>Edit</span><span>View</span>
      </div>

      <div className="p-4">
        <div className="flex items-center gap-3">
          <h2 className="text-sm font-medium text-card-foreground">Q3 review</h2>
          <AiEntryPoint
            verb="summarise"
            object="Q3 review"
            placement="document"
            shortcut="Meta+J"
            onInvoke={() => setSummary("Revenue £1.84m, 3% over plan. Costs over budget on hiring. Cash £6.2m.")}
          />
        </div>
        {summary && <p className="mt-2 text-xs text-muted-foreground">{summary}</p>}

        <p className="mt-4 text-sm leading-relaxed text-card-foreground">
          {BEFORE}
          <span
            className={selected ? "bg-chart-1/20 text-card-foreground" : undefined}
            onMouseUp={() => setSelected(true)}
          >
            {sentence}
          </span>
          {AFTER}
        </p>

        {selected && (
          <div className="mt-2 flex justify-end">
            <AiEntryPoint
              verb="rewrite this"
              object="the selected sentence"
              placement="selection"
              onInvoke={rewrite}
            />
          </div>
        )}
      </div>
    </div>
  );
}
What it renders. Identical markup in both panes, with only the token values changing.

Examples

No screenshots yet for this pattern. Browse Products to see other examples.