From 824e7a8cf246031a7c47ea969ec8d764e975cfd5 Mon Sep 17 00:00:00 2001 From: Evan Sutherland Date: Sat, 28 Mar 2026 10:26:09 -0500 Subject: [PATCH] add documentation for recent features --- docs/advanced-concepts/hooks.md | 27 ++++++++++++- docs/advanced-concepts/rejections.md | 23 +++++++++++ docs/core-concepts/routes.md | 60 ++++++++++++++++++++++++++++ src/types/hooks.ts | 6 +-- 4 files changed, 111 insertions(+), 5 deletions(-) diff --git a/docs/advanced-concepts/hooks.md b/docs/advanced-concepts/hooks.md index ac3059a5..10c53d36 100644 --- a/docs/advanced-concepts/hooks.md +++ b/docs/advanced-concepts/hooks.md @@ -24,7 +24,11 @@ onAfterRouteEnter: (to, context) => { ### On Error -- **onError** Triggered whenever an unexpected error is thrown. Error hooks are run in the order they were registered. +- **onError** Triggered whenever an unexpected error is thrown. Error hooks are run in the order they were registered. The hook is provided both the error and the [error context](/advanced-concepts/hooks#error-context). + +### On Rejection + +- **onRejection** Triggered whenever a rejection is triggered. Rejection hooks are run in the order they were registered. The hook is provided both the rejection and the [rejection context](/advanced-concepts/hooks#rejection-context). ## Context @@ -43,6 +47,8 @@ If the hooks lifecycle is a [before](/advanced-concepts/hooks#before-hooks) hook | ---- | ---- | | abort | Stops the router from continuing with route change | +### Error Context + If the hook is `onError`, you'll also have access to the following properties in your context: | Property | Description | @@ -50,13 +56,22 @@ If the hook is `onError`, you'll also have access to the following properties in | to | What was the destination route prior to the error being thrown | | source | String value indicating where the error occurred. Possible values are `'props'`, `'hook'`, and `'component'` | +### Rejection Context + +If the hook is `onRejection`, you'll also have access to the following properties in your context: + +| Property | Description | +| ---- | ---- | +| to | What was the destination route prior to the rejection being triggered | +| from | What was the route prior to the rejection being triggered | + ## Levels Hooks can be registered **globally**, on your **route**, or from within a **component**. This is useful for both providing the most convenient devx, but also can be a useful tool for ensuring proper execution order of your business logic. ### Execution Order -1. Global before hooks +1. Global before hooks 2. Route before hooks 3. Component before hooks 4. Component after hooks @@ -79,6 +94,14 @@ route.onAfterRouteEnter((to, context) => { }) ``` +### Rejection + +```ts +rejection.onRejection((rejection, context) => { + ... +}) +``` + ### Component In order to register a hook from within a component, you must use the [composition API](https://vuejs.org/guide/extras/composition-api-faq.html#composition-api-faq). diff --git a/docs/advanced-concepts/rejections.md b/docs/advanced-concepts/rejections.md index a786170d..3417161c 100644 --- a/docs/advanced-concepts/rejections.md +++ b/docs/advanced-concepts/rejections.md @@ -88,3 +88,26 @@ const rejection = useRejection() const rejectionType = computed(() => rejection.value.type) ``` + +## Title + +The `setTitle` callback is used to set the document title for the rejection. The callback is given the resolved route and a context object. The callback can be async, and should return a string that should be set as the document.title. + +The context object has the following properties: + +| Property | Type | Description | +| -------- | ---- | ----------- | +| from | ResolvedRoute | The route that is being navigated from. | +| getParentTitle | () => Promise | Promise that resolves to the title of the parent route. | + +```ts +import { createRejection } from '@kitbag/router' + +const authNeededRejection = createRejection({ + type: 'AuthNeeded', +}) + +authNeededRejection.setTitle((to, context) => { + return `Unauthorized!` +}) +``` diff --git a/docs/core-concepts/routes.md b/docs/core-concepts/routes.md index 8d7080db..cfb02e0e 100644 --- a/docs/core-concepts/routes.md +++ b/docs/core-concepts/routes.md @@ -197,6 +197,37 @@ home.onBeforeRouteEnter(() => { }) ``` +## Title + +The `setTitle` callback is used to set the document title for the route. The callback is given the resolved route and a context object. The callback can be async, and should return a string that should be set as the document.title. + +The context object has the following properties: + +| Property | Description | +| -------- | ----------- | +| from | What was the route prior to the hook's execution | +| getParentTitle | A function that returns the title of the parent route. | + +```ts +import { createRoute } from '@kitbag/router' + +const user = createRoute({ + name: 'user.profile', + path: '/user/:userId', +}) + +user.setTitle((to, context) => { + const user = userStore.getUser(to.params.userId) + return `Profile: ${user.name}` +}) +``` + +:::info + +There is also a `setTitle` callback on [rejections](/advanced-concepts/rejections#title). + +::: + ## Context The context for a route is the collection of routes and rejections that are associated with the route. The context you provide to this route will be available to the hooks and props callback functions for this route. @@ -236,3 +267,32 @@ const home = createRoute({ }, }) ``` + +## Hoisting + +When the `hoist` property is true, the route will be treated as a root route. This allows you to leverage the component nesting without having to use a nested URL. + +```ts +const parentRoute = createRoute({ + name: 'parent', + path: '/parent', +}) + +const regularChildRoute = createRoute({ + parent: parentRoute, + name: 'parent.regular', + path: '/regular', +}) + +const hoistedExample = createRoute({ + parent: parentRoute, + name: 'parent.nested', + path: '/nested', + hoist: true, +}) + +regularChildRoute.stringify() +// ^ "/parent/regular" +hoistedExample.string() +// ^ "/nested" +``` diff --git a/src/types/hooks.ts b/src/types/hooks.ts index bfbe9f8a..d86fca83 100644 --- a/src/types/hooks.ts +++ b/src/types/hooks.ts @@ -289,7 +289,7 @@ export type RejectionHookContext< TRouteFrom extends Route = TRoutes[number] > = { to: ResolvedRouteUnion | null, - from: ResolvedRouteUnion | null + from: ResolvedRouteUnion | null, } export type RejectionHook< @@ -307,7 +307,7 @@ export type AddRejectionHook< > = (hook: RejectionHook) => HookRemove export type RejectionHookRunner = ( - rejection: TRejection, + rejection: TRejection, context: { to: RouterResolvedRouteUnion | null, from: RouterResolvedRouteUnion | null } ) => void @@ -344,6 +344,6 @@ export type ErrorHookRunnerContext = { } export type ErrorHookRunner = ( - error: unknown, + error: unknown, context: ErrorHookRunnerContext ) => void