Appearance
Adapters
Core has no opinion about networking, routing, stores, notifications or modal systems. Connect those through small adapters owned by the app or by integration packages.
ts
const actionRunner = new ActionRunner({
request: ({ endpoint, method, body, params, headers }) =>
fetch(endpoint, {
method,
headers: headers as HeadersInit,
body: method === 'GET' ? undefined : JSON.stringify(body),
}).then((response) => response.json()),
toast: (action) => toast.show(action.message, { status: action.status }),
navigate: (action) => router.push({
pathname: action.to,
query: action.query,
}),
confirm: (config) => confirmDialog.open(config),
modal: {
open: (action, context) => modal.open({
centered: action.centered,
content: renderSDUI(action.children, context),
}),
close: () => modal.close(),
},
drawer: {
open: (action) => drawer.open(action.drawerId, action.payload),
close: (action) => {
if (action.drawerId) {
drawer.close(action.drawerId)
return
}
drawer.closeCurrent()
},
},
})renderSDUI, modal, and drawer in this example are app-owned helpers. The core package only calls adapter methods with openModal, closeModal, drawerOpen, and drawerClose action objects.
For larger apps, split adapters by concern:
- Navigation & Screens for route context and screen loading.
- Data & Cache Adapters for requests, invalidation and screen stores.
- Modals & Drawers for overlay action flows.
- Vue, Vue Router, TanStack Query, TanStack Router, React Router, Next App Router, Browser History and RTK Query for integration patterns.
To support another framework, implement a renderer that:
- accepts a
ComponentRegistry. - walks
SDUINodetrees. - renders registered components.
- passes actions to
ActionRunner. - handles unknown components through a fallback.