Buttons
Slide Fill Button
A clean outlined button whose background slides in left to right on hover, revealing a solid fill behind the label.
Loading preview
Advertisement
Ad space reserved for a future placement
Source code
"use client";
import type { ButtonHTMLAttributes, ReactNode } from "react";
type SlideFillButtonSize = "sm" | "md" | "lg";
interface SlideFillButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "color"> {
children: ReactNode;
accentColor?: string;
size?: SlideFillButtonSize;
}
const SIZE_CLASSES: Record<SlideFillButtonSize, string> = {
sm: "px-4 py-2 text-sm",
md: "px-6 py-3 text-base",
lg: "px-8 py-4 text-lg",
};
export function SlideFillButton({
children,
accentColor = "#3f3cf2",
size = "md",
className,
style,
...props
}: SlideFillButtonProps) {
return (
<button
type="button"
className={["slide-fill-button", SIZE_CLASSES[size], className].filter(Boolean).join(" ")}
style={{ ...style, ["--slide-accent" as string]: accentColor }}
{...props}
>
<span className="slide-fill-button-fill" aria-hidden="true" />
<span className="slide-fill-button-label">{children}</span>
<style jsx>{`
.slide-fill-button {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
overflow: hidden;
border-radius: 0.5rem;
border: 1.5px solid var(--slide-accent);
background-color: transparent;
color: var(--slide-accent);
font-weight: 600;
cursor: pointer;
}
.slide-fill-button-fill {
position: absolute;
inset: 0;
background-color: var(--slide-accent);
transform: scaleX(0);
transform-origin: left center;
transition: transform 350ms cubic-bezier(0.16, 1, 0.3, 1);
}
.slide-fill-button:hover .slide-fill-button-fill,
.slide-fill-button:focus-visible .slide-fill-button-fill {
transform: scaleX(1);
}
.slide-fill-button-label {
position: relative;
transition: color 350ms cubic-bezier(0.16, 1, 0.3, 1);
}
.slide-fill-button:hover .slide-fill-button-label,
.slide-fill-button:focus-visible .slide-fill-button-label {
color: white;
}
.slide-fill-button:focus-visible {
outline: 2px solid var(--slide-accent);
outline-offset: 2px;
}
.slide-fill-button:disabled {
cursor: not-allowed;
opacity: 0.5;
}
@media (prefers-reduced-motion: reduce) {
.slide-fill-button-fill,
.slide-fill-button-label {
transition: none;
}
}
`}</style>
</button>
);
}
Usage
Import the component and use it like this.
import { SlideFillButton } from "./SlideFillButton";
export default function Example() {
return (
<SlideFillButton accentColor="#3f3cf2" size="md">
Get started
</SlideFillButton>
);
}
Dependencies
No external dependencies.
Usage notes
Pass an accentColor hex to change the outline/fill color, and size (sm/md/lg) to change padding.