Buttons
Provider Sign In
A provider sign-in button: the mark is pinned to the left edge while the label centres across the full width, so a column of buttons keeps one axis.
- button
- auth
- oauth
- sign-in
Preview
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/button-048?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-048" (Provider Sign In) 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-048.json
Registry item: https://vibeui.ru/r/button-048.json
Installs to: components/vibeui/button-048.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 provider sign-in button: the mark is pinned to the left edge while the label centres across the full width, so a column of buttons keeps one axis.
A white sign-in button for an external provider. The mark is absolutely positioned at the left edge, so the label centres across the whole button and a column of 'Continue with …' lines up on one axis. Three providers switch both the mark and the default label. The marks are pure CSS, no images. Zero dependencies, one file.
## 3. How to use it
import { Button048 } from "@/components/vibeui/button-048"
<Button048 provider="google" onClick={signIn} />
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 mark out of the flow: put it in the line and the label shifts, breaking the column's shared axis
- the white surface with a border — the familiar shape people recognise as a sign-in button
- the 'Continue with …' wording: it is more honest than 'Sign in', because it covers signing up too
- the right padding matching the left one: without it the centred label drifts right
- focus-visible with an offset: sign-in buttons are often first in the tab order
- the constant 2.75rem height — a provider column has to be even
## 6. You may change
- the provider through the provider prop, which switches the mark and the default label
- the label through the label prop when you need your own wording
- the onClick handler and the rest of the native button props
- the mark: replace the CSS shape with the provider's real logo
- the maximum width through className
## 7. Rules
- The marks here are placeholders. Put the official logos in before shipping: providers have their own brand rules.
- Do not translate the provider's name: a localised spelling reads as a counterfeit.
- Do not move the mark into the flow for simplicity — it breaks label alignment across the column.
- 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-048.jsonhttps://vibeui.ru/r/button-048.jsonКомпонент самодостаточен: один файл, без зависимостей, собственная палитра в локальных переменных --vibeui-button-048-*. Серверный компонент. Знак вынут из потока (position:absolute) и не влияет на центрирование подписи — из-за этого несколько кнопок разных провайдеров выстраиваются с общей осью текста. Знаки условные, собраны из conic-gradient и псевдоэлементов; реальные логотипы приносит проект. Подпись по умолчанию берётся из карты LABELS по значению provider.
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 Button048Props = Omit<
ComponentPropsWithoutRef<"button">,
"children"
> & {
/** Провайдер входа: от него зависят подпись и знак слева. */
provider?: "google" | "github" | "apple"
label?: string
}
// Идея компонента: кнопка входа через провайдера. Знак прибит к левому краю,
// а подпись центрируется по всей кнопке — так ряд кнопок разных провайдеров
// выстраивается в колонку с общей осью текста. Знаки здесь условные, из CSS:
// настоящие логотипы приносит проект, у них свои правила использования.
const STYLES = `
:where([data-vibeui-block="button-048"]){
--vibeui-button-048-surface:oklch(1 0 0);
--vibeui-button-048-border:oklch(0.87 0.006 265);
--vibeui-button-048-fg:oklch(0.24 0.02 265);
--vibeui-button-048-ring:oklch(0.55 0.02 265 / 65%);
--vibeui-button-048-font:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
}
[data-vibeui-block="button-048"]{
position:relative;appearance:none;cursor:pointer;box-sizing:border-box;
display:flex;align-items:center;justify-content:center;
width:100%;max-width:20rem;height:2.75rem;padding:0 3rem;
border:1px solid var(--vibeui-button-048-border);border-radius:0.625rem;
background:var(--vibeui-button-048-surface);color:var(--vibeui-button-048-fg);
font-family:var(--vibeui-button-048-font);font-size:0.875rem;font-weight:600;line-height:1;
box-shadow:0 1px 2px oklch(0 0 0 / 6%);
transition:background-color .16s ease,border-color .16s ease;
}
[data-vibeui-block="button-048"]:hover:not(:disabled){
background:oklch(0.97 0.003 265);border-color:oklch(0.8 0.008 265);
}
[data-vibeui-block="button-048"]:focus-visible{outline:2px solid var(--vibeui-button-048-ring);outline-offset:2px}
[data-vibeui-block="button-048"]:disabled{cursor:not-allowed;opacity:.55}
/* Знак прижат к краю, подпись центрируется по всей ширине кнопки. */
[data-vibeui-block="button-048"] [data-part="mark"]{
position:absolute;left:0.9375rem;top:50%;margin-top:-0.5625rem;
width:1.125rem;height:1.125rem;border-radius:50%;
}
[data-vibeui-block="button-048"][data-provider="google"] [data-part="mark"]{
background:conic-gradient(oklch(0.62 0.22 27) 0 25%,oklch(0.8 0.16 85) 0 50%,oklch(0.6 0.16 150) 0 75%,oklch(0.55 0.19 260) 0);
}
[data-vibeui-block="button-048"][data-provider="google"] [data-part="mark"]::after{
content:"";position:absolute;left:50%;top:50%;width:0.5rem;height:0.5rem;
margin:-0.25rem 0 0 -0.25rem;border-radius:50%;background:var(--vibeui-button-048-surface);
}
[data-vibeui-block="button-048"][data-provider="github"] [data-part="mark"]{
background:oklch(0.24 0.01 265);
}
[data-vibeui-block="button-048"][data-provider="github"] [data-part="mark"]::after{
content:"";position:absolute;left:50%;top:0.5rem;width:0.625rem;height:0.4375rem;
margin-left:-0.3125rem;border-radius:0.25rem 0.25rem 0 0;
background:var(--vibeui-button-048-surface);
}
[data-vibeui-block="button-048"][data-provider="apple"] [data-part="mark"]{
background:oklch(0.2 0 0);border-radius:0.375rem;
}
[data-vibeui-block="button-048"][data-provider="apple"] [data-part="mark"]::after{
content:"";position:absolute;left:50%;top:50%;width:0.4375rem;height:0.4375rem;
margin:-0.21875rem 0 0 -0.21875rem;border-radius:50% 50% 50% 0;
background:var(--vibeui-button-048-surface);transform:rotate(-45deg);
}
@media (prefers-reduced-motion:reduce){[data-vibeui-block="button-048"]{transition:none!important}}
`
const LABELS = {
google: "Продолжить с Google",
github: "Продолжить с GitHub",
apple: "Продолжить с Apple",
}
/**
* Кнопка входа через провайдера: знак у края, подпись по центру.
* Один файл, ноль зависимостей, собственная палитра.
*/
export function Button048({
provider = "google",
label,
type = "button",
className,
style,
...props
}: Button048Props) {
return (
<>
<style href="vibeui-button-048" precedence="medium">
{STYLES}
</style>
<button
{...props}
type={type}
data-vibeui-block="button-048"
data-provider={provider}
className={className}
style={style as CSSProperties}
>
<span data-part="mark" aria-hidden="true" />
{label ?? LABELS[provider]}
</button>
</>
)
}