GradientBorder
Animated gradient border wrapper for highlighting cards, hero panels, and callout containers.
Usage
Loading demo...
Semantic Root
Use as when the highlighted surface should be a semantic landmark or list item.
<template>
<TxGradientBorder as="section" :border-width="3" :border-radius="20" padding="1rem 1.25rem">
<article class="rounded-[16px] bg-[var(--tx-bg-color)] p-4">
<h3>Release candidate</h3>
<p>Ready for manual QA.</p>
</article>
</TxGradientBorder>
</template>
Custom Units
Numeric sizing props become pixels. String props are preserved, so CSS variables and multi-value padding are valid.
<template>
<TxGradientBorder
border-width="0.125rem"
border-radius="var(--radius-lg)"
padding="1rem 1.5rem"
:animation-duration="6"
>
<div class="rounded-[inherit] bg-[var(--tx-bg-color)] p-4">
Uses project tokens
</div>
</TxGradientBorder>
</template>
Best Practices
- Put a real surface inside the wrapper and align its radius with
borderRadius - borderWidthto avoid exposed corners. - Use semantic
asvalues for sections, list items, or articles instead of adding extra wrapper landmarks around the component. - Keep
animationDurationslower on dense pages; multiple fast animated borders compete with primary content. - Avoid wrapping controls whose focus rings must escape the border unless the inner content handles focus styling itself.
- Prefer one highlighted gradient surface per view region; use
TxBadgeorTxTagfor smaller status accents. - Under
prefers-reduced-motion: reducethe rotation is disabled and the border settles at a static gradient angle.
API Reference
Props
| Prop | Type | Default | Description |
|---|---|---|---|
as | string | 'div' | Root element tag rendered by the wrapper. |
borderWidth | string | number | '2px' | Gradient border width. Numbers become px. |
borderRadius | string | number | '12px' | Border radius applied to the wrapper and gradient layer. Numbers become px. |
padding | string | number | '12px' | Padding applied to the inner content wrapper. Numbers become px. |
animationDuration | number | 4 | Gradient rotation duration in seconds. |
Slots
| Slot | Props | Description |
|---|---|---|
default | - | Content rendered inside .tx-gradient-border__inner. |
Events
No public events are emitted.
Exposed Methods
No public instance methods are exposed.
CSS Variables
| Variable | Source | Description |
|---|---|---|
--tx-gradient-border-width | borderWidth | Border thickness and blur distance. |
--tx-gradient-border-radius | borderRadius | Wrapper and gradient radius. |
--tx-gradient-inner-padding | padding | Inner wrapper padding. |
--tx-gradient-duration | animationDuration | Rotation animation duration. |
--tx-gradient-angle | internal animation | Registered angle property used by the gradient. |
Overview
- The root element is rendered by
<component :is="as">; default root isdiv. - The component renders one inner wrapper,
.tx-gradient-border__inner, around the default slot. borderWidth,borderRadius, andpaddingaccept numbers or strings. Numbers are normalized to px; strings are passed through unchanged.animationDurationis numeric seconds and is written to--tx-gradient-durationwith anssuffix.- The gradient ring is drawn in a separate
aria-hiddenlayer,.tx-gradient-border__ring, withpointer-events: none; the slotted content owns all actual interaction. - The ring is cut from a filled box, so it follows
borderRadius, and its blur is not clipped: the glow spreads past the wrapper's edge on both sides. .tx-gradient-border__innerusesoverflow: hiddenwith the same radius, so child focus rings or shadows can be clipped when they extend outside it.
Technologies
- Reviewed against
packages/tuffex/packages/components/src/gradient-border/index.ts,TxGradientBorder.vue, andgradient-border.test.ts. - Props are declared in
index.ts; there is no separatesrc/types.tsfor this component. - The animated gradient is a non-interactive layer. Slotted content remains responsible for all interaction and focus styling.
- Ring drawing: the ring used to be a blurred
border-imageon a::beforeinside anoverflow: hiddenroot.border-imageignoresborder-radius, so the frame was square and the rounded clip cut each corner away, and the same clip cut the outer half of the blur off flat. The blur now sits on its own layer and the ring shape on its child, becausefilterruns beforemaskon a single element. - Component source:
packages/tuffex/packages/components/src/gradient-border/src/TxGradientBorder.vue. - Types:
packages/tuffex/packages/components/src/gradient-border/index.ts. - Verified coverage: Coverage:
packages/tuffex/packages/components/src/gradient-border/__tests__/gradient-border.test.tsverifies default root rendering, custom root tags, numeric unit normalization, duration seconds, and string CSS unit preservation.
查看源码
packages/tuffex/packages/components/src/gradient-border/index.ts