Feedback

Inline Help

Help inside a line of text: unlike a tooltip you can enter it with the mouse and with Tab — there is a link to the documentation in there.

  • popover
  • help
  • inline
  • link

Preview

1440pxHost theme

Use it with AI

  1. 1. Copy the link.
  2. 2. Write to your agent in your own words and drop the link into the sentence.
  3. 3. The agent opens the link and installs the component from the registry.

put this in the header: https://vibeui.ru/c/popover-006?lang=en

Первый ответ после простоя приходит медленнее — это Что такое холодный стартПервый запрос после простоя поднимает контейнер с нуля: он идёт на 300–800 мс дольше обычного. Дальше отвечает уже прогретый экземпляр.How to avoid it, и он проходит сам через минуту работы.

Show the full instructions

What the link says, spelled out. Use it when your agent cannot open links — paste this text instead.

# Install and place "popover-006" (Inline Help) from VibeUI

## 1. Install first — do not skip, do not recreate
Run this exact command before writing any code:
npx shadcn@latest add https://vibeui.ru/r/popover-006.json

Registry item: https://vibeui.ru/r/popover-006.json
Installs to: components/vibeui/popover-006.tsx (the exact path follows this project's components.json aliases).
npm dependencies: none.
Registry dependencies: none.

Install it from the registry. Do not recreate it from the description,
do not substitute a similar component from another library, and do not
rewrite it to match the project's existing style.

## 2. What it is
Help inside a line of text: unlike a tooltip you can enter it with the mouse and with Tab — there is a link to the documentation in there.

An inline help popover: an explanation and a documentation link inside. Zero dependencies, one file, the browser owns the state.

## 3. How to use it
import { Popover006 } from "@/components/vibeui/popover-006"

<Popover006
  term="cold start"
  title="What a cold start is"
  linkLabel="How to avoid it"
  href="/docs/cold-start"
/>

Read the installed file for the full prop list.

## 4. Where to place it
This is a small inline component. Put it exactly where the user asked,
inside the existing markup. Do not create a new page, section or
wrapper for it. If a similar control already sits in that spot,
replace it instead of adding a second one.

Placement: ___
(The user fills this line in. If it is still blank, ask where to put it
instead of guessing.)

## 5. Keep exactly as installed
- the local --vibeui-popover-006-* palette — do not swap it for your theme tokens
- the panel layout only inside the :popover-open rule — display in the plain rule overrides the browser's display:none and the panel stays open forever
- a popover rather than a tooltip: there is a link inside, and a tooltip cannot be reached by the pointer
- the inline elements inside the card — block tags inside a paragraph break the markup
- the button as the trigger: a span with a handler cannot be activated from the keyboard
- the paragraph's own light surface: without it the dark text disappears on a dark background

## 6. You may change
- the word through term, the heading through title and the explanation through text
- the link caption through linkLabel and the target through href
- the copy around the term directly in the markup
- the accent through the --vibeui-popover-006-accent variable

## 7. Rules
- The card does not close when the pointer leaves — deliberately: otherwise the link is unreachable.
- If the term wraps to the next line, the card anchors to the first fragment of the word.
- Escape and outside clicks close the card on their own: no custom close handler is needed.
- Do not lift the CSS variables into globals.css: the component has to stay a single file.

## 8. Verify
- it renders with no console errors;
- it looks like the preview on the VibeUI page you copied this from;
- if it does not, you changed something listed in section 5 — put it back.

For developers

npx shadcn@latest add https://vibeui.ru/r/popover-006.json
https://vibeui.ru/r/popover-006.json

Компонент самодостаточен: один файл, без зависимостей, собственная палитра в локальных переменных --vibeui-popover-006-*. Серверный: карточка на HTML popover, идентификатор разводит useId. Раскладка объявлена только в :popover-open. Карточка сделана строчным элементом со свойством popover, поэтому она остаётся допустимым содержимым абзаца; заголовок и текст внутри — тоже строчные с display:block. Позиционирование через anchor positioning с откатом под @supports not. Триггер — кнопка, стилизованная под слово в тексте.

Component source

The same file your agent installs. Here in case you would rather copy it by hand.

import { useId } from "react"
import type { ComponentPropsWithoutRef, CSSProperties } from "react"

export type Popover006Props = Omit<
  ComponentPropsWithoutRef<"div">,
  "children" | "title"
> & {
  /** Слово в тексте, к которому цепляется справка. */
  term?: string
  title?: string
  text?: string
  linkLabel?: string
  href?: string
}

// Идея компонента: справка внутри строки текста. От подсказки отличается тем,
// что внутрь можно войти мышью и Tab — там живёт ссылка на документацию.
// Поэтому это popover, а не tooltip: закрытие по Escape и клику вне, не по уходу.
const STYLES = `
:where([data-vibeui-block="popover-006"]){
--vibeui-popover-006-bg:oklch(1 0 0);
--vibeui-popover-006-fg:oklch(0.23 0.014 265);
--vibeui-popover-006-muted:oklch(0.53 0.014 265);
--vibeui-popover-006-border:oklch(0.89 0.006 265);
--vibeui-popover-006-accent:oklch(0.52 0.16 250);
--vibeui-popover-006-soft:oklch(0.96 0.02 250);
--vibeui-popover-006-font:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
}
[data-vibeui-block="popover-006"]{
display:inline-block;box-sizing:border-box;max-width:26rem;
padding:0.875rem 1rem;
border:1px solid var(--vibeui-popover-006-border);border-radius:0.875rem;
background:var(--vibeui-popover-006-bg);
font-family:var(--vibeui-popover-006-font);color:var(--vibeui-popover-006-fg);
}
[data-vibeui-block="popover-006"] [data-part="line"]{margin:0;font-size:0.875rem;line-height:1.7}
/* Справка цепляется к слову в строке, а не к абзацу целиком. */
[data-vibeui-block="popover-006"] [data-part="host"]{position:relative;display:inline-block}
[data-vibeui-block="popover-006"] [data-part="trigger"]{
appearance:none;cursor:pointer;border:0;background:transparent;
display:inline;padding:0;
color:var(--vibeui-popover-006-accent);font:inherit;font-weight:620;
text-decoration:underline;text-decoration-style:dotted;text-underline-offset:0.2em;
anchor-name:--vibeui-popover-006-anchor;
}
[data-vibeui-block="popover-006"] [data-part="trigger"]::after{
content:"?";display:inline-flex;align-items:center;justify-content:center;
width:0.9375rem;height:0.9375rem;margin-left:0.25rem;vertical-align:0.05em;
border-radius:9999px;background:var(--vibeui-popover-006-soft);
color:var(--vibeui-popover-006-accent);
font-size:0.625rem;font-weight:800;text-decoration:none;
}
[data-vibeui-block="popover-006"] [data-part="trigger"]:focus-visible{outline:2px solid var(--vibeui-popover-006-accent);outline-offset:2px;border-radius:0.25rem}
/* Раскладка карточки только в :popover-open — display в обычном правиле
   отменил бы браузерный display:none и справка висела бы поверх текста. */
[data-vibeui-block="popover-006"] [data-part="card"]{
position:fixed;margin:0;padding:0.875rem;
width:min(18rem,100vw - 2rem);box-sizing:border-box;
border:1px solid var(--vibeui-popover-006-border);border-radius:0.875rem;
background:var(--vibeui-popover-006-bg);color:inherit;
box-shadow:0 24px 52px -30px oklch(0.2 0.02 265 / 60%);
position-anchor:--vibeui-popover-006-anchor;
top:anchor(bottom);left:anchor(left);margin-top:0.5rem;
}
[data-vibeui-block="popover-006"] [data-part="card"]:popover-open{display:flex;flex-direction:column;gap:0.5rem}
@supports not (anchor-name: --a){
[data-vibeui-block="popover-006"] [data-part="card"]{position:absolute;inset:auto;top:calc(100% + 0.5rem);left:0}
}
[data-vibeui-block="popover-006"] [data-part="title"]{display:block;margin:0;font-size:0.875rem;font-weight:660;line-height:1.3}
[data-vibeui-block="popover-006"] [data-part="text"]{display:block;margin:0;font-size:0.8125rem;line-height:1.5;color:var(--vibeui-popover-006-muted)}
[data-vibeui-block="popover-006"] [data-part="link"]{
display:inline-flex;align-items:center;gap:0.3125rem;align-self:flex-start;
color:var(--vibeui-popover-006-accent);font-size:0.8125rem;font-weight:650;
text-decoration:none;border-radius:0.25rem;
}
[data-vibeui-block="popover-006"] [data-part="link"]:hover{text-decoration:underline;text-underline-offset:0.2em}
[data-vibeui-block="popover-006"] [data-part="link"]:focus-visible{outline:2px solid var(--vibeui-popover-006-accent);outline-offset:2px}
@media (prefers-reduced-motion:reduce){[data-vibeui-block="popover-006"] *{animation:none!important;transition:none!important}}
`

/**
 * Поповер справки в строке текста: внутри объяснение и ссылка на документацию.
 * Один файл, ноль зависимостей, собственная палитра.
 */
export function Popover006({
  term = "холодный старт",
  title = "Что такое холодный старт",
  text = "Первый запрос после простоя поднимает контейнер с нуля: он идёт на 300–800 мс дольше обычного. Дальше отвечает уже прогретый экземпляр.",
  linkLabel = "Как его избежать",
  href = "#docs",
  className,
  style,
  ...props
}: Popover006Props) {
  const id = useId().replace(/:/g, "")

  return (
    <>
      <style href="vibeui-popover-006" precedence="medium">
        {STYLES}
      </style>
      <div
        {...props}
        data-vibeui-block="popover-006"
        className={className}
        style={style as CSSProperties}
      >
        <p data-part="line">
          Первый ответ после простоя приходит медленнее — это{" "}
          <span data-part="host">
            <button
              type="button"
              data-part="trigger"
              popoverTarget={`${id}-card`}
              aria-label={`Справка: ${term}`}
            >
              {term}
            </button>
            <span
              data-part="card"
              id={`${id}-card`}
              popover="auto"
              aria-label={title}
            >
              <span data-part="title">{title}</span>
              <span data-part="text">{text}</span>
              <a data-part="link" href={href}>
                {linkLabel}
                <span aria-hidden="true">→</span>
              </a>
            </span>
          </span>
          , и он проходит сам через минуту работы.
        </p>
      </div>
    </>
  )
}