Correct the navigation naming

This commit is contained in:
ivarsbariss
2026-03-05 10:29:01 +01:00
parent 7a03b74453
commit 534216bb54
9 changed files with 223 additions and 8 deletions

View File

@@ -0,0 +1,215 @@
---
name: add-tabs-to-page
description: Adds a TABS_WIDGET to a page so multiple data views live under one page instead of separate pages. Use when the user asks to add tabs, consolidate pages into tabs, create tabbed views, or replace a single table with a tabbed layout.
---
# Add Tabs to a Page
Replaces a page's standalone content (e.g. a single `TABLE_WIDGET_V2`) with a `TABS_WIDGET` containing multiple tabs, each with its own widgets and query binding.
## Prerequisites
- **Tab definitions**: User must provide the tab labels and the query each tab should display.
- **Page prefix**: Each page uses a short widget-ID prefix (e.g. `pa1`, `cp1`). Reuse the existing prefix from the page's widgets.
- Follow the **add-query-to-table** skill for creating any new queries needed by the tabs.
## File Layout
The Tabs widget and all widgets **inside** tabs live under a `Tabs1/` directory:
```
pages/<PageName>/widgets/Tabs1/
├── Tabs1.json # The TABS_WIDGET itself
├── <Table1>.json # Table inside tab 1
├── <Table2>.json # Table inside tab 2
├── <DatePicker>.json # Optional: date pickers inside a tab
└── ...
```
If the page previously had a standalone `Table1.json` at `widgets/Table1.json`, **delete it** after creating the tabbed replacement.
## Instructions
### 1. Design the tab structure
Decide on tab count, labels, and content. Example:
| Tab ID | Label | Canvas widgetId | Content |
|--------|-------|-----------------|---------|
| tab1 | All | `{prefix}cnvsall` | TableAll bound to `query_all` |
| tab2 | SLx | `{prefix}cnvsslx` | TableSLx bound to `query_slx` |
### 2. Create `Tabs1.json`
The TABS_WIDGET has three critical sections:
**A) `tabsObj`** — declares each tab with id, label, index, and canvas widgetId:
```json
"tabsObj": {
"tab1": {
"id": "tab1",
"index": 0,
"isVisible": true,
"label": "All",
"positioning": "vertical",
"widgetId": "<canvas-widgetId-for-tab1>"
},
"tab2": { ... }
}
```
**B) `children`** — array of `CANVAS_WIDGET` entries, one per tab. Each canvas must reference:
- `"parentId"`: the Tabs widget's `widgetId`
- `"tabId"`: matching key from `tabsObj` (e.g. `"tab1"`)
- `"tabName"`: the display label
- `"widgetId"`: unique canvas ID (referenced in `tabsObj` and by child widgets)
**C) Top-level Tabs properties:
```json
{
"type": "TABS_WIDGET",
"version": 3,
"isCanvas": true,
"shouldShowTabs": true,
"defaultTab": "<label of default tab>",
"parentId": "0",
"leftColumn": 9,
"rightColumn": 64,
"topRow": 5,
"bottomRow": 67,
"dynamicHeight": "AUTO_HEIGHT",
"dynamicBindingPathList": [
{"key": "accentColor"},
{"key": "boxShadow"}
],
"accentColor": "{{appsmith.theme.colors.primaryColor}}",
"boxShadow": "{{appsmith.theme.boxShadow.appBoxShadow}}",
"backgroundColor": "#FFFFFF",
"borderColor": "#E0DEDE",
"borderRadius": "0.375rem",
"borderWidth": 1
}
```
### 3. Create widgets inside each tab
Each widget inside a tab sets `"parentId"` to that tab's **canvas widgetId** (not the Tabs widgetId). Widgets start at `topRow: 0` within each canvas.
**Table-only tabs** (no date pickers):
```json
{
"type": "TABLE_WIDGET_V2",
"parentId": "<canvas-widgetId>",
"topRow": 0,
"bottomRow": 58,
"leftColumn": 0,
"rightColumn": 62,
"tableData": "{{<query_name>.data}}",
...
}
```
**Tabs with date pickers** (see Sales - Units Shipped for reference):
| Widget | topRow | bottomRow | leftColumn | rightColumn |
|--------|--------|-----------|------------|-------------|
| DateFrom | 0 | 7 | 0 | 5 |
| DateTo | 0 | 7 | 5 | 10 |
| Table | 7 | 58 | 0 | 62 |
Date pickers use `"type": "DATE_PICKER_WIDGET2"`, `"dateFormat": "YYYY-MM-DD HH:mm"`, and `"parentId"` set to the tab's canvas widgetId.
### 4. Create queries for each tab
Follow the **add-query-to-table** skill. Each query's `metadata.json` must have:
- `"pageId"`: the page name (e.g. `"Pending POs - All"`)
- `"gitSyncId"`: use the same 24-char hex prefix as the page, with a unique UUID suffix
- `"runBehaviour": "AUTOMATIC"`
### 5. Delete the old standalone widget
If the page had a `widgets/Table1.json` (or similar) that the Tabs widget replaces, delete it.
### 6. Verify
- Each canvas `widgetId` in `children` matches the corresponding `widgetId` in `tabsObj`.
- Each widget inside a tab has `parentId` set to its tab's canvas `widgetId`.
- `defaultTab` matches one of the tab labels (not the tab ID).
- All queries reference the correct `pageId`.
- Run `git status` / `git diff` to confirm only intended changes.
## Canvas Widget Template
Each canvas child in the `children` array follows this template:
```json
{
"borderRadius": "{{appsmith.theme.borderRadius.appBorderRadius}}",
"bottomRow": 620,
"boxShadow": "{{appsmith.theme.boxShadow.appBoxShadow}}",
"canExtend": true,
"detachFromLayout": true,
"dynamicBindingPathList": [
{"key": "borderRadius"},
{"key": "boxShadow"}
],
"dynamicHeight": "AUTO_HEIGHT",
"dynamicTriggerPathList": [],
"flexLayers": [],
"isDisabled": false,
"isLoading": false,
"isVisible": true,
"key": "<unique-key>",
"leftColumn": 0,
"maxDynamicHeight": 9000,
"minDynamicHeight": 4,
"minHeight": 150,
"minWidth": 450,
"mobileBottomRow": 150,
"mobileLeftColumn": 0,
"mobileRightColumn": 602.625,
"mobileTopRow": 0,
"needsErrorInfo": false,
"parentColumnSpace": 1,
"parentId": "<tabs-widgetId>",
"parentRowSpace": 1,
"renderMode": "CANVAS",
"responsiveBehavior": "fill",
"rightColumn": 602.625,
"shouldScrollContents": false,
"tabId": "<tab-id>",
"tabName": "<tab-label>",
"topRow": 0,
"type": "CANVAS_WIDGET",
"version": 1,
"widgetId": "<unique-canvas-widgetId>",
"widgetName": "Canvas<N>"
}
```
## Consolidating Multiple Pages into Tabs
When merging separate pages into one tabbed page:
1. **Choose the surviving page** (or create a new one via **create-new-page** skill).
2. **Move each page's query** into the surviving page's `queries/` directory. Update `pageId` and generate new `gitSyncId` values (same 24-char prefix as the surviving page).
3. **Create the Tabs widget** with one tab per former page, plus any additional tabs (e.g. "All").
4. **Delete the old page directories** entirely.
5. **Remove old navigation buttons** from all remaining pages (delete the button JSON files).
6. **Update `application.json`** to remove entries for deleted pages.
7. **Keep one nav button** pointing to the surviving page.
## Reference
| Item | Value |
|------|-------|
| Widget type | `TABS_WIDGET` version `3` |
| Widget directory | `widgets/Tabs1/` |
| Canvas parent | Tabs `widgetId` |
| Widget-in-tab parent | Canvas `widgetId` for that tab |
| `defaultTab` | Tab **label** (not tab ID) |
| `tabsObj` keys | `tab1`, `tab2`, `tab3`, ... |
| Existing examples | `Sales - Units Shipped`, `Pending POs - All` |

View File

@@ -40,7 +40,7 @@
"resetFormOnClick": false,
"responsiveBehavior": "hug",
"rightColumn": 64,
"text": "All",
"text": "Pending POs",
"topRow": 22,
"type": "BUTTON_WIDGET",
"version": 1,

View File

@@ -40,7 +40,7 @@
"responsiveBehavior": "fill",
"rightColumn": 64,
"shouldTruncate": false,
"text": "Pending POs",
"text": "Engineering",
"textAlign": "LEFT",
"textColor": "#231F20",
"topRow": 18,

View File

@@ -36,7 +36,7 @@
"resetFormOnClick": false,
"responsiveBehavior": "hug",
"rightColumn": 64,
"text": "All",
"text": "Pending POs",
"topRow": 22,
"type": "BUTTON_WIDGET",
"version": 1,

View File

@@ -40,7 +40,7 @@
"responsiveBehavior": "fill",
"rightColumn": 64,
"shouldTruncate": false,
"text": "Pending POs",
"text": "Engineering",
"textAlign": "LEFT",
"textColor": "#231F20",
"topRow": 18,

View File

@@ -36,7 +36,7 @@
"resetFormOnClick": false,
"responsiveBehavior": "hug",
"rightColumn": 64,
"text": "All",
"text": "Pending POs",
"topRow": 22,
"type": "BUTTON_WIDGET",
"version": 1,

View File

@@ -40,7 +40,7 @@
"responsiveBehavior": "fill",
"rightColumn": 64,
"shouldTruncate": false,
"text": "Pending POs",
"text": "Engineering",
"textAlign": "LEFT",
"textColor": "#231F20",
"topRow": 18,

View File

@@ -36,7 +36,7 @@
"resetFormOnClick": false,
"responsiveBehavior": "hug",
"rightColumn": 64,
"text": "All",
"text": "Pending POs",
"topRow": 22,
"type": "BUTTON_WIDGET",
"version": 1,

View File

@@ -40,7 +40,7 @@
"responsiveBehavior": "fill",
"rightColumn": 64,
"shouldTruncate": false,
"text": "Pending POs",
"text": "Engineering",
"textAlign": "LEFT",
"textColor": "#231F20",
"topRow": 18,