Tables

Log Table

A dense log table: monospaced columns line the paths up, and the status code carries a dot, not just a colour.

  • table
  • logs
  • mono
  • status

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/table-008?lang=en

Recent requests
ВремяМетодАдресКодмс
10:42:11GET/r/button-001.json20034
10:42:09GET/components/card-004200128
10:41:58POST/api/registry/build202940
10:41:40GET/r/table-404.json40412
10:41:22GET/c/hero-00120051
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 "table-008" (Log Table) 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/table-008.json

Registry item: https://vibeui.ru/r/table-008.json
Installs to: components/vibeui/table-008.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 log table: monospaced columns line the paths up, and the status code carries a dot, not just a colour.

A request table: time, method, path, a dotted status code and duration. Dense rows, monospaced columns. Zero dependencies, one file, no client JS.

## 3. How to use it
import { Table008 } from "@/components/vibeui/table-008"

<Table008 rows={[{ time: "10:42:11", method: "GET", path: "/r/button-001.json", code: 200, ms: 34 }]} />

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-table-008-* palette — do not swap it for your theme tokens
- the monospaced body: paths and codes get compared character by character
- the dot beside the code: in a field of grey the colour is lost, the shape is not
- the different dot shape for failures: circle and square differ without colour
- tabular figures and the right-aligned duration
- the dense rows: logs need density, not air

## 6. You may change
- the rows array and the column set
- the thresholds inside the tone function
- caption — the table caption
- the state colours

## 7. Rules
- The tone is derived from the code: do not pass it as a prop or data and display will drift apart.
- Long paths do not wrap: the table scrolls horizontally instead.
- For a live log stream add your own virtualisation — there is none here.
- 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/table-008.json
https://vibeui.ru/r/table-008.json

Компонент самодостаточен: один файл, без зависимостей, собственная палитра в локальных переменных --vibeui-table-008-*. Серверный: хуков нет. Тело таблицы набрано моноширинным шрифтом с табличными цифрами, поэтому адреса и коды выравниваются в столбик. Тон строки считается из кода ответа функцией, а не приходит пропом.

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 Table008Row = {
  time: string
  method: string
  path: string
  code: number
  ms: number
}

export type Table008Props = Omit<
  ComponentPropsWithoutRef<"div">,
  "children"
> & {
  rows?: Table008Row[]
  caption?: string
  accent?: string
}

// Идея компонента: плотная таблица логов. Моноширинный шрифт и табличные цифры
// выравнивают адреса и коды в столбик, поэтому отличие в одном символе видно
// без чтения. Код ответа помечен точкой, а не только цветом: строки просматривают
// глазами по краю, и красный текст в потоке серого теряется.
const STYLES = `
:where([data-vibeui-block="table-008"]){
--vibeui-table-008-bg:oklch(1 0 0);
--vibeui-table-008-fg:oklch(0.24 0.014 265);
--vibeui-table-008-muted:oklch(0.56 0.014 265);
--vibeui-table-008-border:oklch(0.93 0.005 265);
--vibeui-table-008-head:oklch(0.975 0.003 265);
--vibeui-table-008-ok:oklch(0.62 0.15 152);
--vibeui-table-008-warn:oklch(0.72 0.15 75);
--vibeui-table-008-fail:oklch(0.58 0.19 25);
--vibeui-table-008-mono:ui-monospace,SFMono-Regular,Menlo,Consolas,"Liberation Mono",monospace;
--vibeui-table-008-font:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
}
[data-vibeui-block="table-008"]{
width:100%;box-sizing:border-box;overflow-x:auto;
background:var(--vibeui-table-008-bg);
border:1px solid var(--vibeui-table-008-border);border-radius:0.875rem;
font-family:var(--vibeui-table-008-font);color:var(--vibeui-table-008-fg);
}
[data-vibeui-block="table-008"] table{width:100%;border-collapse:collapse}
[data-vibeui-block="table-008"] caption{padding:0.625rem 0.75rem;text-align:left;font-size:0.8125rem;font-weight:650}
[data-vibeui-block="table-008"] th,
[data-vibeui-block="table-008"] td{
padding:0.25rem 0.75rem;text-align:left;white-space:nowrap;
border-top:1px solid var(--vibeui-table-008-border);
}
[data-vibeui-block="table-008"] thead th{
background:var(--vibeui-table-008-head);
font-size:0.6875rem;font-weight:600;letter-spacing:0.03em;text-transform:uppercase;
color:var(--vibeui-table-008-muted);
}
/* Моноширинные ячейки: адреса и коды сравнивают посимвольно. */
[data-vibeui-block="table-008"] tbody td{
font-family:var(--vibeui-table-008-mono);font-size:0.75rem;line-height:1.7;
font-variant-numeric:tabular-nums;
}
[data-vibeui-block="table-008"] [data-align="end"]{text-align:right}
[data-vibeui-block="table-008"] [data-part="time"],
[data-vibeui-block="table-008"] [data-part="ms"]{color:var(--vibeui-table-008-muted)}
[data-vibeui-block="table-008"] [data-part="method"]{font-weight:700}
/* Точка у кода: цвет в потоке серого теряется, форма — нет. */
[data-vibeui-block="table-008"] [data-part="code"]{display:flex;align-items:center;gap:0.375rem}
[data-vibeui-block="table-008"] [data-part="dot"]{
width:0.4375rem;height:0.4375rem;border-radius:9999px;background:var(--vibeui-table-008-ok);
}
[data-vibeui-block="table-008"] [data-tone="warn"] [data-part="dot"]{background:var(--vibeui-table-008-warn)}
[data-vibeui-block="table-008"] [data-tone="fail"] [data-part="dot"]{background:var(--vibeui-table-008-fail);border-radius:0.125rem}
[data-vibeui-block="table-008"] [data-tone="fail"] [data-part="code"]{color:var(--vibeui-table-008-fail);font-weight:700}
@media (prefers-reduced-motion:reduce){[data-vibeui-block="table-008"] *{animation:none!important;transition:none!important}}
`

const DEFAULT_ROWS: Table008Row[] = [
  {
    time: "10:42:11",
    method: "GET",
    path: "/r/button-001.json",
    code: 200,
    ms: 34,
  },
  {
    time: "10:42:09",
    method: "GET",
    path: "/components/card-004",
    code: 200,
    ms: 128,
  },
  {
    time: "10:41:58",
    method: "POST",
    path: "/api/registry/build",
    code: 202,
    ms: 940,
  },
  {
    time: "10:41:40",
    method: "GET",
    path: "/r/table-404.json",
    code: 404,
    ms: 12,
  },
  { time: "10:41:22", method: "GET", path: "/c/hero-001", code: 200, ms: 51 },
]

function tone(code: number) {
  if (code >= 400) return "fail"
  if (code >= 300) return "warn"
  return "ok"
}

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

  return (
    <>
      <style href="vibeui-table-008" precedence="medium">
        {STYLES}
      </style>
      <div
        {...props}
        data-vibeui-block="table-008"
        className={className}
        style={palette}
      >
        <table>
          <caption>{caption}</caption>
          <thead>
            <tr>
              <th scope="col">Время</th>
              <th scope="col">Метод</th>
              <th scope="col">Адрес</th>
              <th scope="col">Код</th>
              <th scope="col" data-align="end">
                мс
              </th>
            </tr>
          </thead>
          <tbody>
            {rows.map((row) => (
              <tr key={`${row.time}-${row.path}`} data-tone={tone(row.code)}>
                <td data-part="time">{row.time}</td>
                <td data-part="method">{row.method}</td>
                <td>{row.path}</td>
                <td>
                  <span data-part="code">
                    <span data-part="dot" aria-hidden="true" />
                    {row.code}
                  </span>
                </td>
                <td data-part="ms" data-align="end">
                  {row.ms}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </>
  )
}