Accordion

Borderless Accordion

A borderless accordion: rows and hairlines, nothing else. It does not read as a box dropped on the page, which makes it right for a list of questions inside running text.

  • accordion
  • faq
  • minimal
  • no-js

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/accordion-003?lang=en

Сколько времени занимает подключение?

Полчаса на первый проект: домен подключается за пять минут, остальное — наполнение страниц. Переносить существующий сайт дольше, обычно день.

Что будет с сайтом, если я перестану платить?

Сайт остаётся опубликованным до конца оплаченного периода, дальше переходит в режим только для чтения. Исходники ваши и никуда не деваются.

Можно ли работать вдвоём над одним проектом?

Да, участники приглашаются по почте и получают роль редактора или читателя. Одновременное редактирование одной страницы не блокируется.

Есть ли ограничение по трафику?

Мягкое: до ста тысяч просмотров в месяц включено, дальше предупредим и предложим перейти на следующий тариф. Сайт при этом не выключается.

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 "accordion-003" (Borderless Accordion) 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/accordion-003.json

Registry item: https://vibeui.ru/r/accordion-003.json
Installs to: components/vibeui/accordion-003.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 borderless accordion: rows and hairlines, nothing else. It does not read as a box dropped on the page, which makes it right for a list of questions inside running text.

An accordion with no borders or fills: question rows, hairlines between them and a plus sign that becomes a minus by rotating one bar. It never forms a visual box, so it belongs inside a text page. One-at-a-time behaviour is a single prop. Zero dependencies, one file, its own palette, no client JS.

## 3. How to use it
import { Accordion003 } from "@/components/vibeui/accordion-003"

<Accordion003
  exclusive
  items={[{ question: "How long does setup take?", answer: "Half an hour for the first project." }]}
/>

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-accordion-003-* palette — do not swap it for your theme tokens (border-border, text-muted-foreground and the like)
- the absence of a border and background: the moment a box appears the whole point of this variant is gone — it exists to sit in text
- the native details/summary instead of stateful buttons
- the two-bar sign with its rotation: swapping in a library icon adds a dependency where CSS is enough
- the top rule of the list and the bottom rules of the sections — without borders they are the only thing holding the rhythm
- the focus-visible outline on summary: headings are tabbed through
- the ch-based width limit on answers: with no border the line otherwise spans the page
- the <style> block inside the component — it holds the palette, the rules and the sign

## 6. You may change
- the items array: questions and answers
- exclusive — whether only one section stays open
- defaultOpen — which section starts open; by default all are closed
- the accent through the accent prop — it colours hover, the sign and focus
- max width and outer spacing through className

## 7. Rules
- This variant assumes a light page background. On a tinted surface give the parent a background, not the component.
- Do not nest it inside a bordered card: that is a box in a box, and accordion-002 already covers it.
- Every section starts closed on purpose: an open first answer pushes the other questions down.
- 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/accordion-003.json
https://vibeui.ru/r/accordion-003.json

Компонент самодостаточен: один файл, без зависимостей, собственная палитра в локальных переменных --vibeui-accordion-003-*. Раскрытие держат нативные <details>/<summary>. Знак «плюс» собран из двух псевдоэлементов: горизонтальная полоса стоит на месте, вертикальная поворачивается в неё при раскрытии, поэтому «плюс» превращается в «минус» без второй иконки. Пропом exclusive включается взаимное исключение через атрибут name у details. Отступы и кегль считаются от собственной ширины через @container.

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 Accordion003Item = {
  question: string
  answer: string
}

export type Accordion003Props = Omit<
  ComponentPropsWithoutRef<"div">,
  "children"
> & {
  items?: Accordion003Item[]
  defaultOpen?: number
  /** Открытым остаётся только один раздел. */
  exclusive?: boolean
  accent?: string
}

// Идея компонента: аккордеон без рамок — только строки и волосяные линии
// между ними. Он не выглядит вставкой на странице и годится там, где список
// вопросов идёт внутри текста. Знак «плюс» превращается в «минус» поворотом
// одной полосы: это читается даже боковым зрением.
const STYLES = `
:where([data-vibeui-block="accordion-003"]){
--vibeui-accordion-003-fg:oklch(0.22 0.014 265);
--vibeui-accordion-003-muted:oklch(0.5 0.014 265);
--vibeui-accordion-003-line:oklch(0.9 0.006 265);
--vibeui-accordion-003-accent:oklch(0.55 0.2 262);
--vibeui-accordion-003-font:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
container-type:inline-size;
}
[data-vibeui-block="accordion-003"]{
display:flex;flex-direction:column;
width:100%;max-width:42rem;box-sizing:border-box;
color:var(--vibeui-accordion-003-fg);font-family:var(--vibeui-accordion-003-font);
border-top:1px solid var(--vibeui-accordion-003-line);
}
[data-vibeui-block="accordion-003"] details{border-bottom:1px solid var(--vibeui-accordion-003-line)}
[data-vibeui-block="accordion-003"] summary{
display:flex;align-items:flex-start;justify-content:space-between;gap:1.25rem;
padding:1rem 0.25rem;cursor:pointer;list-style:none;
font-size:0.9375rem;font-weight:550;line-height:1.45;
transition:color .16s ease;
}
[data-vibeui-block="accordion-003"] summary::-webkit-details-marker{display:none}
[data-vibeui-block="accordion-003"] summary:hover{color:var(--vibeui-accordion-003-accent)}
[data-vibeui-block="accordion-003"] summary:focus-visible{outline:2px solid var(--vibeui-accordion-003-accent);outline-offset:2px;border-radius:0.375rem}
/* Плюс и минус: горизонтальная полоса на месте, вертикальная складывается. */
[data-vibeui-block="accordion-003"] [data-part="sign"]{
position:relative;flex:none;width:0.875rem;height:0.875rem;margin-top:0.3125rem;
}
[data-vibeui-block="accordion-003"] [data-part="sign"]::before,
[data-vibeui-block="accordion-003"] [data-part="sign"]::after{
content:"";position:absolute;left:0;top:50%;
width:100%;height:1.5px;margin-top:-0.75px;border-radius:1px;
background:var(--vibeui-accordion-003-muted);
transition:transform .2s cubic-bezier(.32,.72,0,1),background-color .16s ease;
}
[data-vibeui-block="accordion-003"] [data-part="sign"]::after{transform:rotate(90deg)}
[data-vibeui-block="accordion-003"] details[open] [data-part="sign"]::after{transform:rotate(0deg)}
[data-vibeui-block="accordion-003"] details[open] [data-part="sign"]::before,
[data-vibeui-block="accordion-003"] details[open] [data-part="sign"]::after{background:var(--vibeui-accordion-003-accent)}
[data-vibeui-block="accordion-003"] [data-part="answer"]{
margin:0;padding:0 2.5rem 1.125rem 0.25rem;
font-size:0.875rem;line-height:1.65;color:var(--vibeui-accordion-003-muted);max-width:64ch;
}
@container (min-width: 32rem){
[data-vibeui-block="accordion-003"] summary{padding:1.125rem 0.25rem;font-size:1rem}
[data-vibeui-block="accordion-003"] [data-part="answer"]{font-size:0.9375rem}
}
@media (prefers-reduced-motion:reduce){[data-vibeui-block="accordion-003"] *{animation:none!important;transition:none!important}}
`

const DEFAULT_ITEMS: Accordion003Item[] = [
  {
    question: "Сколько времени занимает подключение?",
    answer:
      "Полчаса на первый проект: домен подключается за пять минут, остальное — наполнение страниц. Переносить существующий сайт дольше, обычно день.",
  },
  {
    question: "Что будет с сайтом, если я перестану платить?",
    answer:
      "Сайт остаётся опубликованным до конца оплаченного периода, дальше переходит в режим только для чтения. Исходники ваши и никуда не деваются.",
  },
  {
    question: "Можно ли работать вдвоём над одним проектом?",
    answer:
      "Да, участники приглашаются по почте и получают роль редактора или читателя. Одновременное редактирование одной страницы не блокируется.",
  },
  {
    question: "Есть ли ограничение по трафику?",
    answer:
      "Мягкое: до ста тысяч просмотров в месяц включено, дальше предупредим и предложим перейти на следующий тариф. Сайт при этом не выключается.",
  },
]

/**
 * Аккордеон без рамок: строки, волосяные линии и знак «плюс».
 * Один файл, ноль зависимостей, собственная палитра.
 */
export function Accordion003({
  items = DEFAULT_ITEMS,
  defaultOpen = -1,
  exclusive = false,
  accent,
  className,
  style,
  ...props
}: Accordion003Props) {
  const palette = {
    ...(accent ? { "--vibeui-accordion-003-accent": accent } : null),
    ...style,
  } as CSSProperties

  return (
    <>
      <style href="vibeui-accordion-003" precedence="medium">
        {STYLES}
      </style>
      <div
        {...props}
        data-vibeui-block="accordion-003"
        className={className}
        style={palette}
      >
        {items.map((item, index) => (
          <details
            key={item.question}
            name={exclusive ? "vibeui-accordion-003" : undefined}
            open={index === defaultOpen}
          >
            <summary>
              {item.question}
              <span data-part="sign" aria-hidden="true" />
            </summary>
            <p data-part="answer">{item.answer}</p>
          </details>
        ))}
      </div>
    </>
  )
}