Skip to main content

Adopting Widgemo

This guide is for teams adding @widgemo/widgemo-core to an already-running application — not a greenfield build. The goal is not a full rewrite. The goal is a controlled, incremental replacement of existing table, card, and list surfaces with Widgemo, one widget at a time, while keeping the rest of the app undisturbed.


1. Install and Verify Dependencies​

npm install @widgemo/widgemo-core

@widgemo/widgemo-core requires React 18+ and React DOM as peer dependencies. Verify they are already present:

npm list react react-dom

If either is missing or below v18, install or update them before proceeding.


2. Import the Stylesheet​

Import the Widgemo stylesheet once at your app root (e.g. main.tsx, App.tsx, or your global CSS entry point):

import '@widgemo/widgemo-core/style.css';

This must load before any Widgemo component renders. Importing it more than once has no effect, but importing it after the component renders will cause a flash of unstyled content.


3. Make Theming Decisions Early​

This is the step most teams skip, and it causes the most friction later.

Widgemo ships with a default light and dark theme that works out of the box. In many apps, the default will look noticeably off compared to the surrounding UI — different button colors, border radii, background tones, or typography. Aligning Widgemo's visual style to your existing app is much easier to do at the start than to retrofit after several widgets are live.

The basics: wrap with WidgemoThemeProvider​

Every Widgemo instance should be inside a WidgemoThemeProvider. The provider is where you control theming.

import { Widgemo, WidgemoThemeProvider } from '@widgemo/widgemo-core';

function MyWidget({ rows }) {
return (
<WidgemoThemeProvider theme="light">
<Widgemo data={rows} config={config} />
</WidgemoThemeProvider>
);
}

If your app already has a dark mode, pass theme="auto" to follow the system preference, or wire it to your own theme state:

<WidgemoThemeProvider theme={userPrefersDark ? 'dark' : 'light'}>

Customising to match your app​

For apps with a strong existing visual identity, pass a theme object to override specific tokens:

<WidgemoThemeProvider theme={{
colors: {
actionButtonBg: '#1a1a2e',
actionButtonColor: '#ffffff',
},
zone: {
backgroundColor: '#f8f9fa',
borderRadius: '0.5rem',
},
}}>
<Widgemo data={rows} config={config} />
</WidgemoThemeProvider>

You can also apply per-Widgemo overrides via config.zones.content.themeOverrides when individual Widgemos need to deviate from the shared provider theme.

For teams with a design system or CSS custom property library, Widgemo's --widgemo-* CSS variables can be overridden globally:

/* In your global stylesheet, after importing widgemo-core/style.css */
:root {
--widgemo-color-actionButtonBg: #1a1a2e;
--widgemo-action-button-border-radius: 0.25rem;
}

Reference: Theming Concepts · Theme API


4. Replace One Surface at a Time​

Do not plan a big-bang migration. Pick the simplest existing table or card list and replace it first.

Rollout order that minimises risk:

  1. Pick a read-heavy, low-interaction surface (a simple data list with no actions) as the first target.
  2. Keep your existing data fetching and state management entirely unchanged — pass the same data array to <Widgemo>.
  3. Start with mode: 'table' and layout: { type: 'auto' }. Widgemo will infer field labels from data keys.
  4. Declare explicit fields only when you need to control labels, types, or rendering.
  5. Once that Widgemo is stable, move to the next surface.
// Before: your existing component
function AccountsTable({ rows }) {
return (
<table>
<thead>…</thead>
<tbody>{rows.map(r => <tr key={r.id}>…</tr>)}</tbody>
</table>
);
}

// After: direct replacement, same data prop
function AccountsTable({ rows }) {
return (
<WidgemoThemeProvider theme="light">
<Widgemo
data={rows}
config={{
zones: {
header: { title: 'Accounts' },
content: {
mode: 'table',
item: {
fields: [
{ key: 'name', label: 'Account' },
{ key: 'owner', label: 'Owner' },
{ key: 'status', label: 'Status', renderAs: 'badge' },
],
layout: { type: 'auto' },
},
},
},
}}
/>
</WidgemoThemeProvider>
);
}

Minimum Viable Replacement

A realistic first replacement: existing data unchanged, rendering moved to Widgemo.

Accounts

Same data, new rendering primitive

Account
Owner
Status
Acme NorthAuroraactive
Acme SouthMateopending

5. Wire Actions and Interactions to Existing App Logic​

This is where Widgemo connects back to your app. Actions (buttons on items or zones) and gestures (item clicks, drags) fire an InteractionContext payload to a single handler. You decide what to do with it.

Zone and item actions​

Declare actions in config, and route their events to existing handlers via interactions.onEvent:

const config = {
interactions: {
onEvent: (ctx) => {
if (ctx.interactionId === 'edit-account') {
openEditModal(ctx.entity); // your existing function
}
if (ctx.interactionId === 'delete-account') {
deleteAccount(ctx.entity.id); // your existing function
}
},
},
zones: {
content: {
mode: 'table',
actions: [
{ id: 'edit-account', label: 'Edit', icon: 'edit', placement: 'pinned' },
{ id: 'delete-account', label: 'Delete', icon: 'delete', placement: 'menu', variant: 'danger' },
],
item: { fields: […], layout: { type: 'auto' } },
},
},
};

The InteractionContext includes kind (whether it was an item action, zone action, or gesture), interactionId, interactionLabel, entity (the row that was acted on), and data (the full visible dataset).

Item-click gestures​

If your existing table rows are clickable (navigate to a detail view, open a panel), declare an item-click gesture:

const config = {
interactions: {
onEvent: (ctx) => {
if (ctx.kind === 'item-click') {
router.push(`/accounts/${ctx.entity.id}`); // your existing navigation
}
},
},
zones: {
content: {
mode: 'table',
gestures: [{ type: 'item-click' }],
item: { fields: […], layout: { type: 'auto' } },
},
},
};

Reference: Content Config: Actions and Interactions · Content Config: Gestures


6. Progressive Discovery and Enrichment​

Once a Widgemo is live and stable, you can progressively enrich it without risk:

  • Add renderAs to fields for richer visual output (badges, progress bars, currency, links)
  • Add sortable: true to fields that should be user-sortable
  • Add config.zones.content.filtering or sorting for declarative data behavior
  • Switch mode from table to grid or board if the data suits a different layout
  • Add modeConfig to tune mode-specific options

Each of these is an additive config change. Nothing in your data layer or interaction handlers changes.


Practical Checklist​

StepDone?
@widgemo/widgemo-core installed☐
Peer dependencies (React 18+) verified☐
Stylesheet imported at app root☐
WidgemoThemeProvider wrapping each Widgemo☐
Theme tokens reviewed against app brand☐
First surface replaced and validated☐
Actions wired to existing app handlers☐
Gestures wired where rows were previously clickable☐

Further Reading​

AI-Assisted Adoption​

The docs/adoption/ folder in the widgemo-core GitHub repo contains copy-paste prompts for AI coding agents:

FilePurpose
AGENT_PROMPTS_ADOPTION.mdDiscovery, refactor, and validation prompts
ADOPTION_DISCOVERY.mdRead-only discovery instructions
ADOPTION_REFACTOR.mdRefactor implementation rules
ADOPTION_BRIEF_TEMPLATE.mdSource-of-truth brief template