Avatar
Verified Name
Знак подтверждения стоит после имени, а не в углу портрета: подтверждают имя, и в углу галочка теряется среди присутствия и роли.
- avatar
- verified
- badge
- identity
Превью
Использовать с AI
- 1. Скопируйте ссылку.
- 2. Напишите агенту своими словами и вставьте её в предложение.
- 3. Агент откроет ссылку и поставит компонент из registry.
размести это в шапке: https://vibeui.ru/c/avatar-035
Показать полную инструкцию
То, что лежит по ссылке в развёрнутом виде. Нужна, если агент не может открыть ссылку — тогда вставьте этот текст целиком.
# Установка и размещение «avatar-035» (Verified Name) из VibeUI
## 1. Сначала установка — не пропускай, не пересоздавай
Выполни эту команду до того, как писать код:
npx shadcn@latest add https://vibeui.ru/r/avatar-035.json
Registry item: https://vibeui.ru/r/avatar-035.json
Ставится в: components/vibeui/avatar-035.tsx (точный путь следует алиасам components.json этого проекта).
npm-зависимости: нет.
Registry-зависимости: нет.
Ставь из реестра. Не пересоздавай по описанию, не подменяй похожим
компонентом из другой библиотеки и не переписывай под стиль проекта.
## 2. Что это
Знак подтверждения стоит после имени, а не в углу портрета: подтверждают имя, и в углу галочка теряется среди присутствия и роли.
Аватар со знаком подтверждения в строке имени: три вида различаются формой знака и расшифрованы словами. Ноль зависимостей, один файл, клиентского JS нет.
## 3. Как использовать
import { Avatar035 } from "@/components/vibeui/avatar-035"
<Avatar035 name="Анна Реброва" kind="person" since="с 12 марта 2025" />
Полный список пропсов — в установленном файле.
## 4. Куда поставить
Это мелкий inline-компонент. Поставь его ровно туда, куда просил
пользователь, внутрь существующей разметки. Не создавай ради него
новую страницу, секцию или обёртку. Если на этом месте уже стоит похожий
контрол — замени его, а не добавляй второй.
Куда поставить: ___
(Эту строку заполняет пользователь. Если она осталась пустой — спроси,
а не угадывай.)
## 5. Сохранить как установлено
- локальную палитру --vibeui-avatar-035-* и не подменять её токенами вашей темы
- знак в строке имени, а не в углу портрета: подтверждают имя, и в углу знак теряется среди присутствия и роли
- различие видов формой знака — круг, квадрат, шестиугольник: по цвету их не отличить
- расшифровку словами во второй строке: галочка сама по себе немая
- aria-hidden на знаке — иначе скринридер прочитает подтверждение дважды
- собственную светлую подложку строки: без неё тёмный текст пропадает на тёмном фоне
## 6. Можно менять
- имя и вид подтверждения через kind
- дату подтверждения через since
- цвета трёх видов в переменных
- формулировки расшифровки в словаре
## 7. Правила
- Знак подтверждения — обещание от вашего имени: рисуйте его только там, где проверка действительно была.
- Не ставьте рядом с ним второй значок в углу портрета: два знака подряд читаются как один составной.
- Дата приходит готовой строкой: форматирование и склонение месяца остаются на вызывающем коде.
- Не выносите CSS-переменные в globals.css: компонент обязан оставаться одним файлом.
## 8. Проверка
- рендерится без ошибок в консоли;
- выглядит так же, как превью на странице VibeUI, откуда взята ссылка;
- если нет — ты изменил что-то из раздела 5, верни как было.Для разработчика
npx shadcn@latest add https://vibeui.ru/r/avatar-035.jsonhttps://vibeui.ru/r/avatar-035.jsonКомпонент самодостаточен: один файл, без зависимостей, собственная палитра в локальных переменных --vibeui-avatar-035-*. Серверный: хуков нет. Знак вынесен в строку имени, а не в угол портрета: подтверждают имя, а в углу галочка соседствует с присутствием и ролью и теряется среди них. Три вида подтверждения различаются формой знака — круг, скруглённый квадрат, шестиугольник на clip-path, — и каждый расшифрован словами во второй строке. Сама галочка нарисована двумя бордюрами псевдоэлемента, иконочный пакет ради неё не нужен.
Исходник компонента
Тот же файл, который поставит агент. Нужен, если вы предпочитаете скопировать код руками.
import type { ComponentPropsWithoutRef, CSSProperties } from "react"
export type Avatar035Props = Omit<
ComponentPropsWithoutRef<"div">,
"children"
> & {
name?: string
kind?: "person" | "organisation" | "creator"
since?: string
}
// Идея компонента: знак подтверждения стоит после имени, а не в углу портрета.
// Подтверждают имя, а не фотографию: в углу аватара галочка соседствует с
// присутствием и ролью и теряется среди них, а рядом с именем она читается
// как часть подписи и переезжает вместе с ней в любую строку. Три вида
// подтверждения различаются формой знака — круг, квадрат, шестиугольник, — и
// каждый расшифрован словами во второй строке: галочка сама по себе немая.
const STYLES = `
:where([data-vibeui-block="avatar-035"]){
--vibeui-avatar-035-size:2.5rem;
--vibeui-avatar-035-tick:1rem;
--vibeui-avatar-035-bg:oklch(1 0 0);
--vibeui-avatar-035-fg:oklch(0.24 0.014 265);
--vibeui-avatar-035-muted:oklch(0.55 0.014 265);
--vibeui-avatar-035-border:oklch(0.91 0.006 265);
--vibeui-avatar-035-person:oklch(0.55 0.2 262);
--vibeui-avatar-035-org:oklch(0.55 0.13 195);
--vibeui-avatar-035-creator:oklch(0.62 0.17 320);
--vibeui-avatar-035-font:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
}
/* Своя светлая подложка: тёмный текст обязан читаться на любом фоне. */
[data-vibeui-block="avatar-035"]{
display:flex;align-items:center;gap:0.75rem;
box-sizing:border-box;width:100%;max-width:20rem;padding:0.5rem 0.75rem;
background:var(--vibeui-avatar-035-bg);
border:1px solid var(--vibeui-avatar-035-border);border-radius:0.75rem;
font-family:var(--vibeui-avatar-035-font);color:var(--vibeui-avatar-035-fg);
}
[data-vibeui-block="avatar-035"] *{box-sizing:border-box}
[data-vibeui-block="avatar-035"] [data-part="face"]{
display:grid;place-items:center;flex:none;
width:var(--vibeui-avatar-035-size);height:var(--vibeui-avatar-035-size);
border-radius:9999px;
background:oklch(0.9 0.06 var(--vibeui-avatar-035-hue,265));
color:oklch(0.36 0.12 var(--vibeui-avatar-035-hue,265));
font-size:calc(var(--vibeui-avatar-035-size) * 0.34);font-weight:700;line-height:1;
}
[data-vibeui-block="avatar-035"] [data-part="text"]{display:flex;flex-direction:column;gap:0.0625rem;min-width:0;flex:1 1 auto}
/* Знак — часть подписи: он стоит в строке имени, а не в углу портрета. */
[data-vibeui-block="avatar-035"] [data-part="name"]{
display:flex;align-items:center;gap:0.3125rem;min-width:0;
font-size:0.875rem;font-weight:650;
}
[data-vibeui-block="avatar-035"] [data-part="label"]{
min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
[data-vibeui-block="avatar-035"] [data-part="badge"]{
position:relative;display:grid;place-items:center;flex:none;
width:var(--vibeui-avatar-035-tick);height:var(--vibeui-avatar-035-tick);
border-radius:9999px;background:var(--vibeui-avatar-035-person);
}
/* Форма знака различает вид подтверждения, а не только цвет. */
[data-vibeui-block="avatar-035"][data-kind="organisation"] [data-part="badge"]{
border-radius:0.25rem;background:var(--vibeui-avatar-035-org);
}
[data-vibeui-block="avatar-035"][data-kind="creator"] [data-part="badge"]{
border-radius:0;background:var(--vibeui-avatar-035-creator);
clip-path:polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%);
}
/* Галочка на двух бордюрах: иконочный пакет ради неё не нужен. */
[data-vibeui-block="avatar-035"] [data-part="badge"]::after{
content:"";width:0.1875rem;height:0.375rem;
border:solid oklch(1 0 0);border-width:0 0.09375rem 0.09375rem 0;
transform:translateY(-0.0625rem) rotate(45deg);
}
[data-vibeui-block="avatar-035"] [data-part="since"]{
font-size:0.75rem;color:var(--vibeui-avatar-035-muted);
overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
@media (prefers-reduced-motion:reduce){[data-vibeui-block="avatar-035"] *{animation:none!important;transition:none!important}}
`
const KIND_LABEL = {
person: "Личность подтверждена",
organisation: "Организация подтверждена",
creator: "Автор подтверждён",
} as const
function hue(name: string) {
let hash = 2166136261
for (const symbol of name) {
hash ^= symbol.codePointAt(0)!
hash = Math.imul(hash, 16777619)
}
return ((hash >>> 0) % 12) * 30
}
function initials(name: string) {
return name
.split(" ")
.slice(0, 2)
.map((part) => part.charAt(0).toUpperCase())
.join("")
}
/**
* Аватар со знаком подтверждения в строке имени: вид различается формой знака.
* Один файл, ноль зависимостей, собственная палитра.
*/
export function Avatar035({
name = "Анна Реброва",
kind = "person",
since = "с 12 марта 2025",
className,
style,
...props
}: Avatar035Props) {
const palette = {
"--vibeui-avatar-035-hue": hue(name),
...style,
} as CSSProperties
return (
<>
<style href="vibeui-avatar-035" precedence="medium">
{STYLES}
</style>
<div
{...props}
data-vibeui-block="avatar-035"
data-kind={kind}
className={className}
style={palette}
>
<span data-part="face" aria-hidden="true">
{initials(name)}
</span>
<span data-part="text">
<span data-part="name">
<span data-part="label">{name}</span>
{/* Знак немой: расшифровку несёт строка под именем. */}
<span data-part="badge" aria-hidden="true" />
</span>
<span data-part="since">
{KIND_LABEL[kind]} {since}
</span>
</span>
</div>
</>
)
}