@mercurjs/docs 2.2.0-canary.40 → 2.2.0-canary.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/content/learn/concepts.mdx +1 -1
- package/content/references/workflows/product/confirm-products.mdx +2 -0
- package/content/references/workflows/product/reject-product.mdx +2 -0
- package/content/references/workflows/product/request-product-change.mdx +2 -0
- package/content/references/workflows/seller/approve-seller.mdx +2 -0
- package/content/references/workflows/seller/suspend-seller.mdx +2 -0
- package/content/references/workflows/seller/terminate-seller.mdx +2 -0
- package/content/references/workflows/seller/unsuspend-seller.mdx +2 -0
- package/content/references/workflows/seller/unterminate-seller.mdx +2 -0
- package/content/resources/customization/custom-fields.mdx +5 -1
- package/content/resources/customization/extending-panels.mdx +170 -113
- package/content/resources/tutorials/add-a-widget.mdx +111 -0
- package/content/resources/tutorials/custom-panel-page.mdx +2 -2
- package/content/resources/tutorials/customize-navigation.mdx +111 -0
- package/content/resources/tutorials/extend-forms-and-tables.mdx +189 -0
- package/content/resources/tutorials/extend-onboarding.mdx +254 -0
- package/content/resources/tutorials/import-export-products.mdx +3 -3
- package/llms.txt +5 -3
- package/package.json +1 -1
- package/content/resources/tutorials/recompose-a-page.mdx +0 -129
- package/content/resources/tutorials/replace-panel-components.mdx +0 -116
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Re-compose a built-in page"
|
|
3
|
-
description: "Override a built-in panel page by dropping a route file at the same path and re-composing its compound component slots."
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
Every page in the admin and vendor panels is exported as a **compound component** — a root plus named slots like `Header`, `HeaderActions`, and `DataTable`. That means you never fork a page to change one part of it: you drop a `page.tsx` at the same route path, render the original page, and swap only the slot you care about. Everything you don't touch keeps its default behavior — data fetching, filters, pagination, i18n, all of it.
|
|
7
|
-
|
|
8
|
-
<Info>
|
|
9
|
-
**This is not Medusa's widget system.** Medusa's admin lets you inject widgets into predefined zones around a page. Mercur takes a different approach: pages are React compound components you re-compose directly. There are no injection zones and no `defineWidgetConfig` — you get the actual page component and decide what renders inside it. See [Extending Panels](/rc/resources/customization/extending-panels) for the full comparison.
|
|
10
|
-
</Info>
|
|
11
|
-
|
|
12
|
-
## What you'll build
|
|
13
|
-
|
|
14
|
-
A vendor portal `/products` page with **Import** and **Export** buttons added next to the built-in Create button — while the table, search, filters, and everything else stay exactly as shipped. This is the same technique the official `product-import-export` block uses.
|
|
15
|
-
|
|
16
|
-
## Slot anatomy
|
|
17
|
-
|
|
18
|
-
Built-in pages are exported from the `/pages` subpath of each panel package:
|
|
19
|
-
|
|
20
|
-
```typescript
|
|
21
|
-
import { ProductListPage } from "@mercurjs/vendor/pages" // vendor portal
|
|
22
|
-
import { CustomerListPage } from "@mercurjs/admin/pages" // admin panel
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
Each list page exposes the same family of slots:
|
|
26
|
-
|
|
27
|
-
| Slot | Renders |
|
|
28
|
-
|------|---------|
|
|
29
|
-
| `Table` | The `Container` shell holding header + table |
|
|
30
|
-
| `Header` | The title/actions row |
|
|
31
|
-
| `HeaderTitle` | Heading and subtitle |
|
|
32
|
-
| `HeaderActions` | The action button cluster |
|
|
33
|
-
| `HeaderCreateButton` | The built-in Create button |
|
|
34
|
-
| `DataTable` | The wired data table — fetching, columns, filters, pagination |
|
|
35
|
-
|
|
36
|
-
Detail pages expose section slots instead (e.g. `CustomerDetailPage.Main`, `CustomerDetailPage.Sidebar`, `CustomerDetailPage.MainGeneralSection`).
|
|
37
|
-
|
|
38
|
-
## Override the page
|
|
39
|
-
|
|
40
|
-
<Steps>
|
|
41
|
-
<Step title="Drop a route file at the same path">
|
|
42
|
-
Create the file in your vendor app at the path that matches the built-in route. `/products` maps to `src/routes/products/page.tsx`:
|
|
43
|
-
|
|
44
|
-
```tsx apps/vendor/src/routes/products/page.tsx
|
|
45
|
-
import { Link } from "react-router-dom"
|
|
46
|
-
import { Button } from "@medusajs/ui"
|
|
47
|
-
import { ArrowDownTray, ArrowUpTray } from "@medusajs/icons"
|
|
48
|
-
import { ProductListPage } from "@mercurjs/vendor/pages"
|
|
49
|
-
|
|
50
|
-
export default function ProductsWithImportExport() {
|
|
51
|
-
return (
|
|
52
|
-
<ProductListPage>
|
|
53
|
-
<ProductListPage.Table>
|
|
54
|
-
<ProductListPage.Header>
|
|
55
|
-
<ProductListPage.HeaderTitle />
|
|
56
|
-
<ProductListPage.HeaderActions>
|
|
57
|
-
<Button size="small" variant="secondary" asChild>
|
|
58
|
-
<Link to="import">
|
|
59
|
-
<ArrowUpTray />
|
|
60
|
-
Import
|
|
61
|
-
</Link>
|
|
62
|
-
</Button>
|
|
63
|
-
<Button size="small" variant="secondary" asChild>
|
|
64
|
-
<Link to="export">
|
|
65
|
-
<ArrowDownTray />
|
|
66
|
-
Export
|
|
67
|
-
</Link>
|
|
68
|
-
</Button>
|
|
69
|
-
<ProductListPage.HeaderCreateButton />
|
|
70
|
-
</ProductListPage.HeaderActions>
|
|
71
|
-
</ProductListPage.Header>
|
|
72
|
-
<ProductListPage.DataTable />
|
|
73
|
-
</ProductListPage.Table>
|
|
74
|
-
</ProductListPage>
|
|
75
|
-
)
|
|
76
|
-
}
|
|
77
|
-
```
|
|
78
|
-
</Step>
|
|
79
|
-
<Step title="Reuse the slots you don't change">
|
|
80
|
-
Note what happened in that file: `HeaderTitle`, `HeaderCreateButton`, and `DataTable` are the originals, rendered untouched. Only `HeaderActions` gained two buttons. You re-compose top-down — render the page, re-declare only the branch you're changing, and keep original slots for everything inside it.
|
|
81
|
-
</Step>
|
|
82
|
-
<Step title="Reload the panel">
|
|
83
|
-
The dashboard SDK picks the file up automatically (adding or removing a route file triggers a full reload in dev). Because the path matches a built-in route, **your page replaces the built-in one** — no configuration, no registration.
|
|
84
|
-
</Step>
|
|
85
|
-
</Steps>
|
|
86
|
-
|
|
87
|
-
<Note>
|
|
88
|
-
When a custom route's path matches a built-in route, your page replaces the built-in one. Routes at new paths are appended instead. That one rule is the entire override mechanism.
|
|
89
|
-
</Note>
|
|
90
|
-
|
|
91
|
-
## How defaults work
|
|
92
|
-
|
|
93
|
-
If you render a compound page with **no children**, it renders its full default composition — so `<ProductListPage />` alone is identical to the built-in page. Every page root follows the pattern:
|
|
94
|
-
|
|
95
|
-
```tsx
|
|
96
|
-
Children.count(children) > 0 ? children : <DefaultComposition />
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
## Verify
|
|
100
|
-
|
|
101
|
-
1. Run your project (`bun run dev`) and open the vendor portal.
|
|
102
|
-
2. Navigate to **Products** — the list should look identical to before, plus Import and Export buttons in the header.
|
|
103
|
-
3. Search, filter, and paginate the table — all built-in behavior must still work, since `DataTable` is untouched.
|
|
104
|
-
4. Delete your `src/routes/products/page.tsx` and reload — the built-in page comes back. Nothing was forked.
|
|
105
|
-
|
|
106
|
-
## FAQ
|
|
107
|
-
|
|
108
|
-
<AccordionGroup>
|
|
109
|
-
<Accordion title="Where do I find which slots a page exposes?">
|
|
110
|
-
Import the page from `@mercurjs/vendor/pages` or `@mercurjs/admin/pages` and let your editor's autocomplete list the attached members — every slot is a static property on the page component. The naming is consistent across pages: list pages expose `Table`/`Header`/`HeaderTitle`/`HeaderActions`/`HeaderCreateButton`/`DataTable`; detail pages expose `Main`/`Sidebar` plus one property per section.
|
|
111
|
-
</Accordion>
|
|
112
|
-
<Accordion title="Can I remove a built-in element, like the Create button?">
|
|
113
|
-
Yes — re-composition is declarative. Anything you don't render doesn't appear: re-declare `HeaderActions` with only your own buttons and omit `HeaderCreateButton`.
|
|
114
|
-
</Accordion>
|
|
115
|
-
<Accordion title="What about changing the table columns?">
|
|
116
|
-
`DataTable` is a single slot — you either keep it wholesale or replace it with your own table. For a different column set, replace the slot with your own component built on the shared `DataTable`/`useDataTable` primitives from the panel package.
|
|
117
|
-
</Accordion>
|
|
118
|
-
</AccordionGroup>
|
|
119
|
-
|
|
120
|
-
## Next steps
|
|
121
|
-
|
|
122
|
-
<CardGroup cols={2}>
|
|
123
|
-
<Card title="Replace panel components" href="/rc/resources/tutorials/replace-panel-components">
|
|
124
|
-
Swap global chrome like the sidebar or topbar instead of a single page.
|
|
125
|
-
</Card>
|
|
126
|
-
<Card title="Add a custom API route" href="/rc/resources/tutorials/custom-api-route">
|
|
127
|
-
Back your custom page with a typed endpoint of your own.
|
|
128
|
-
</Card>
|
|
129
|
-
</CardGroup>
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Replace panel components"
|
|
3
|
-
description: "Swap the sidebar, topbar actions, or store setup screen for your own components through dashboard SDK configuration."
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
Some customizations aren't about one page — they change the panel's global chrome. For those, the dashboard SDK exposes a small set of **named component overrides**: you point the plugin config at your own file, and the panel renders your component in place of the built-in one everywhere it appears.
|
|
7
|
-
|
|
8
|
-
<Info>
|
|
9
|
-
**Choose the right tool.** A component override replaces one of four global layout slots across the whole panel. If you want to change a single page, [re-compose it](/rc/resources/tutorials/recompose-a-page) instead — and if you want to add a new screen, just [drop in a route](/rc/resources/tutorials/custom-panel-page). The decision guide in [Extending Panels](/rc/resources/customization/extending-panels#choosing-your-extension-mechanism) compares all three.
|
|
10
|
-
</Info>
|
|
11
|
-
|
|
12
|
-
## What you'll build
|
|
13
|
-
|
|
14
|
-
A vendor portal with custom topbar actions (a help link and a status badge) and a custom main sidebar, configured entirely from `vite.config.ts`.
|
|
15
|
-
|
|
16
|
-
## The available slots
|
|
17
|
-
|
|
18
|
-
Exactly four layout components can be replaced:
|
|
19
|
-
|
|
20
|
-
| Component | Where it renders |
|
|
21
|
-
|-----------|------------------|
|
|
22
|
-
| `MainSidebar` | Primary navigation sidebar on every main page |
|
|
23
|
-
| `SettingsSidebar` | Sidebar of the `/settings` section |
|
|
24
|
-
| `TopbarActions` | Action cluster on the right side of the top bar |
|
|
25
|
-
| `StoreSetup` | The store setup screen shown to new sellers (vendor portal) |
|
|
26
|
-
|
|
27
|
-
Anything else — a page, a section, a table — is customized through routes and compound components, not through overrides.
|
|
28
|
-
|
|
29
|
-
## Set up the override
|
|
30
|
-
|
|
31
|
-
<Steps>
|
|
32
|
-
<Step title="Write the replacement component">
|
|
33
|
-
Create the component anywhere under `src/`. It must have a **default export**:
|
|
34
|
-
|
|
35
|
-
```tsx apps/vendor/src/components/topbar-actions.tsx
|
|
36
|
-
import { Badge, Button } from "@medusajs/ui"
|
|
37
|
-
|
|
38
|
-
export default function TopbarActions() {
|
|
39
|
-
return (
|
|
40
|
-
<div className="flex items-center gap-x-2">
|
|
41
|
-
<Badge size="2xsmall" color="green">
|
|
42
|
-
All systems operational
|
|
43
|
-
</Badge>
|
|
44
|
-
<Button size="small" variant="transparent" asChild>
|
|
45
|
-
<a href="https://help.example.com" target="_blank" rel="noreferrer">
|
|
46
|
-
Help
|
|
47
|
-
</a>
|
|
48
|
-
</Button>
|
|
49
|
-
</div>
|
|
50
|
-
)
|
|
51
|
-
}
|
|
52
|
-
```
|
|
53
|
-
</Step>
|
|
54
|
-
<Step title="Register it in the Vite config">
|
|
55
|
-
Component overrides live in the `components` option of `mercurDashboardPlugin`, in your panel app's `vite.config.ts`. Paths are **relative to `src/`**:
|
|
56
|
-
|
|
57
|
-
```typescript apps/vendor/vite.config.ts
|
|
58
|
-
import { defineConfig } from 'vite'
|
|
59
|
-
import react from '@vitejs/plugin-react'
|
|
60
|
-
import { mercurDashboardPlugin } from '@mercurjs/dashboard-sdk'
|
|
61
|
-
|
|
62
|
-
export default defineConfig({
|
|
63
|
-
plugins: [
|
|
64
|
-
react(),
|
|
65
|
-
mercurDashboardPlugin({
|
|
66
|
-
medusaConfigPath: '../../packages/api/medusa-config.ts',
|
|
67
|
-
components: {
|
|
68
|
-
TopbarActions: 'components/topbar-actions',
|
|
69
|
-
MainSidebar: 'components/main-sidebar',
|
|
70
|
-
},
|
|
71
|
-
}),
|
|
72
|
-
],
|
|
73
|
-
})
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
The plugin resolves each path at build time and swaps your component in through the `virtual:mercur/components` module — no runtime registration, no context providers to wire.
|
|
77
|
-
</Step>
|
|
78
|
-
<Step title="Restart the dev server">
|
|
79
|
-
Vite config changes require a restart. After it, your components render everywhere their slots appear.
|
|
80
|
-
</Step>
|
|
81
|
-
</Steps>
|
|
82
|
-
|
|
83
|
-
<Tip>
|
|
84
|
-
Build overrides with `@medusajs/ui` components and Medusa UI color tokens so they match the rest of the panel. The panels ship no other UI library.
|
|
85
|
-
</Tip>
|
|
86
|
-
|
|
87
|
-
## Verify
|
|
88
|
-
|
|
89
|
-
1. Open the vendor portal — the top bar shows your badge and Help link on every page.
|
|
90
|
-
2. Navigate between main pages and `/settings` — the override applies everywhere its slot renders.
|
|
91
|
-
3. Remove the `components` entry and restart — the built-in components return. The originals were never modified.
|
|
92
|
-
|
|
93
|
-
## FAQ
|
|
94
|
-
|
|
95
|
-
<AccordionGroup>
|
|
96
|
-
<Accordion title="If I replace MainSidebar, do my custom routes still show up in the menu?">
|
|
97
|
-
Only if your sidebar renders them. A `MainSidebar` override replaces the **entire** navigation sidebar, including the auto-generated menu items from route `config` exports — read them from `virtual:mercur/menu-items` if you want to keep automatic navigation. If you only want to add or reorder items, you don't need an override at all: the `config` export on route files (with `rank` and `nested`) covers that.
|
|
98
|
-
</Accordion>
|
|
99
|
-
<Accordion title="Can I override other components, like the login page or a form?">
|
|
100
|
-
No — these four slots are the complete list. The login flow, forms, and everything page-level are customized through drop-in routes and [compound re-composition](/rc/resources/tutorials/recompose-a-page).
|
|
101
|
-
</Accordion>
|
|
102
|
-
<Accordion title="Do overrides apply to both panels?">
|
|
103
|
-
Each panel app has its own `vite.config.ts`, so overrides are configured per panel. `StoreSetup` only exists in the vendor portal; the other three slots exist in both.
|
|
104
|
-
</Accordion>
|
|
105
|
-
</AccordionGroup>
|
|
106
|
-
|
|
107
|
-
## Next steps
|
|
108
|
-
|
|
109
|
-
<CardGroup cols={2}>
|
|
110
|
-
<Card title="Re-compose a built-in page" href="/rc/resources/tutorials/recompose-a-page">
|
|
111
|
-
Change one page's composition instead of global chrome.
|
|
112
|
-
</Card>
|
|
113
|
-
<Card title="Extending Panels" href="/rc/resources/customization/extending-panels">
|
|
114
|
-
The full reference for routes, navigation, branding, and overrides.
|
|
115
|
-
</Card>
|
|
116
|
-
</CardGroup>
|