Display

Dense List Rows

A dense list where row height comes from a single step variable: density changes as a whole, and separators are inset lines without doubled seams.

  • item
  • list
  • dense
  • table

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/item-010?lang=en

  • AL-118Кабель питания, 2 м412
  • AL-119Кабель питания, 5 м96
  • BR-204Кронштейн настенный1 240
  • BR-207Кронштейн потолочный38
  • CM-330Модуль связи RS-4857
  • CM-331Модуль связи Ethernet0
  • DX-402Датчик протечки615
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 "item-010" (Dense List Rows) 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/item-010.json

Registry item: https://vibeui.ru/r/item-010.json
Installs to: components/vibeui/item-010.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 dense list where row height comes from a single step variable: density changes as a whole, and separators are inset lines without doubled seams.

A dense list of rows with a code, a title and a number: three density steps from one unit. Zero dependencies, one file.

## 3. How to use it
import { Item010 } from "@/components/vibeui/item-010"

<Item010 density="compact" rows={[{ code: "AL-118", title: "Cable", value: "412" }]} />

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-item-010-* palette — do not swap it for your theme tokens
- the row height driven by one step variable: tweaking paddings per node breaks the rhythm
- the inset-shadow separator — a border on every row doubles up at the seams
- tabular figures in the right column: the column gets compared top to bottom
- clipping the title with an ellipsis instead of wrapping — otherwise rows differ in height
- the ul and li elements: a dense list is still a list, not a grid of divs

## 6. You may change
- the rows array: code, title and value
- density — one of the three density steps
- the accent through the accent prop
- the list width and the set of columns

## 7. Rules
- For sortable columns and headers use a table: this is a list, not a table.
- At the tight step a row is under 24 pixels — check you do not need a tap target on phones.
- The row key is the code: it has to be unique.
- 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/item-010.json
https://vibeui.ru/r/item-010.json

Компонент самодостаточен: один файл, без зависимостей, собственная палитра в локальных переменных --vibeui-item-010-*. Серверный: хуков нет. Корень — ul, каждая строка это li с гридом из трёх колонок. Высота строки берётся из --vibeui-item-010-step, а проп density переключает шаг через data-density, поэтому плотность меняется одним значением. Разделитель сделан внутренней тенью на соседних строках, а не рамкой каждой: рамки удваивались бы на стыках.

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 Item010Row = {
  code: string
  title: string
  value: string
}

export type Item010Props = Omit<ComponentPropsWithoutRef<"ul">, "children"> & {
  rows?: Item010Row[]
  density?: "tight" | "compact" | "cozy"
  accent?: string
}

// Идея компонента: строка для плотного списка, где на экран должно попасть
// сорок записей, а не восемь. Высота задана одной переменной шага, поэтому
// плотность меняется целиком, а не подкруткой отступов у каждого узла. Строки
// разделены внутренней линией, а не рамкой каждой строки: рамки удваивались бы
// на стыках и давали двойную черту. Числа набраны табличными цифрами и выровнены
// вправо — в плотном списке колонку сравнивают взглядом сверху вниз.
const STYLES = `
:where([data-vibeui-block="item-010"]){
--vibeui-item-010-bg:oklch(1 0 0);
--vibeui-item-010-fg:oklch(0.23 0.014 265);
--vibeui-item-010-muted:oklch(0.56 0.014 265);
--vibeui-item-010-border:oklch(0.91 0.006 265);
--vibeui-item-010-hover:oklch(0.97 0.003 265);
--vibeui-item-010-accent:oklch(0.55 0.19 262);
--vibeui-item-010-step:1.625rem;
--vibeui-item-010-font:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
}
[data-vibeui-block="item-010"]{
list-style:none;margin:0;padding:0;overflow:hidden;
width:100%;max-width:24rem;box-sizing:border-box;
background:var(--vibeui-item-010-bg);
border:1px solid var(--vibeui-item-010-border);border-radius:0.625rem;
font-family:var(--vibeui-item-010-font);color:var(--vibeui-item-010-fg);
}
[data-vibeui-block="item-010"] *{box-sizing:border-box}
[data-vibeui-block="item-010"][data-density="tight"]{--vibeui-item-010-step:1.5rem}
[data-vibeui-block="item-010"][data-density="compact"]{--vibeui-item-010-step:1.875rem}
[data-vibeui-block="item-010"][data-density="cozy"]{--vibeui-item-010-step:2.375rem}
/* Высота строки — один шаг: плотность меняется целиком, а не по отступам. */
[data-vibeui-block="item-010"] [data-part="row"]{
display:grid;grid-template-columns:3.5rem minmax(0,1fr) auto;align-items:center;gap:0.625rem;
min-height:var(--vibeui-item-010-step);padding:0 0.625rem;
font-size:0.75rem;line-height:1.25;
}
/* Линия внутри строки, а не рамка у каждой: иначе на стыках двойная черта. */
[data-vibeui-block="item-010"] [data-part="row"] + [data-part="row"]{
box-shadow:inset 0 1px 0 var(--vibeui-item-010-border);
}
[data-vibeui-block="item-010"] [data-part="row"]:hover{background:var(--vibeui-item-010-hover)}
[data-vibeui-block="item-010"] [data-part="code"]{
color:var(--vibeui-item-010-accent);font-weight:650;font-variant-numeric:tabular-nums;
font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:0.6875rem;
}
[data-vibeui-block="item-010"] [data-part="title"]{
overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
[data-vibeui-block="item-010"] [data-part="value"]{
justify-self:end;color:var(--vibeui-item-010-muted);
font-variant-numeric:tabular-nums;font-feature-settings:"tnum";
}
@media (prefers-reduced-motion:reduce){[data-vibeui-block="item-010"] *{animation:none!important;transition:none!important}}
`

const DEFAULT_ROWS: Item010Row[] = [
  { code: "AL-118", title: "Кабель питания, 2 м", value: "412" },
  { code: "AL-119", title: "Кабель питания, 5 м", value: "96" },
  { code: "BR-204", title: "Кронштейн настенный", value: "1 240" },
  { code: "BR-207", title: "Кронштейн потолочный", value: "38" },
  { code: "CM-330", title: "Модуль связи RS-485", value: "7" },
  { code: "CM-331", title: "Модуль связи Ethernet", value: "0" },
  { code: "DX-402", title: "Датчик протечки", value: "615" },
]

/**
 * Плотный список: строка ростом в один шаг, три колонки, табличные цифры.
 * Один файл, ноль зависимостей, собственная палитра.
 */
export function Item010({
  rows = DEFAULT_ROWS,
  density = "tight",
  accent,
  className,
  style,
  ...props
}: Item010Props) {
  const palette = {
    ...(accent ? { "--vibeui-item-010-accent": accent } : null),
    ...style,
  } as CSSProperties

  return (
    <>
      <style href="vibeui-item-010" precedence="medium">
        {STYLES}
      </style>
      <ul
        {...props}
        data-vibeui-block="item-010"
        data-density={density}
        className={className}
        style={palette}
      >
        {rows.map((row) => (
          <li key={row.code} data-part="row">
            <span data-part="code">{row.code}</span>
            <span data-part="title">{row.title}</span>
            <span data-part="value">{row.value}</span>
          </li>
        ))}
      </ul>
    </>
  )
}