Buttons

Call Link Button

A contact button built on a real tel: link: the number is visible and copyable, while a pulsing ring and an hours line say the line is open.

  • button
  • call
  • tel
  • contact

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/button-052?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 "button-052" (Call Link Button) 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/button-052.json

Registry item: https://vibeui.ru/r/button-052.json
Installs to: components/vibeui/button-052.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 contact button built on a real tel: link: the number is visible and copyable, while a pulsing ring and an hours line say the line is open.

A call button that shows the number itself: the purpose on top, a monospace number below it, opening hours under that. On the left a handset in a circle with an expanding ring: the line is open. It is a tel: link, so the number can be copied from the context menu and works on any platform. Zero dependencies, one file.

## 3. How to use it
import { Button052 } from "@/components/vibeui/button-052"

<Button052 phone="+7 495 120-45-90" hint="We answer 9:00–21:00">
  Call support
</Button052>

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 tel: link instead of a click handler: only that way is the number copyable and dialable
- the human-readable number on screen — only href is stripped, never what the user reads
- the monospace face and tabular-nums on the number: the digits must not shift the width
- the availability ring and the prefers-reduced-motion rule that stops it
- the three lines in the order purpose, number, hours: why call first, where second
- the contrasting fill — a contact button has to be findable on the page at a glance

## 6. You may change
- the purpose label
- the number through the phone prop, which also builds the href
- the hours line through the hint prop
- the accent colour through the accent prop
- outer spacing through className

## 7. Rules
- Do not show the pulsing ring when the line is actually closed: the animation promises availability right now.
- Keep the number in international format with a plus — otherwise a call from abroad will not connect.
- Do not swap the link for a button with a handler: on desktop that removes the ability to copy the number.
- 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/button-052.json
https://vibeui.ru/r/button-052.json

Компонент самодостаточен: один файл, без зависимостей, собственная палитра в локальных переменных --vibeui-button-052-*. Серверный компонент, корень — <a href="tel:…">: на телефоне вызов уходит в звонилку, на десктопе — в приложение пользователя. Из видимой записи номера пробелы и разделители вычищаются только в href, поэтому человекочитаемый вид сохраняется. Трубка нарисована рамкой с прозрачными гранями, кольцо доступности — анимация на псевдоэлементе, номер набран моноширинным с tabular-nums.

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 Button052Props = Omit<ComponentPropsWithoutRef<"a">, "href"> & {
  /** Номер в человекочитаемом виде: он же попадает в tel: после чистки. */
  phone?: string
  /** Строка доступности под номером: часы работы или статус линии. */
  hint?: string
  accent?: string
}

// Идея компонента: кнопка связи — это ссылка tel:, а не обработчик клика.
// Тогда на телефоне вызов уходит в звонилку, на десктопе — в приложение
// пользователя, а номер можно скопировать из контекстного меню. Из видимой
// записи номера пробелы и скобки вычищаются только в href.
const STYLES = `
:where([data-vibeui-block="button-052"]){
--vibeui-button-052-accent:oklch(0.55 0.15 150);
--vibeui-button-052-fg:oklch(0.99 0.01 150);
--vibeui-button-052-font:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
--vibeui-button-052-mono:ui-monospace,SFMono-Regular,Menlo,Consolas,"Liberation Mono",monospace;
}
[data-vibeui-block="button-052"]{
display:inline-flex;align-items:center;gap:0.75rem;box-sizing:border-box;
padding:0.625rem 1.125rem 0.625rem 0.875rem;border-radius:9999px;
background:var(--vibeui-button-052-accent);color:var(--vibeui-button-052-fg);
font-family:var(--vibeui-button-052-font);text-decoration:none;
transition:filter .16s ease;
}
[data-vibeui-block="button-052"]:hover{filter:brightness(1.07)}
[data-vibeui-block="button-052"]:focus-visible{outline:2px solid var(--vibeui-button-052-accent);outline-offset:3px}
/* Трубка: скруглённый прямоугольник, повёрнутый и обрезанный по углам. */
[data-vibeui-block="button-052"] [data-part="dial"]{
position:relative;flex:none;
display:flex;align-items:center;justify-content:center;
width:2rem;height:2rem;border-radius:50%;background:oklch(1 0 0 / 20%);
}
[data-vibeui-block="button-052"] [data-part="dial"]::before{
content:"";width:0.875rem;height:0.875rem;
border:2px solid currentColor;border-radius:0.4375rem 0.25rem 0.4375rem 0.25rem;
border-top-color:transparent;border-right-color:transparent;
transform:rotate(8deg);
}
/* Кольцо доступности пульсирует: линия открыта прямо сейчас. */
[data-vibeui-block="button-052"] [data-part="dial"]::after{
content:"";position:absolute;inset:-2px;border-radius:50%;
border:2px solid oklch(1 0 0 / 55%);
animation:vibeui-button-052-ring 2.4s ease-out infinite;
}
@keyframes vibeui-button-052-ring{
0%{opacity:.7;transform:scale(1)}
70%{opacity:0;transform:scale(1.35)}
100%{opacity:0;transform:scale(1.35)}
}
[data-vibeui-block="button-052"] [data-part="text"]{display:flex;flex-direction:column;gap:0.1875rem}
[data-vibeui-block="button-052"] [data-part="label"]{font-size:0.75rem;font-weight:600;opacity:.85;letter-spacing:0.02em}
[data-vibeui-block="button-052"] [data-part="phone"]{
font-family:var(--vibeui-button-052-mono);font-size:0.9375rem;font-weight:600;
font-variant-numeric:tabular-nums;letter-spacing:0.01em;
}
[data-vibeui-block="button-052"] [data-part="hint"]{font-size:0.6875rem;opacity:.75}
@media (prefers-reduced-motion:reduce){[data-vibeui-block="button-052"] *{animation:none!important;transition:none!important}}
`

/**
 * Кнопка звонка на настоящей ссылке tel: с номером и статусом линии.
 * Один файл, ноль зависимостей, собственная палитра.
 */
export function Button052({
  phone = "+7 495 120-45-90",
  hint = "Отвечаем с 9:00 до 21:00",
  accent,
  className,
  style,
  children = "Позвонить в поддержку",
  ...props
}: Button052Props) {
  const palette = {
    ...(accent ? { "--vibeui-button-052-accent": accent } : null),
    ...style,
  } as CSSProperties

  return (
    <>
      <style href="vibeui-button-052" precedence="medium">
        {STYLES}
      </style>
      <a
        {...props}
        href={`tel:${phone.replace(/[^\d+]/g, "")}`}
        data-vibeui-block="button-052"
        className={className}
        style={palette}
      >
        <span data-part="dial" aria-hidden="true" />
        <span data-part="text">
          <span data-part="label">{children}</span>
          <span data-part="phone">{phone}</span>
          {hint ? <span data-part="hint">{hint}</span> : null}
        </span>
      </a>
    </>
  )
}