Feedback

First Run

A first run where the emptiness is not missing data but work not yet started: three numbered steps, the current one highlighted, one action.

  • empty
  • onboarding
  • steps
  • first run

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/empty-005?lang=en

Three steps to start

Готово 0 из 3

  1. Подключите репозиторийGitHub или GitLab — доступ можно отозвать в любой момент
  2. Проверьте команду сборкиОпределится сама, менять её обычно не нужно
  3. Опубликуйте первый разАдрес выдаётся сразу, свой домен подключается позже
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 "empty-005" (First Run) 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/empty-005.json

Registry item: https://vibeui.ru/r/empty-005.json
Installs to: components/vibeui/empty-005.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
A first run where the emptiness is not missing data but work not yet started: three numbered steps, the current one highlighted, one action.

A first-run empty state: a heading, a readiness counter, three numbered steps with explanations and one button that starts the first step. Zero dependencies, one file, its own palette.

## 3. How to use it
import { Empty005 } from "@/components/vibeui/empty-005"

<Empty005 title="Three steps to start" steps={steps} actionLabel="Connect a repository" onAction={connect} />

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-empty-005-* palette — do not swap it for your theme tokens
- a numbered ol rather than a set of cards: the order of the steps is the meaning, not the decoration
- highlighting the current step: without it nothing says where to begin
- the line between the numbers — it shows the steps run in sequence rather than being picked
- one button for the whole screen: it starts the first step, the rest wait their turn
- the readiness counter: it promises an end and shows how much work there is

## 6. You may change
- title — the empty state heading
- the steps array: the step heading and the explanation under it
- actionLabel — the wording of the first-step button
- the onAction handler — starting the first step
- the accent through the accent prop — it colours the current number and the button

## 7. Rules
- More than three or four steps on the first screen scares people off: show the rest after the first success.
- Progress is not computed here: the current step and the counter come from the caller.
- Do not show this screen to an experienced user: after the first project it is useless.
- 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/empty-005.json
https://vibeui.ru/r/empty-005.json

Компонент самодостаточен: один файл, без зависимостей, собственная палитра в локальных переменных --vibeui-empty-005-*. Серверный: хуков нет. Шаги — ol с номерами в кружках; соединительная линия нарисована псевдоэлементом у всех элементов, кроме последнего, поэтому лишний хвост под последним номером не появляется. Текущий шаг помечен data-current, остальные приглушены цветом подписи.

Component source

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

import type { ComponentPropsWithoutRef, CSSProperties } from "react"

export type Empty005Step = {
  title: string
  hint: string
}

export type Empty005Props = Omit<
  ComponentPropsWithoutRef<"div">,
  "children" | "title"
> & {
  title?: string
  steps?: Empty005Step[]
  actionLabel?: string
  onAction?: () => void
  accent?: string
}

// Идея компонента: первый запуск, где пусто не потому, что данных нет, а
// потому, что работа ещё не начата. Поэтому здесь не картинка с подписью, а
// три шага с нумерацией: первый выделен как текущий, остальные приглушены —
// видно, сколько всего работы. Кнопка ровно одна и запускает первый шаг.
const STYLES = `
:where([data-vibeui-block="empty-005"]){
--vibeui-empty-005-bg:oklch(1 0 0);
--vibeui-empty-005-fg:oklch(0.21 0.014 265);
--vibeui-empty-005-muted:oklch(0.55 0.014 265);
--vibeui-empty-005-border:oklch(0.91 0.006 265);
--vibeui-empty-005-accent:oklch(0.55 0.17 265);
--vibeui-empty-005-font:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
}
[data-vibeui-block="empty-005"]{
display:flex;flex-direction:column;gap:0.75rem;
width:100%;max-width:24rem;box-sizing:border-box;padding:1.5rem 1.375rem;
background:var(--vibeui-empty-005-bg);
border:1px solid var(--vibeui-empty-005-border);border-radius:1rem;
font-family:var(--vibeui-empty-005-font);color:var(--vibeui-empty-005-fg);
}
[data-vibeui-block="empty-005"] [data-part="head"]{display:flex;flex-direction:column;gap:0.25rem}
[data-vibeui-block="empty-005"] [data-part="title"]{margin:0;font-size:1.0625rem;font-weight:700;line-height:1.25}
[data-vibeui-block="empty-005"] [data-part="progress"]{
margin:0;font-size:0.75rem;font-weight:650;color:var(--vibeui-empty-005-muted);
}
[data-vibeui-block="empty-005"] [data-part="steps"]{list-style:none;margin:0;padding:0}
/* Линия между номерами показывает, что шаги идут подряд, а не вразнобой. */
[data-vibeui-block="empty-005"] [data-part="step"]{
position:relative;display:flex;gap:0.75rem;padding-bottom:0.875rem;
}
[data-vibeui-block="empty-005"] [data-part="step"]:last-child{padding-bottom:0}
[data-vibeui-block="empty-005"] [data-part="step"]:not(:last-child)::before{
content:"";position:absolute;left:0.8125rem;top:1.875rem;bottom:0.25rem;
width:1.5px;background:var(--vibeui-empty-005-border);
}
[data-vibeui-block="empty-005"] [data-part="number"]{
flex:none;display:flex;align-items:center;justify-content:center;
width:1.625rem;height:1.625rem;border-radius:9999px;
border:1.5px solid var(--vibeui-empty-005-border);
background:var(--vibeui-empty-005-bg);
font-size:0.75rem;font-weight:700;color:var(--vibeui-empty-005-muted);
}
[data-vibeui-block="empty-005"] [data-part="step"][data-current="true"] [data-part="number"]{
border-color:transparent;background:var(--vibeui-empty-005-accent);color:oklch(0.99 0.01 265);
}
[data-vibeui-block="empty-005"] [data-part="body"]{display:flex;flex-direction:column;gap:0.125rem;padding-top:0.125rem}
[data-vibeui-block="empty-005"] [data-part="name"]{font-size:0.875rem;font-weight:650;line-height:1.3}
[data-vibeui-block="empty-005"] [data-part="hint"]{font-size:0.75rem;line-height:1.4;color:var(--vibeui-empty-005-muted)}
[data-vibeui-block="empty-005"] [data-part="step"]:not([data-current="true"]) [data-part="name"]{color:var(--vibeui-empty-005-muted)}
[data-vibeui-block="empty-005"] [data-part="action"]{
appearance:none;border:0;cursor:pointer;width:100%;
height:2.625rem;border-radius:0.75rem;
background:var(--vibeui-empty-005-accent);color:oklch(0.99 0.01 265);
font:inherit;font-size:0.9375rem;font-weight:650;
}
[data-vibeui-block="empty-005"] [data-part="action"]:focus-visible{outline:2px solid var(--vibeui-empty-005-accent);outline-offset:2px}
@media (prefers-reduced-motion:reduce){[data-vibeui-block="empty-005"] *{animation:none!important;transition:none!important}}
`

const DEFAULT_STEPS: Empty005Step[] = [
  {
    title: "Подключите репозиторий",
    hint: "GitHub или GitLab — доступ можно отозвать в любой момент",
  },
  {
    title: "Проверьте команду сборки",
    hint: "Определится сама, менять её обычно не нужно",
  },
  {
    title: "Опубликуйте первый раз",
    hint: "Адрес выдаётся сразу, свой домен подключается позже",
  },
]

/**
 * Первый запуск в три шага: текущий выделен, действие одно.
 * Один файл, ноль зависимостей, собственная палитра.
 */
export function Empty005({
  title = "Начнём с трёх шагов",
  steps = DEFAULT_STEPS,
  actionLabel = "Подключить репозиторий",
  onAction,
  accent,
  className,
  style,
  ...props
}: Empty005Props) {
  const palette = {
    ...(accent ? { "--vibeui-empty-005-accent": accent } : null),
    ...style,
  } as CSSProperties

  return (
    <>
      <style href="vibeui-empty-005" precedence="medium">
        {STYLES}
      </style>
      <div
        {...props}
        data-vibeui-block="empty-005"
        className={className}
        style={palette}
      >
        <div data-part="head">
          <h3 data-part="title">{title}</h3>
          <p data-part="progress">Готово 0 из {steps.length}</p>
        </div>
        <ol data-part="steps">
          {steps.map((step, index) => (
            <li key={step.title} data-part="step" data-current={index === 0}>
              <span data-part="number" aria-hidden="true">
                {index + 1}
              </span>
              <span data-part="body">
                <span data-part="name">{step.title}</span>
                <span data-part="hint">{step.hint}</span>
              </span>
            </li>
          ))}
        </ol>
        <button type="button" data-part="action" onClick={onAction}>
          {actionLabel}
        </button>
      </div>
    </>
  )
}