Buttons

Shiny Button

A bordered button with a light sweep that crosses it on hover.

Shiny Button keeps a quiet outline at rest and slides a diagonal light band across its face when the pointer enters. The band starts fully outside the left edge and travels past the right one, so the button reads as polished rather than as a permanent gradient.

Everything is CSS: the sweep is a transform transition driven by the group-hover state, so it costs one composited layer and nothing per frame.

Usage

The sweep is a single gradient that slides across on hover, then waits off-screen until the next one.

<template>
  <div class="flex w-full flex-col items-center gap-4 py-6">
    <MShinyButton>
      Hover for the shine
    </MShinyButton>
  </div>
</template>

Customize

Customize

No customizable props detected for this component.

Props

Prop Type Default Description
classstring''CSS classes for the button itself.

Slots

Slot Props Description
default-The button's label.

UI

This component's theme exposes the slots below. Override any of them per instance with the ui prop, or app-wide under ui.shinyButton in app.config.ts.

Prop Type Default Description
uiobject-Per-slot classes merged over the theme defaults.
Slot Props Description
root-group relative inline-flex items-center justify-center overflow-hidden rounded-lg border border-default bg-default px-6 py-3 text-sm font-medium text-highlighted transition hover:border-accented active:scale-[0.98]
shine-pointer-events-none absolute inset-y-0 -left-full w-full bg-gradient-to-r from-transparent via-white/25 to-transparent transition-transform duration-700 group-hover:translate-x-[300%]
label-relative z-10

Accessibility

The root is a real <button type="button">, so keyboard activation and the focus ring come from the browser. The sweep is decorative and marked aria-hidden. Hover is the only trigger, so a keyboard or touch user simply sees the resting outline — nothing is hidden behind the effect.

Copyright © 2026