SwBackTop
SwBackTop is a back-to-top button for long pages: once scrolling passes the threshold (about one viewport by default) a round button fades in at the bottom-right; clicking smooth-scrolls back to the top. Users with prefers-reduced-motion: reduce get an instant jump instead (no long smooth animation). The scroll listener is rAF-throttled + passive, registered client-side only — zero SSR side effects.
The button is 2.75rem visually with a built-in sw-hit-area touch target (44×44); its aria-label comes from the framework's built-in trilingual dictionary (回到顶部 / 回到頂部 / Back to top) and follows the site language.
Site-wide setup is one line: mount
<SwBackTop />inlayouts/default.vue(listens to window scroll). The demos below usetargetpointing at local scroll containers so they can run inside a docs page — the button appears at the viewport's bottom-right (position: fixed).
Basic usage (target container)
Scroll the pane past the threshold → button fades in → click scrolls the pane back to top
<!-- Site-wide default: mount once in layouts/default.vue, listens to window -->
<SwBackTop />
<!-- Local scroll layout: target a scroll container (CSS selector) -->
<SwBackTop target=".scroll-pane" />
Custom threshold
threshold (px) controls how far the user must scroll before the button appears; default is about one viewport (window.innerHeight / container clientHeight):
<SwBackTop :threshold="200" />
Slot rendering
The #default slot replaces the default arrow icon (text or your icon library both work):
Slot-rendered “TOP” text button
<SwBackTop><PhRocket :size="20" /></SwBackTop>
Token repositioning & theming
Position / size / colors all go through --sw-back-top-* tokens — override in overrides.css, no :deep needed:
Brand color + larger size + custom position
/* overrides.css: make room for a bottom TabBar on mobile + brand color */
:root {
--sw-back-top-bottom: 5.5rem;
--sw-back-top-bg: var(--primary);
--sw-back-top-color: var(--primary-foreground);
}
Props
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
threshold | number | undefined | Appearance threshold (px). Unset = about one viewport (window.innerHeight / container clientHeight, not recomputed on resize) | |
target | string | undefined | Scroll container CSS selector; unset listens to window. If the selector matches nothing: dev warn + the component becomes a no-op |
Slots
| Name | Scope | Description |
|---|---|---|
default | — | Button content, defaults to an inline up-arrow SVG |
Styling Tokens
| Token | Default | Applies to |
|---|---|---|
--sw-back-top-right | 1.5rem | Distance from viewport right edge |
--sw-back-top-bottom | 2rem | Distance from viewport bottom edge |
--sw-back-top-size | 2.75rem | Button diameter |
--sw-back-top-bg | var(--card) | Background |
--sw-back-top-color | var(--foreground-soft) | Icon / text color |
--sw-back-top-z | 90 | Stacking level (below the common nav at 100) |
Caveats
- No custom events: clicking simply scrolls to top; for analytics wrap the click outside or use
useTracker(tier-③ pure utility component, no:trackprop). - Under
prefers-reduced-motion: reduce: scroll-to-top becomes an instant jump and the fade transition is disabled (UX-004). - Sites with a bottom TabBar on mobile: override
--sw-back-top-bottomto make room (e.g.5.5rem) — the framework does not ship breakpoint offsets (TabBar height is business knowledge).