Display
Icon Tile
An icon tile: a fixed size and slot, with the background and glyph derived from one hue instead of hand-picked.
- icon
- tile
- tone
- list
Preview
1440pxHost theme
Use it with AI
- 1. Copy the link.
- 2. Write to your agent in your own words and drop the link into the sentence.
- 3. The agent opens the link and installs the component from the registry.
put this in the header: https://vibeui.ru/c/icontile-001?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 "icontile-001" (Icon Tile) 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/icontile-001.json
Registry item: https://vibeui.ru/r/icontile-001.json
Installs to: components/vibeui/icontile-001.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
An icon tile: a fixed size and slot, with the background and glyph derived from one hue instead of hand-picked.
A pad behind an icon: five tones, three sizes, square or circle. Background and glyph derive from one hue. Zero dependencies, one file, no client JS.
## 3. How to use it
import { Icontile001 } from "@/components/vibeui/icontile-001"
<Icontile001 glyph="◆" tone="success" size="md" label="Done" />
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-icontile-001-* palette — do not swap it for your theme tokens
- deriving background and glyph from a shared hue: the pair is not hand-picked
- the fixed tile size — otherwise a list jumps with every icon's width
- hiding it from screen readers without a label: a decorative tile must not read
- the glyph size as a fraction of the tile, not a fixed number
- flex:none — the tile must not shrink in a narrow row
## 6. You may change
- glyph — a symbol or your own icon
- tone, size and shape
- label for a meaningful tile
- the corner radius
## 7. Rules
- The meaning lives in the adjacent text: colour alone carries no state.
- The default glyph is a placeholder; drop in your icon at the same size.
- Five tones is the ceiling: more colours stop being distinguishable in a list.
- 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/icontile-001.jsonhttps://vibeui.ru/r/icontile-001.jsonКомпонент самодостаточен: один файл, без зависимостей, собственная палитра в локальных переменных --vibeui-icontile-001-*. Серверный: хуков нет. Тон задаётся парой переменных оттенка и насыщенности, а цвета фона и знака выводятся из них функцией oklch — поэтому новый тон добавляется одной строкой. Без подписи плитка скрыта от скринридера как декоративная.
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 Icontile001Props = Omit<
ComponentPropsWithoutRef<"span">,
"children" | "color"
> & {
glyph?: string
label?: string
tone?: "neutral" | "accent" | "success" | "warning" | "danger"
size?: "sm" | "md" | "lg"
shape?: "square" | "circle"
}
// Идея компонента: подложка под иконку. Иконка сама по себе теряется в тексте,
// а плитка задаёт ей постоянный размер и место, поэтому список пунктов не
// прыгает, когда иконки разной ширины. Тон задаётся одной парой переменных —
// фон и цвет знака считаются от общего оттенка, а не подбираются вручную.
// Плитка декоративна: она скрыта от скринридера, а смысл несёт подпись рядом.
const STYLES = `
:where([data-vibeui-block="icontile-001"]){
--vibeui-icontile-001-size:2.5rem;
--vibeui-icontile-001-hue:265;
--vibeui-icontile-001-chroma:0.02;
--vibeui-icontile-001-radius:0.75rem;
--vibeui-icontile-001-font:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
}
/* Фон и знак считаются от одного оттенка: пара цветов не подбирается руками. */
[data-vibeui-block="icontile-001"]{
display:inline-flex;align-items:center;justify-content:center;flex:none;
width:var(--vibeui-icontile-001-size);height:var(--vibeui-icontile-001-size);
border-radius:var(--vibeui-icontile-001-radius);
background:oklch(0.94 var(--vibeui-icontile-001-chroma) var(--vibeui-icontile-001-hue));
color:oklch(0.45 calc(var(--vibeui-icontile-001-chroma) * 4) var(--vibeui-icontile-001-hue));
font-family:var(--vibeui-icontile-001-font);
font-size:calc(var(--vibeui-icontile-001-size) * 0.44);
font-weight:650;line-height:1;
}
[data-vibeui-block="icontile-001"][data-shape="circle"]{--vibeui-icontile-001-radius:9999px}
[data-vibeui-block="icontile-001"][data-size="sm"]{--vibeui-icontile-001-size:2rem;--vibeui-icontile-001-radius:0.625rem}
[data-vibeui-block="icontile-001"][data-size="lg"]{--vibeui-icontile-001-size:3.25rem;--vibeui-icontile-001-radius:1rem}
[data-vibeui-block="icontile-001"][data-tone="accent"]{--vibeui-icontile-001-hue:262;--vibeui-icontile-001-chroma:0.05}
[data-vibeui-block="icontile-001"][data-tone="success"]{--vibeui-icontile-001-hue:152;--vibeui-icontile-001-chroma:0.045}
[data-vibeui-block="icontile-001"][data-tone="warning"]{--vibeui-icontile-001-hue:75;--vibeui-icontile-001-chroma:0.05}
[data-vibeui-block="icontile-001"][data-tone="danger"]{--vibeui-icontile-001-hue:25;--vibeui-icontile-001-chroma:0.05}
@media (prefers-reduced-motion:reduce){[data-vibeui-block="icontile-001"]{transition:none!important}}
`
/**
* Плитка под иконку: постоянный размер и тон из одного оттенка.
* Один файл, ноль зависимостей, собственная палитра.
*/
export function Icontile001({
glyph = "◆",
label,
tone = "accent",
size = "md",
shape = "square",
className,
style,
...props
}: Icontile001Props) {
return (
<>
<style href="vibeui-icontile-001" precedence="medium">
{STYLES}
</style>
<span
{...props}
data-vibeui-block="icontile-001"
data-tone={tone}
data-size={size}
data-shape={shape}
role={label ? "img" : undefined}
aria-label={label}
aria-hidden={label ? undefined : true}
className={className}
style={style as CSSProperties}
>
{glyph}
</span>
</>
)
}