Embed in a React app
Show a tablewalk App, or one of its lists, records or dashboards, inside your own React app’s routes, under your router.
import { TablewalkApp, TablewalkProvider } from 'tablewalk/react';
<TablewalkProvider endpoint="/api/tw"> <TablewalkApp app="compass" basePath="/crm" /></TablewalkProvider>;The endpoint is the tablewalk server: the handler
mounted in your server with
basePath: '/api/tw', or a tablewalk process your server rewrites /api/tw
to. basePath is where your app shows the App: /crm/leads/127 is lead 127.
Your router owns the address bar, so Back, Forward and your own links move
the App too.
The general path puts this beside a route and a design of your own, in one sample App.
React Router
Section titled “React Router”import { useReactRouterNavigator } from 'tablewalk/react/react-router';
function Crm() { return ( <TablewalkProvider endpoint="/api/tw" navigator={useReactRouterNavigator()}> <TablewalkApp app="compass" basePath="/crm" /> </TablewalkProvider> );}// <Route path="/crm/*" element={<Crm />} />TanStack Router
Section titled “TanStack Router”import { useTanStackNavigator } from 'tablewalk/react/tanstack-router';
const crm = createRoute({ getParentRoute: () => root, path: '/crm/$', component: Crm });function Crm() { return ( <TablewalkProvider endpoint="/api/tw" navigator={useTanStackNavigator()}> <TablewalkApp app="compass" basePath="/crm" /> </TablewalkProvider> );}Next.js
Section titled “Next.js”'use client';import { useNextNavigator } from 'tablewalk/react/next';
export default function Crm() { return ( <TablewalkProvider endpoint="/api/tw" navigator={useNextNavigator()}> <TablewalkApp app="compass" basePath="/crm" /> </TablewalkProvider> );}Another router
Section titled “Another router”import { routerNavigator, STATE_KEY, walkOf } from 'tablewalk/react';
const navigator = routerNavigator({ read: () => ({ pathname: router.pathname, search: router.search, state: walkOf(router.state) }), push: (href, state) => router.push(href, { [STATE_KEY]: state }), replace: (href, state) => router.replace(href, { ...router.state, [STATE_KEY]: state }),});router.subscribe(() => navigator.hostMoved()); // on every move: the App's own are told apartPass it as the Provider’s navigator. The App’s walk rides in the entry’s state under STATE_KEY, beside your
router’s own. With no router, the Provider uses window.history
(browserNavigator()).
On the server every element renders an empty slot (or its fallback); the
App loads in the browser the first time an element is on screen.
One list, record or dashboard
Section titled “One list, record or dashboard”<TablewalkList app="compass" view="leads" tab="working" onOpenRecord={(lead) => openDrawer(lead.key)} /><TablewalkRecord app="compass" resource="lead" id={127} /><TablewalkDashboard app="compass" view="sales-dashboard" period="last-30-days" /><TablewalkPage app="depot" page="pick-walk" params={{ list: '12' }} />A surface has no App chrome and keeps its own address, so your address bar
does not change. TablewalkPage draws one of the App’s
free-form pages by its path. onOpenRecord hands you the record a list opens; without
it, the record opens in place. A page shows one tablewalk element at a time.
Sign-in
Section titled “Sign-in”With auth left out, the App uses tablewalk’s own session cookie. To sign
people in with your app’s session instead, mint an assertion on your server
and hand it over:
<TablewalkProvider endpoint="/api/tw" auth={{ assertion: () => fetch('/my/tablewalk-assertion').then((r) => r.text()) }}>On the same origin the exchange sets the session cookie. On another origin
the session is a token kept in memory, and is renewed before it lapses; the
server must list your page’s origin (embed.origins on the
handler).
Before it draws, the Provider asks the server once: the sign-in comes back with the first page’s data in it, so the App starts on one request.
The assistant
Section titled “The assistant”<TablewalkAssistant app="compass" conversation={id} />The App’s assistant as a page of your app, under the same Provider.
Styles
Section titled “Styles”You import no CSS. tablewalk’s styles are scoped to its own elements, in one
cascade layer named tablewalk, so they never reach your page. Your styles
in cascade layers (a reset, Tailwind’s base) do not reach the App. Your
unlayered element rules (button { … }) still do; put them in a layer.
theme, mode and density on the Provider choose the look. theme is a
look’s name, or your own made with defineTheme:
import { defineTheme } from 'tablewalk/app';
const harbor = defineTheme({ id: 'harbor', label: 'Harbor', extends: 'mono', colors: { light: { accent: '#0b6e4f' } } });<TablewalkProvider endpoint="/api/tw" theme={harbor}>