Visit target
Define a standalone control that opens another Backlit view.
A visit target defines a standalone navigation control. Use it in an action bar, a table row action, or a lookup create control.
It uses kind: "visit" in the protocol. A link attachment uses kind: "link".
API
visitTo(
view: Linkable,
args?: unknown[] | ((row) => unknown[]),
presentation?:
| { text?: string; icon?: string; tooltip?: string; mode?: TargetMode; skip?: boolean; filters?: GetFiltersFor<View> }
| ((row) => { text?: string; icon?: string; tooltip?: string; skip?: boolean; filters?: GetFiltersFor<View> })
): VisitTarget
filters sets the state the target view opens with, as on linkTo. Either
form of the presentation can carry it.
visitTo(subscriberList, [], { text: 'Bounced', filters: { status: 'bounced' } })
Pass the view definition directly. visitTo does not accept a thunk because
it is used inside a view resolver. Use a thunk with linkTo when field
declarations create a module cycle.
args must match the target view parameters in length and order. Missing args
on an active target are an authoring error.
Return skip: true from the presentation callback to remove the control for
one row. Backlit checks skip before it resolves args. skip does not travel
in the protocol.
Use linkTo instead when a field value or a table row already supplies the
content to make clickable.
Complete controls
import {
callout,
defineResource,
fields,
linkTo,
panel,
submitTo,
table,
visitTo,
} from '@backlit/sdk'
import { z } from 'zod'
const orders = defineResource('orders', [
fields.text('id'),
fields.text('title'),
])
const detail = orders.view('detail', ['id'], (ctx) =>
callout(`Order ${ctx.paramValues.id}`)
)
const archive = orders.action(
'archive',
['id'],
z.object({}),
(ctx) => ctx.refresh()
)
const rename = orders.action(
'rename',
['id'],
z.object({ title: z.string().min(1) }),
(ctx) => ctx.notify(ctx.data.title)
)
orders.view('list', () =>
panel([
table([{ id: '42', title: 'Notebook' }])
.setFields(orders.pick('title'))
.onRowClick(linkTo(detail, (row) => [row.id]))
.setRowActions([
visitTo(detail, (row) => [row.id], {
text: 'Open',
mode: 'drawer',
}),
submitTo(
archive,
(row: { id: string }) => [row.id],
{
text: 'Archive',
intent: 'destructive',
}
).setDialog({
title: 'Archive this order?',
submitLabel: 'Archive',
}),
submitTo(
rename,
(row: { id: string }) => [row.id],
{
text: 'Rename',
}
)
.setDialog({ title: 'Rename order' })
.setFields(orders.pick('title')),
]),
]).setActions([
visitTo(detail, ['42'], {
text: 'Open order',
mode: 'modal',
}),
submitTo(rename, ['42'], {
text: 'Rename order',
primary: true,
})
.withInitialData({ title: 'Notebook' })
.setDialog({ title: 'Rename order' })
.setFields(orders.pick('title')),
])
)
export default orders{
"kind": "success",
"status": 200,
"node": {
"kind": "view",
"resource": "orders",
"name": "list",
"slots": {
"content": [
{
"kind": "panel",
"actions": [
{
"kind": "visit",
"resource": "orders",
"view": "detail",
"mode": "modal",
"args": [
"42"
],
"text": "Open order"
},
{
"kind": "action",
"form": {
"kind": "form",
"target": {
"resource": "orders",
"action": "rename",
"args": [
"42"
]
},
"slots": {
"content": [
{
"kind": "form-fields",
"fields": [
{
"kind": "text",
"name": "title",
"label": ""
}
]
}
]
},
"initial": {
"title": "Notebook"
}
},
"text": "Rename order",
"primary": true,
"dialog": {
"title": "Rename order"
}
}
],
"slots": {
"content": [
{
"kind": "table",
"fields": [
{
"kind": "text",
"name": "title",
"label": ""
}
],
"targets": [
{
"kind": "link",
"resource": "orders",
"view": "detail"
},
{
"kind": "visit",
"resource": "orders",
"view": "detail",
"mode": "drawer"
},
{
"kind": "action",
"form": {
"kind": "form",
"target": {
"resource": "orders",
"action": "archive"
},
"slots": {
"content": []
}
}
},
{
"kind": "action",
"form": {
"kind": "form",
"target": {
"resource": "orders",
"action": "rename"
},
"slots": {
"content": [
{
"kind": "form-fields",
"fields": [
{
"kind": "text",
"name": "title",
"label": ""
}
]
}
]
}
}
}
],
"data": [
{
"title": "Notebook",
"$click": {
"target": 0,
"args": [
"42"
]
},
"$actions": [
{
"target": 1,
"args": [
"42"
],
"text": "Open"
},
{
"target": 2,
"text": "Archive",
"intent": "destructive",
"dialog": {
"title": "Archive this order?"
},
"form": {
"target": {
"args": [
"42"
]
},
"submit": {
"label": "Archive"
}
}
},
{
"target": 3,
"text": "Rename",
"dialog": {
"title": "Rename order"
},
"form": {
"target": {
"args": [
"42"
]
},
"initial": {
"title": "Notebook"
}
}
}
]
}
]
}
]
}
}
]
}
}
}