# Introduction Source: https://solid-route-progress.vercel.app/docs ```tsx import { Router } from '@solidjs/router' import { Suspense } from 'solid-js' import { RouteProgress } from 'solid-route-progress/router' import 'solid-route-progress/style.css' ( <> {props.children} )} /> ``` ## Entry points | Entry | Exports | | --------------------------------- | ------------------------------------------------------------------------------ | | `solid-route-progress` | `createProgress`, ``, ``, ``, `useProgress()`, `createCrossDocumentProgress()`, `IGNORE_ATTRIBUTE` | | `solid-route-progress/router` | ``, `createRouteProgress()` | | `solid-route-progress/navigation` | ``, `createNavigationProgress()` | | `solid-route-progress/style.css` | the stylesheet | ## What JavaScript writes | Written | On | Value | | -------------- | -------- | -------------------------------------------- | | `--sp-value` | the bar | `0` to `1`, the target of the CSS transition | | `--sp-speed` | the bar | the `speed` option | | `data-state` | the bar | `idle \| trickle \| active \| done` | | `data-error` | the bar | during the done phase of a failed load | | `data-sp-busy` | `` | while any bar is visible | Everything else is CSS. ## How it works 1. `start()` waits `delay` (200 ms), then flips `data-state` to `trickle` and sets `--sp-value` to `trickleTo` (0.95). The stylesheet's `trickle` rule has a 10 s transition on `translate` whose curve races out and then crawls. It is one transition, and no timer steps it. 2. `set(n)` switches to `active`, which leaves the bar on its short `--sp-speed` transition for the hop, then hands back to `trickle`. CSS transitions interrupt from the _current_ animated value, so there is nothing to sync. 3. Once the last hold is released (or on `done()`), the bar hops to 100% in the `done` state (with `data-error` if a hold was released as an `'error'`; a `'cancel'` skips this step and fades straight out), then `idle` fades the whole bar out with `opacity` + a delayed `visibility: hidden`. The bar itself is parked back at `--sp-start` only after the fade has finished. Both steps take `speed`, which the bar also writes to `--sp-speed`, so the CSS and the timers never disagree. A load that starts during this phase waits for the fade and for `delay`, whichever is longer. 4. If the load ends while `delay` is still pending, or before the browser painted the bar (tracked with a single `requestAnimationFrame`), the bar is dropped silently. ## Size What each setup adds to your bundle, in bytes, after tree-shaking: | Import | min | gzip | brotli | | ----------------------------------------------------------- | ---- | ---- | ------ | | ``, `solid-route-progress/router` | 4838 | 2363 | 2135 | | ``, `solid-route-progress/navigation` | 4300 | 2099 | 1905 | | `createProgress` alone | 1721 | 908 | 841 | | `solid-route-progress/style.css` | 1089 | 510 | 418 | Zero dependencies. The bar only moves `opacity` and `translate`, so its animations run on the compositor thread and stay smooth while the next route keeps the main thread busy. ## Next [Installation](https://solid-route-progress.vercel.app/docs/installation.md) · [Quick start](https://solid-route-progress.vercel.app/docs/quick-start.md) · [Examples](https://solid-route-progress.vercel.app/docs/examples.md) --- # Installation Source: https://solid-route-progress.vercel.app/docs/installation ```sh npm i solid-route-progress # or pnpm add solid-route-progress # or yarn add solid-route-progress # or bun add solid-route-progress ``` | Peer | Version | | ----------------- | ---------------------------------------------- | | `solid-js` | 1.9 or a later 1.x | | `@solidjs/router` | 0.15 or 1.x, for `solid-route-progress/router` | Solid 2 is not supported yet. ## Stylesheet ```css /* app.css */ @import 'tailwindcss'; /* optional */ @import 'solid-route-progress/style.css'; ``` ```ts import 'solid-route-progress/style.css' ``` ## Browsers The bar draws in Chrome and Edge 111, Firefox 113 and Safari 15.4 or later (`@layer`, plus `oklch()` for the default color). | Feature | Chrome / Edge | Firefox | Safari | Without it | | ----------------------------------------------------------- | ------------- | ------- | ------ | --------------------------------------------- | | `linear()` trickle curve | 113 | 112 | 17.2 | the drift eases with `ease` instead | | `@property`, for `--sp-value` on your own elements | 85 | 128 | 16.4 | those elements jump; the bar is unaffected | | `:dir()`, for right-to-left pages | 120 | 49 | 16.4 | the bar fills from the left under `dir="rtl"` | | Navigation API, for cross-document and `NavigationProgress` | 102 | 147 | 26.2 | those navigations are not tracked | ## Builds | Export condition | Build | | ---------------- | ----------------------------------------------------------------------- | | `solid` | JSX untouched; SolidStart and `vite-plugin-solid` compile it themselves | | default | DOM-compiled, no server rendering | | `development` | dev warnings; production resolves it to `false` and drops them | --- # Quick start Source: https://solid-route-progress.vercel.app/docs/quick-start ## `@solidjs/router` ```tsx import { Router, Route } from '@solidjs/router' import { Suspense } from 'solid-js' import { RouteProgress } from 'solid-route-progress/router' import 'solid-route-progress/style.css' const Layout = (props) => ( <> {props.children} ) ``` ## SolidStart ```tsx // src/app.tsx import { Router } from '@solidjs/router' import { FileRoutes } from '@solidjs/start/router' import { Suspense } from 'solid-js' import { RouteProgress } from 'solid-route-progress/router' import './app.css' export default function App() { return ( ( <> {props.children} )} > ) } ``` A complete app, themed with Tailwind: [`examples/solidstart`](https://github.com/kecan0406/solid-route-progress/tree/main/examples/solidstart) ([open in StackBlitz](https://stackblitz.com/github/kecan0406/solid-route-progress/tree/main/examples/solidstart?file=src/app.tsx)). ## Without a router ```tsx import { NavigationProgress } from 'solid-route-progress/navigation' const Layout = (props) => ( <> {props.children} ) ``` [Navigation API](https://solid-route-progress.vercel.app/docs/navigation-api.md) ## Driving it yourself ```tsx import { ProgressProvider, useProgress } from 'solid-route-progress' {children} ``` ```ts const progress = useProgress() await progress.track(fetch('/api/items')) const release = progress.start() progress.set(0.6) release() // release('error') · release('cancel') ``` [Controller](https://solid-route-progress.vercel.app/docs/controller.md) · [Examples](https://solid-route-progress.vercel.app/docs/examples.md) --- # Styling Source: https://solid-route-progress.vercel.app/docs/styling ## Custom properties | Property | Default | Meaning | | ----------------------- | ---------------------- | ------------------------------------------------------------ | | `--sp-color` | `oklch(0.65 0.14 241)` | bar color | | `--sp-height` | `3px` | bar thickness | | `--sp-z-index` | `9999` | bar stacking order | | `--sp-start` | `0.08` | value the bar is revealed at | | `--sp-trickle-duration` | `10s` | how long the loading drift takes | | `--sp-trickle-easing` | `linear(…)` | shape of the drift | | `--sp-speed` | the `speed` option | read-only; set it through [`speed`](https://solid-route-progress.vercel.app/docs/controller.md#options) | Set them on `:root`, in Tailwind's `@theme`, on a class, or inline. ```css :root { --sp-color: oklch(0.62 0.19 264); /* or var(--color-indigo-500) */ --sp-height: 2px; } ``` ```css :root { color-scheme: light dark; --sp-color: light-dark(oklch(0.55 0.2 264), oklch(0.75 0.12 264)); } ``` ## Utilities ```tsx ``` The stylesheet sits in the `components.sprogress` sublayer, so utilities, your own `@layer components` rules and unlayered CSS all beat it without `!important`. ## Hooks for the rest of the page | Hook | Where | When | | ------------------------------------------------ | -------- | --------------------------- | | `data-state="idle \| trickle \| active \| done"` | the bar | always | | `data-error` | the bar | done phase of a failed load | | `data-sp-busy` | `` | while any bar is visible | ```tsx
…
``` ```tsx // opt out // also aria-busy="true" ``` ## Inside a container ```tsx
…
``` ## Your own template ```tsx import { Show } from 'solid-js' import { Bar, useProgress } from 'solid-route-progress' const Percent = () => { const progress = useProgress() // `value()` is the target, and while trickling that is `trickleTo`, not the drawn position return ( {Math.round(progress.value() * 100)}% ) } ``` `--sp-value` is registered as a ``, so your own elements can transition it. Keep the `var()` fallbacks. ```css .ring { background: conic-gradient( var(--sp-color, oklch(0.65 0.14 241)) calc(var(--sp-value) * 1turn), transparent 0 ); transition: --sp-value var(--sp-trickle-duration, 10s) var(--sp-trickle-easing, ease-out); } ``` ## Recipes They are not shipped, so they cost nothing until you paste them. See them live in [Examples](https://solid-route-progress.vercel.app/docs/examples.md#styling-recipes). ### Failed loads ```css .sprogress[data-error] { --sp-color: oklch(0.63 0.19 23); } ``` ### Spinner ```tsx