@maltjoy/mcp-server 0.4.0 → 0.6.0-beta.0
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/LICENSE +21 -0
- package/README.md +30 -3
- package/dist/doc/VJoyAdminBanner/guideline.md +284 -0
- package/dist/doc/VJoyAvailability/guideline.md +352 -0
- package/dist/doc/VJoyAvatar/guideline.md +192 -0
- package/dist/doc/VJoyAvatarsList/guideline.md +328 -0
- package/dist/doc/VJoyBadge/guideline.md +169 -0
- package/dist/doc/VJoyBadgeLevel/guideline.md +166 -0
- package/dist/doc/VJoyBlockSkeleton/guideline.md +150 -0
- package/dist/doc/VJoyBottomSheet/guideline.md +345 -0
- package/dist/doc/VJoyBottomSheetTrigger/guideline.md +156 -0
- package/dist/doc/VJoyButton/guideline.md +371 -0
- package/dist/doc/VJoyButton/metadata.json +0 -16
- package/dist/doc/VJoyButtonCard/guideline.md +384 -0
- package/dist/doc/VJoyCheckbox/guideline.md +317 -0
- package/dist/doc/VJoyCheckboxCard/guideline.md +381 -0
- package/dist/doc/VJoyCheckboxGroup/guideline.md +363 -0
- package/dist/doc/VJoyCheckboxGroup/metadata.json +7 -7
- package/dist/doc/VJoyCollapse/guideline.md +362 -0
- package/dist/doc/VJoyCollapseItem/guideline.md +394 -0
- package/dist/doc/VJoyCompanyAvatar/guideline.md +162 -0
- package/dist/doc/VJoyDialog/guideline.md +425 -0
- package/dist/doc/VJoyDialogTrigger/guideline.md +186 -0
- package/dist/doc/VJoyDot/guideline.md +177 -0
- package/dist/doc/VJoyDrawer/guideline.md +392 -0
- package/dist/doc/VJoyDrawerTrigger/guideline.md +145 -0
- package/dist/doc/VJoyDropdown/guideline.md +393 -0
- package/dist/doc/VJoyDropdown/metadata.json +6 -6
- package/dist/doc/VJoyDropdownList/guideline.md +396 -0
- package/dist/doc/VJoyDropdownList/metadata.json +7 -7
- package/dist/doc/VJoyDropzone/guideline.md +390 -0
- package/dist/doc/VJoyDropzone/metadata.json +36 -1
- package/dist/doc/VJoyFilterBar/guideline.md +419 -0
- package/dist/doc/VJoyFilterBarButton/guideline.md +359 -0
- package/dist/doc/VJoyFloatingActionsBar/guideline.md +372 -0
- package/dist/doc/VJoyFormError/guideline.md +325 -0
- package/dist/doc/VJoyFormError/metadata.json +0 -14
- package/dist/doc/VJoyFormFieldSkeleton/guideline.md +159 -0
- package/dist/doc/VJoyFormGroup/guideline.md +285 -0
- package/dist/doc/VJoyFunnel/guideline.md +349 -0
- package/dist/doc/VJoyFunnelFooter/guideline.md +178 -0
- package/dist/doc/VJoyFunnelHeader/guideline.md +204 -0
- package/dist/doc/VJoyHighlight/guideline.md +169 -0
- package/dist/doc/VJoyIcon/JoyIcon.types.ts +1 -1
- package/dist/doc/VJoyIcon/guideline.md +168 -0
- package/dist/doc/VJoyIcon/metadata.json +0 -1
- package/dist/doc/VJoyIconButton/guideline.md +169 -0
- package/dist/doc/VJoyIconButton/metadata.json +1 -1
- package/dist/doc/VJoyIndicator/guideline.md +168 -0
- package/dist/doc/VJoyIndicators/guideline.md +183 -0
- package/dist/doc/VJoyInput/JoyInput.types.ts +1 -6
- package/dist/doc/VJoyInput/guideline.md +401 -0
- package/dist/doc/VJoyInput/metadata.json +5 -14
- package/dist/doc/VJoyInputDigit/guideline.md +381 -0
- package/dist/doc/VJoyInputNumber/guideline.md +414 -0
- package/dist/doc/VJoyInputNumber/metadata.json +22 -17
- package/dist/doc/VJoyInputPassword/guideline.md +379 -0
- package/dist/doc/VJoyInputPassword/metadata.json +0 -14
- package/dist/doc/VJoyLabel/guideline.md +200 -0
- package/dist/doc/VJoyLink/guideline.md +360 -0
- package/dist/doc/VJoyListItem/guideline.md +335 -0
- package/dist/doc/VJoyMenu/guideline.md +304 -0
- package/dist/doc/VJoyMenu/metadata.json +21 -21
- package/dist/doc/VJoyMenuItem/guideline.md +352 -0
- package/dist/doc/VJoyPagination/guideline.md +355 -0
- package/dist/doc/VJoyPanel/guideline.md +238 -0
- package/dist/doc/VJoyPanelSection/guideline.md +160 -0
- package/dist/doc/VJoyPasswordRequirement/guideline.md +336 -0
- package/dist/doc/VJoyPasswordRequirement/metadata.json +1 -1
- package/dist/doc/VJoyProductTour/JoyProductTour.types.ts +0 -1
- package/dist/doc/VJoyProductTour/guideline.md +455 -0
- package/dist/doc/VJoyProductTour/metadata.json +1 -1
- package/dist/doc/VJoyProductTourTrigger/guideline.md +167 -0
- package/dist/doc/VJoyProgressBar/guideline.md +348 -0
- package/dist/doc/VJoyRadio/guideline.md +346 -0
- package/dist/doc/VJoyRadioGroup/guideline.md +331 -0
- package/dist/doc/VJoyRatingStars/guideline.md +306 -0
- package/dist/doc/VJoyScreenLoader/guideline.md +172 -0
- package/dist/doc/VJoySelect/guideline.md +396 -0
- package/dist/doc/VJoySelectableItem/guideline.md +351 -0
- package/dist/doc/VJoySelectableItemGroup/guideline.md +370 -0
- package/dist/doc/VJoySeparator/guideline.md +161 -0
- package/dist/doc/VJoySnackbar/guideline.md +402 -0
- package/dist/doc/VJoySpinner/guideline.md +168 -0
- package/dist/doc/VJoyStep/guideline.md +182 -0
- package/dist/doc/VJoyStepper/guideline.md +390 -0
- package/dist/doc/VJoyTab/guideline.md +298 -0
- package/dist/doc/VJoyTabs/guideline.md +353 -0
- package/dist/doc/VJoyTag/guideline.md +226 -0
- package/dist/doc/VJoyTagsInput/guideline.md +387 -0
- package/dist/doc/VJoyTagsList/guideline.md +311 -0
- package/dist/doc/VJoyTagsList/metadata.json +27 -27
- package/dist/doc/VJoyTemplate/guideline.md +366 -0
- package/dist/doc/VJoyText/guideline.md +175 -0
- package/dist/doc/VJoyText/metadata.json +1 -1
- package/dist/doc/VJoyTextarea/guideline.md +378 -0
- package/dist/doc/VJoyTitleBrand/guideline.md +155 -0
- package/dist/doc/VJoyToggle/guideline.md +327 -0
- package/dist/doc/VJoyTooltip/guideline.md +322 -0
- package/dist/doc/VJoyUserCard/guideline.md +268 -0
- package/dist/doc/VJoyUserCard/metadata.json +3 -17
- package/dist/doc/VJoyWalkthrough/guideline.md +351 -0
- package/dist/doc/VJoyWalkthroughTrigger/guideline.md +171 -0
- package/dist/doc/VJoyWrapper/guideline.md +173 -0
- package/dist/doc/css-classes.json +1 -15
- package/dist/doc/design-tokens.json +1 -0
- package/dist/doc/index.json +20 -30
- package/dist/index.js +22 -2
- package/dist/index.js.map +1 -1
- package/dist/tools/get-component-guideline.d.ts +30 -0
- package/dist/tools/get-component-guideline.d.ts.map +1 -0
- package/dist/tools/get-component-guideline.js +51 -0
- package/dist/tools/get-component-guideline.js.map +1 -0
- package/dist/tools/get-documentation-page.d.ts +22 -0
- package/dist/tools/get-documentation-page.d.ts.map +1 -0
- package/dist/tools/get-documentation-page.js +21 -0
- package/dist/tools/get-documentation-page.js.map +1 -0
- package/dist/tools/list-documentation-pages.d.ts +22 -0
- package/dist/tools/list-documentation-pages.d.ts.map +1 -0
- package/dist/tools/list-documentation-pages.js +17 -0
- package/dist/tools/list-documentation-pages.js.map +1 -0
- package/dist/tools/search-documentation.d.ts +41 -0
- package/dist/tools/search-documentation.d.ts.map +1 -0
- package/dist/tools/search-documentation.js +25 -0
- package/dist/tools/search-documentation.js.map +1 -0
- package/dist/zeroheight-parser.d.ts +27 -0
- package/dist/zeroheight-parser.d.ts.map +1 -0
- package/dist/zeroheight-parser.js +77 -0
- package/dist/zeroheight-parser.js.map +1 -0
- package/package.json +10 -10
- package/dist/doc/VJoyMultiCheckbox/metadata.json +0 -332
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: VJoyTemplate
|
|
3
|
+
status: draft
|
|
4
|
+
language: en
|
|
5
|
+
dsds: JoyTemplate.dsds.json
|
|
6
|
+
dsdsVersion: "0.15.2"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Template
|
|
10
|
+
|
|
11
|
+
Use **`VJoyTemplate`** when you need a consistent **page-level layout** — header (title, subtitle, actions, optional back control), a main content column, and an optional sidebar.
|
|
12
|
+
|
|
13
|
+
It handles responsive stacking, optional full-width mode, a loading overlay via `VJoyScreenLoader`, and decorative background shapes. Compose page sections inside the slots with `VJoyPanel`, forms with `VJoyWrapper`, and navigation menus in the sidebar when needed.
|
|
14
|
+
|
|
15
|
+
| | |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| **Code** | `VJoyTemplate` from `@maltjoy/core-vue` |
|
|
18
|
+
| **Design** | [Figma — Joy Core Design System](https://www.figma.com/design/jfndp2QBJGS9yeuWbeGuvD/) |
|
|
19
|
+
| **Storybook** | [VJoyTemplate docs](https://doc.malt.tech/joy-storybook/?path=/docs/components-layout-vjoytemplate--docs) |
|
|
20
|
+
| **DSDS (machine)** | [`JoyTemplate.dsds.json`](./JoyTemplate.dsds.json) |
|
|
21
|
+
| **Live API** | `joy_get_component_info("VJoyTemplate")` |
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## When to use this component
|
|
26
|
+
|
|
27
|
+
Use the template when building a **new product screen** that needs a predictable page chrome: page title, optional subtitle, top-right actions, primary content, and sometimes a secondary column (filters, navigation, summary card).
|
|
28
|
+
|
|
29
|
+
It is the default wrapper for most in-app pages. Stack `VJoyPanel` components in `template-main` (and optionally `template-sidebar`) to create sections with consistent spacing.
|
|
30
|
+
|
|
31
|
+
### When not to use this component
|
|
32
|
+
|
|
33
|
+
| Need | Use instead |
|
|
34
|
+
| --- | --- |
|
|
35
|
+
| Multi-step guided flow / onboarding funnel | `VJoyFunnel` |
|
|
36
|
+
| Card or section inside an existing page (not the page shell) | `VJoyPanel` |
|
|
37
|
+
| Modal overlay interrupting the current task | `VJoyDialog` |
|
|
38
|
+
| Slide-in panel from the edge | `VJoyDrawer` |
|
|
39
|
+
| Flexbox utility layout inside a form or toolbar | `VJoyWrapper` |
|
|
40
|
+
| Custom page markup with ad-hoc layout CSS | Still use `VJoyTemplate` + Joy tokens — don’t reinvent page chrome |
|
|
41
|
+
|
|
42
|
+
> **Internal:** `VJoyTemplateShape` / `TemplateShape` is not public API. Use the `shapes` prop on `VJoyTemplate` — do not import the shape component directly.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## How it works
|
|
47
|
+
|
|
48
|
+
The root is a `<div class="joy-template">` (not `<main>`) so apps can own the document landmark and avoid duplicate `<main>` regions. Content is organized through **named slots**; the header row renders only when at least one header slot is provided.
|
|
49
|
+
|
|
50
|
+
### Anatomy
|
|
51
|
+
|
|
52
|
+
| Part | Required? | What it is |
|
|
53
|
+
| --- | --- | --- |
|
|
54
|
+
| Root container | Yes | `.joy-template` — padding, max width, optional `--full` / `--loading` modifiers |
|
|
55
|
+
| Decorative shapes | No | Fixed bottom-right shapes when `shapes` is true (primary palette; not customizable) |
|
|
56
|
+
| Header row | No* | `.joy-template__heading` — back, title block, actions (*shown when any header slot is used) |
|
|
57
|
+
| Back slot | No | `#template-back` — typically a `VJoyIconButton` left of the title |
|
|
58
|
+
| Title slot | Yes (product rule) | `#template-title` — page heading; ESLint requires an `h1`–`h6` (prefer `h1`) |
|
|
59
|
+
| Subtitle slot | No | `#template-subtitle` — supporting description below the title |
|
|
60
|
+
| Actions slot | No | `#template-actions` — top-right area, usually primary/secondary CTAs |
|
|
61
|
+
| Content row | No* | `.joy-template__content` — flex row for main + sidebar (*when those slots are used) |
|
|
62
|
+
| Main slot | No | `#template-main` — primary page body (panels, forms, lists) |
|
|
63
|
+
| Sidebar slot | No | `#template-sidebar` — secondary column (e.g. `VJoyMenu`, summary, filters) |
|
|
64
|
+
| Loading overlay | No | `VJoyScreenLoader` with blur on content when `loading` is true |
|
|
65
|
+
| Loader content slot | No | `#template-loader-content` — message beside the spinner |
|
|
66
|
+
|
|
67
|
+
### Default values
|
|
68
|
+
|
|
69
|
+
- `full` defaults to **`false`** (`true` → content wrapper spans 100% width)
|
|
70
|
+
- `sidebar` defaults to **`right`** (`left` reverses the flex order)
|
|
71
|
+
- `loading` defaults to **`false`**
|
|
72
|
+
- `loadingColor` defaults to **`light`** (`dark` for darker backgrounds)
|
|
73
|
+
- `shapes` defaults to **`false`**
|
|
74
|
+
|
|
75
|
+
Layout tokens (CSS custom properties on `.joy-template`):
|
|
76
|
+
|
|
77
|
+
- `--template-layout-width` — **`1024px`** (overridden to `100%` when `full` is true)
|
|
78
|
+
- `--template-sidebar-width` — **`320px`**
|
|
79
|
+
- `--template-inner-spacing` — **`var(--joy-core-spacing-8)`** (spacing-6 ≤ 991px, spacing-4 ≤ 760px)
|
|
80
|
+
|
|
81
|
+
Props and slots: use Joy MCP (`joy_get_component_info`, `joy_get_component_types`) or Storybook — this page focuses on **when** and **how**, not a full API dump.
|
|
82
|
+
|
|
83
|
+
### Responsive behavior
|
|
84
|
+
|
|
85
|
+
- **≤ 1024px:** main and sidebar stack vertically (sidebar below main by default; order follows `sidebar` prop).
|
|
86
|
+
- **≤ 767px:** header actions wrap to a full-width row below the title block.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Layout options
|
|
91
|
+
|
|
92
|
+
`VJoyTemplate` has no color variant prop. Choose **layout behavior** by props and slots.
|
|
93
|
+
|
|
94
|
+
### Default (centered column)
|
|
95
|
+
|
|
96
|
+
Content wrapper is capped at `--template-layout-width` (1024px) and centered. Use for standard product pages.
|
|
97
|
+
|
|
98
|
+
### Full width (`full`)
|
|
99
|
+
|
|
100
|
+
Sets `--template-layout-width` to `100%`. Use when the page must use the full viewport width (dashboards, wide tables) while keeping inner padding from `--template-inner-spacing`.
|
|
101
|
+
|
|
102
|
+
Avoid `full` when a readable line length matters and the design expects the default 1024px column.
|
|
103
|
+
|
|
104
|
+
### Sidebar right (`sidebar="right"`)
|
|
105
|
+
|
|
106
|
+
Default. Main content on the left, sidebar on the right — typical for detail pages with a nav or summary column.
|
|
107
|
+
|
|
108
|
+
### Sidebar left (`sidebar="left"`)
|
|
109
|
+
|
|
110
|
+
Reverses the flex row. Use when design places the secondary column on the left (uncommon; confirm with layout specs).
|
|
111
|
+
|
|
112
|
+
### Decorative shapes (`shapes`)
|
|
113
|
+
|
|
114
|
+
Fixed primary-colored shapes in the bottom-right corner. Disabled by default; no palette or position customization.
|
|
115
|
+
|
|
116
|
+
Use only when design approves decorative branding on that screen. Avoid on dense or data-heavy pages where shapes compete with content.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## States
|
|
121
|
+
|
|
122
|
+
| State | What the user sees / can do |
|
|
123
|
+
| --- | --- |
|
|
124
|
+
| Default | Page content visible; header and columns per provided slots |
|
|
125
|
+
| Loading (`loading`) | `VJoyScreenLoader` overlay; main wrapper blurred; optional message in `#template-loader-content` |
|
|
126
|
+
| Loading color `light` / `dark` | Spinner/contrast tuned for light vs dark page backgrounds |
|
|
127
|
+
|
|
128
|
+
Prefer `loading` during initial page fetch or route transitions instead of empty shells with no feedback.
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Best practices
|
|
133
|
+
|
|
134
|
+
Rules use RFC 2119 strength (same idea as DSDS `guidelines.level`).
|
|
135
|
+
|
|
136
|
+
### Page structure
|
|
137
|
+
|
|
138
|
+
- **MUST** provide `#template-title` on every `VJoyTemplate` (enforced by ESLint `require-vjoytemplate-template-title`).
|
|
139
|
+
- **MUST** put an **`h1`–`h6` inside `#template-title`**, preferably **`h1`** (ESLint `require-vjoytemplate-template-title-heading`).
|
|
140
|
+
- **SHOULD** place `VJoyMenu` in `#template-sidebar` when used as page nav (ESLint `require-vjoymenu-template-sidebar`).
|
|
141
|
+
- **SHOULD** stack sections with `VJoyPanel` inside `#template-main` rather than ad-hoc margin on every block.
|
|
142
|
+
- **SHOULD** use `#template-back` with `VJoyIconButton` (e.g. `arrow-left`, `variant="ghost"`) for upward navigation.
|
|
143
|
+
- **SHOULD** reserve `#template-actions` for page-level CTAs (one principal action + companions).
|
|
144
|
+
|
|
145
|
+
### Implementation
|
|
146
|
+
|
|
147
|
+
- **MUST** use only documented props: `full`, `sidebar`, `loading`, `loadingColor`, `shapes`.
|
|
148
|
+
- **MUST** use Joy tokens and documented CSS variables — no custom page-shell chrome.
|
|
149
|
+
- **MUST NOT** import or render `VJoyTemplateShape` / `TemplateShape` directly — use `shapes`.
|
|
150
|
+
- **MUST NOT** override `--template-layout-width` unless unavoidable; design treats 1024px as a strict rule.
|
|
151
|
+
- **MAY** override `--template-sidebar-width` when the sidebar needs a different fixed width.
|
|
152
|
+
- **MUST NOT** wrap the template root in another `<main>` if the app already exposes a single page `<main>`.
|
|
153
|
+
|
|
154
|
+
### Interaction
|
|
155
|
+
|
|
156
|
+
- **MUST** set `loading` while async page data is not ready (with a short message in `#template-loader-content` when helpful).
|
|
157
|
+
- **SHOULD** keep sidebar content supplementary — primary tasks stay in `#template-main`.
|
|
158
|
+
|
|
159
|
+
### Do / don’t
|
|
160
|
+
|
|
161
|
+
| Do | Don’t |
|
|
162
|
+
| --- | --- |
|
|
163
|
+
| `#template-title` with `<h1>` | Plain `<div>` or missing title slot |
|
|
164
|
+
| `VJoyPanel` for sections | Random margin utilities on every block |
|
|
165
|
+
| `shapes` prop for decoration | Import internal shape component |
|
|
166
|
+
| `full` for intentional wide layouts | `full` on every page by default |
|
|
167
|
+
| `VJoyMenu` in `#template-sidebar` | `VJoyMenu` floating outside the template sidebar slot |
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Content
|
|
172
|
+
|
|
173
|
+
The template does not own copy — it structures where **page title**, **subtitle**, and **actions** appear. Follow product voice in those slots.
|
|
174
|
+
|
|
175
|
+
### Title (`#template-title`)
|
|
176
|
+
|
|
177
|
+
- **MUST** use a real heading element (`h1` preferred) — one primary page title per view.
|
|
178
|
+
- **SHOULD** match the browser tab / route purpose; keep it scannable (short noun phrase or task name).
|
|
179
|
+
- **MAY** use `VJoyTitleBrand` inside the slot for marketing-style highlighted titles (also valid in `VJoyDialog`).
|
|
180
|
+
|
|
181
|
+
### Subtitle (`#template-subtitle`)
|
|
182
|
+
|
|
183
|
+
- **SHOULD** clarify scope or context in one line — not duplicate the title.
|
|
184
|
+
- **SHOULD NOT** hold long paragraphs; move body copy to `#template-main`.
|
|
185
|
+
|
|
186
|
+
### Actions (`#template-actions`)
|
|
187
|
+
|
|
188
|
+
- **SHOULD** use `VJoyButton` with clear verb + noun labels (see Button guidelines).
|
|
189
|
+
- **SHOULD** limit to a small set of actions (typically one `main`/`primary` + secondary/ghost companions).
|
|
190
|
+
- **SHOULD NOT** crowd the header with many equal-weight CTAs.
|
|
191
|
+
|
|
192
|
+
### Loading message (`#template-loader-content`)
|
|
193
|
+
|
|
194
|
+
- **SHOULD** use short, present-tense text (`Loading projects…`) — not marketing copy.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Accessibility
|
|
199
|
+
|
|
200
|
+
Behaviors (what must happen), not slogans.
|
|
201
|
+
|
|
202
|
+
| Behavior | Expectation |
|
|
203
|
+
| --- | --- |
|
|
204
|
+
| Document landmark | Template root is a `<div>` — the **app** provides `<main>` (or equivalent) around or above this component; avoid nested `<main>` |
|
|
205
|
+
| Page title | `#template-title` contains a heading (`h1` preferred) so assistive tech can find the page name |
|
|
206
|
+
| Heading order | Don’t skip levels inside the page; template title is typically the page `h1` |
|
|
207
|
+
| Back control | `#template-back` should expose an accessible name (`label` on `VJoyIconButton`) |
|
|
208
|
+
| Loading | Overlay blocks interaction on blurred content; provide meaningful loader text when the wait is non-trivial |
|
|
209
|
+
| Shapes | Decorative only — no information conveyed by shapes alone |
|
|
210
|
+
|
|
211
|
+
Target: **WCAG 2.2 AA** where the product requires it.
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Examples
|
|
216
|
+
|
|
217
|
+
```vue
|
|
218
|
+
<script setup lang="ts">
|
|
219
|
+
import { ref } from 'vue'
|
|
220
|
+
import {
|
|
221
|
+
VJoyTemplate,
|
|
222
|
+
VJoyIconButton,
|
|
223
|
+
VJoyButton,
|
|
224
|
+
VJoyPanel,
|
|
225
|
+
} from '@maltjoy/core-vue'
|
|
226
|
+
|
|
227
|
+
const loading = ref(false)
|
|
228
|
+
</script>
|
|
229
|
+
|
|
230
|
+
<template>
|
|
231
|
+
<!-- Standard page with sidebar -->
|
|
232
|
+
<VJoyTemplate>
|
|
233
|
+
<template #template-title>
|
|
234
|
+
<h1>Project settings</h1>
|
|
235
|
+
</template>
|
|
236
|
+
<template #template-subtitle>
|
|
237
|
+
Manage visibility, team, and billing for this project.
|
|
238
|
+
</template>
|
|
239
|
+
<template #template-actions>
|
|
240
|
+
<VJoyButton variant="main" label="Save changes" />
|
|
241
|
+
</template>
|
|
242
|
+
<template #template-main>
|
|
243
|
+
<VJoyPanel title="General">…</VJoyPanel>
|
|
244
|
+
<VJoyPanel title="Team">…</VJoyPanel>
|
|
245
|
+
</template>
|
|
246
|
+
<template #template-sidebar>
|
|
247
|
+
<!-- e.g. VJoyMenu for section nav -->
|
|
248
|
+
…
|
|
249
|
+
</template>
|
|
250
|
+
</VJoyTemplate>
|
|
251
|
+
|
|
252
|
+
<!-- Back navigation + loading -->
|
|
253
|
+
<VJoyTemplate :loading="loading" loading-color="light">
|
|
254
|
+
<template #template-back>
|
|
255
|
+
<VJoyIconButton
|
|
256
|
+
icon="arrow-left"
|
|
257
|
+
variant="ghost"
|
|
258
|
+
label="Back to projects"
|
|
259
|
+
/>
|
|
260
|
+
</template>
|
|
261
|
+
<template #template-title>
|
|
262
|
+
<h1>Acme brief</h1>
|
|
263
|
+
</template>
|
|
264
|
+
<template #template-main>
|
|
265
|
+
…
|
|
266
|
+
</template>
|
|
267
|
+
<template #template-loader-content>
|
|
268
|
+
Loading project…
|
|
269
|
+
</template>
|
|
270
|
+
</VJoyTemplate>
|
|
271
|
+
|
|
272
|
+
<!-- Full width + decorative shapes (design-approved) -->
|
|
273
|
+
<VJoyTemplate full shapes sidebar="left">
|
|
274
|
+
<template #template-title>
|
|
275
|
+
<h1>Analytics</h1>
|
|
276
|
+
</template>
|
|
277
|
+
<template #template-main>
|
|
278
|
+
…
|
|
279
|
+
</template>
|
|
280
|
+
</VJoyTemplate>
|
|
281
|
+
</template>
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
In Nuxt (or apps with auto-import), omit the import if `VJoyTemplate` is already global.
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## Related
|
|
289
|
+
|
|
290
|
+
| Component | Use when |
|
|
291
|
+
| --- | --- |
|
|
292
|
+
| `VJoyPanel` | Sections inside `template-main` or `template-sidebar` |
|
|
293
|
+
| `VJoyFunnel` | Multi-step flows instead of a standard page shell |
|
|
294
|
+
| `VJoyWrapper` | Form field spacing and flex layout inside a panel |
|
|
295
|
+
| `VJoyMenu` | Sidebar navigation (place in `#template-sidebar`) |
|
|
296
|
+
| `VJoyIconButton` | Back control in `#template-back` |
|
|
297
|
+
| `VJoyButton` | Page-level actions in `#template-actions` |
|
|
298
|
+
| `VJoyTitleBrand` | Branded / highlighted page titles |
|
|
299
|
+
| `VJoyScreenLoader` | Standalone full-screen loading (template embeds it when `loading`) |
|
|
300
|
+
| `VJoyDialog` / `VJoyDrawer` | Overlays on top of the page — not replacements for the template |
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## For agents
|
|
305
|
+
|
|
306
|
+
Optional for readers; **required** for vibe-coding quality. Maps to `agentDocumentBlocks` in [`JoyTemplate.dsds.json`](./JoyTemplate.dsds.json).
|
|
307
|
+
|
|
308
|
+
### Pick the right component
|
|
309
|
+
|
|
310
|
+
| If the intent is… | Emit… | Do not emit… |
|
|
311
|
+
| --- | --- | --- |
|
|
312
|
+
| Standard app page layout | `VJoyTemplate` + slots | Custom page grid CSS |
|
|
313
|
+
| Section/card inside a page | `VJoyPanel` inside `#template-main` | Nested `VJoyTemplate` |
|
|
314
|
+
| Onboarding / step funnel | `VJoyFunnel` | `VJoyTemplate` with fake stepper chrome |
|
|
315
|
+
| Decorative corner shapes | `VJoyTemplate` + `shapes` | `VJoyTemplateShape` / `TemplateShape` import |
|
|
316
|
+
| Page nav menu | `VJoyMenu` in `#template-sidebar` | `VJoyMenu` outside the sidebar slot |
|
|
317
|
+
| Modal task | `VJoyDialog` | `VJoyTemplate` pretending to be a dialog |
|
|
318
|
+
|
|
319
|
+
### Hard rules
|
|
320
|
+
|
|
321
|
+
1. **MUST** call `joy_get_component_info("VJoyTemplate")` and/or read `JoyTemplate.types.ts` before generating props.
|
|
322
|
+
2. **MUST** include `#template-title` with an **`h1`–`h6`** element (prefer **`h1`**).
|
|
323
|
+
3. **MUST** use only documented props: `full`, `sidebar`, `loading`, `loadingColor`, `shapes`.
|
|
324
|
+
4. **MUST** use slot names exactly: `template-back`, `template-title`, `template-subtitle`, `template-actions`, `template-main`, `template-sidebar`, `template-loader-content`.
|
|
325
|
+
5. **MUST NOT** import `VJoyTemplateShape` or `TemplateShape`.
|
|
326
|
+
6. **MUST NOT** override `--template-layout-width` except via `full` or documented emergency override.
|
|
327
|
+
7. **MUST NOT** add a `<main>` wrapper inside the template — root is already a `<div>`.
|
|
328
|
+
8. **SHOULD** default `sidebar="right"`, `loading={false}`, `shapes={false}`, `full={false}`.
|
|
329
|
+
9. **SHOULD** set `loading` during async page load and optional `#template-loader-content` text.
|
|
330
|
+
|
|
331
|
+
### Valid enums (from `JoyTemplate.types.ts` + MCP)
|
|
332
|
+
|
|
333
|
+
| Prop | Values |
|
|
334
|
+
| --- | --- |
|
|
335
|
+
| `sidebar` | `left`, `right` |
|
|
336
|
+
| `loadingColor` | `light`, `dark` |
|
|
337
|
+
| `full`, `loading`, `shapes` | `boolean` |
|
|
338
|
+
|
|
339
|
+
### Checklist
|
|
340
|
+
|
|
341
|
+
- [ ] Correct component (`VJoyTemplate` or named alternative)
|
|
342
|
+
- [ ] `#template-title` present with heading (`h1` preferred)
|
|
343
|
+
- [ ] Props / enums from MCP or types only
|
|
344
|
+
- [ ] No invented props / no custom template chrome CSS
|
|
345
|
+
- [ ] `VJoyMenu` in `#template-sidebar` when used as page nav
|
|
346
|
+
- [ ] `loading` + loader slot for async page states
|
|
347
|
+
- [ ] `shapes` only when decorative branding is intended
|
|
348
|
+
- [ ] Sections composed with `VJoyPanel`, not one-off layout hacks
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
|
|
352
|
+
## DSDS mapping
|
|
353
|
+
|
|
354
|
+
This Markdown mirrors [`JoyTemplate.dsds.json`](./JoyTemplate.dsds.json) (DSDS **0.15.2**).
|
|
355
|
+
|
|
356
|
+
| Section here | DSDS block |
|
|
357
|
+
| --- | --- |
|
|
358
|
+
| When to use / not | `use-cases` |
|
|
359
|
+
| Anatomy / layout options | `anatomy` |
|
|
360
|
+
| States | `states` |
|
|
361
|
+
| Best practices / content rules | `guidelines` (+ `content`) |
|
|
362
|
+
| Accessibility | `accessibility` |
|
|
363
|
+
| Examples | `sections` |
|
|
364
|
+
| For agents | `agentDocumentBlocks` |
|
|
365
|
+
| Props detail | `api` in JSON + Joy MCP |
|
|
366
|
+
| Layout tokens | `design-specifications` in JSON (token names, not raw px dumps) |
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: VJoyText
|
|
3
|
+
status: draft
|
|
4
|
+
language: en
|
|
5
|
+
dsds: JoyText.dsds.json
|
|
6
|
+
dsdsVersion: "0.15.2"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Text
|
|
10
|
+
|
|
11
|
+
Use **`VJoyText`** when you need body copy or headings with Joy typography tokens — font family, size, line height, and weight — without hand-picking CSS classes.
|
|
12
|
+
|
|
13
|
+
It renders a semantic HTML tag (`p`, `span`, `h1`–`h6`, or `strong`) and applies a `joy-font-*` preset from `@maltjoy/themes`. Text color uses `--joy-color-text-body`.
|
|
14
|
+
|
|
15
|
+
| | |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| **Code** | `VJoyText` from `@maltjoy/core-vue` |
|
|
18
|
+
| **Design** | [Figma — Joy Core Design System](https://www.figma.com/design/jfndp2QBJGS9yeuWbeGuvD/) |
|
|
19
|
+
| **Storybook** | [VJoyText docs](https://doc.malt.tech/joy-storybook/?path=/docs/components-view-vjoytext--docs) |
|
|
20
|
+
| **Fonts reference** | [CSS framework — Advanced fonts](https://doc.malt.tech/joy-storybook/?path=/docs/css-framework--docs#advanced-fonts) |
|
|
21
|
+
| **DSDS (machine)** | [`JoyText.dsds.json`](./JoyText.dsds.json) |
|
|
22
|
+
| **Live API** | `joy_get_component_info("VJoyText")` |
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## When to use this component
|
|
27
|
+
|
|
28
|
+
Use `VJoyText` for readable paragraphs, supporting descriptions, and headings that should follow Joy typography scales — especially when the same preset should stay consistent across the product.
|
|
29
|
+
|
|
30
|
+
Typical jobs: page or panel body copy, helper text under a title, list item descriptions, and semantic headings (`tagName="h2"`, etc.) with a chosen preset.
|
|
31
|
+
|
|
32
|
+
### When not to use this component
|
|
33
|
+
|
|
34
|
+
| Need | Use instead |
|
|
35
|
+
| --- | --- |
|
|
36
|
+
| Branded marketing title with highlighted spans | `VJoyTitleBrand` |
|
|
37
|
+
| A clickable text link inside a sentence | `VJoyLink` |
|
|
38
|
+
| Form field label, required mark, or legend | `VJoyLabel` |
|
|
39
|
+
| Button or icon-only control | `VJoyButton` / `VJoyIconButton` |
|
|
40
|
+
| Raw `joy-font-*` on arbitrary markup | Still prefer `VJoyText` — don’t duplicate typography rules in app CSS |
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## How it works
|
|
45
|
+
|
|
46
|
+
### Anatomy
|
|
47
|
+
|
|
48
|
+
| Part | Required? | What it is |
|
|
49
|
+
| --- | --- | --- |
|
|
50
|
+
| Root element | Yes | Dynamic tag from `tagName` (default `p`) |
|
|
51
|
+
| Typography class | Yes | `joy-font-{preset}` utility from `@maltjoy/themes` |
|
|
52
|
+
| Base text styles | Yes | `.joy-text` — body color, zero margin/padding, `display: block` |
|
|
53
|
+
| Default slot | Yes | Text and inline markup (e.g. `<strong>`) |
|
|
54
|
+
|
|
55
|
+
### Default values
|
|
56
|
+
|
|
57
|
+
- `tagName` defaults to **`p`**
|
|
58
|
+
- `preset` defaults to **`primary-400`**
|
|
59
|
+
|
|
60
|
+
Props and slots: use Joy MCP or Storybook — this page focuses on **when** and **how**, not a full API dump.
|
|
61
|
+
|
|
62
|
+
### Typography presets
|
|
63
|
+
|
|
64
|
+
`preset` maps to a bundled font-family, font-size, line-height, and font-weight. Allowed values come from `TJoyTextFontPreset` (MCP / `JoyText.types.ts`).
|
|
65
|
+
|
|
66
|
+
| Family | Presets | Use when |
|
|
67
|
+
| --- | --- | --- |
|
|
68
|
+
| **Primary** | `primary-100` … `primary-800` (steps: 100, 200, 300, 400, 600, 800) | Default UI copy — body, labels, most headings |
|
|
69
|
+
| **Primary bold** | `primary-150`, `primary-250`, `primary-350`, `primary-450`, `primary-650`, `primary-850` | Same size as the matching `primary-*` step but **bold** (values ending in `50`) |
|
|
70
|
+
| **Secondary** | `secondary-200`, `secondary-400`, `secondary-600`, `secondary-800` | Supporting or de-emphasized copy |
|
|
71
|
+
|
|
72
|
+
**Bold reminder:** `*50` presets match the size of the corresponding `primary-*` step and only apply to the **primary** family. For example, `primary-450` is bold `primary-400`.
|
|
73
|
+
|
|
74
|
+
Pick preset by **hierarchy and emphasis**, not arbitrary pixel sizes. See the [Advanced fonts](https://doc.malt.tech/joy-storybook/?path=/docs/css-framework--docs#advanced-fonts) docs for the full scale.
|
|
75
|
+
|
|
76
|
+
### Semantic tags
|
|
77
|
+
|
|
78
|
+
Set `tagName` to match document structure — `h1`–`h6` for headings, `p` for paragraphs, `span` for inline runs, `strong` when the root itself should be emphasized. Lowercase only.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Best practices
|
|
83
|
+
|
|
84
|
+
Rules use RFC 2119 strength (**MUST** / **SHOULD** / **MUST NOT** / **SHOULD NOT**).
|
|
85
|
+
|
|
86
|
+
### Typography
|
|
87
|
+
|
|
88
|
+
- **MUST** use only documented `preset` values from MCP or `JoyText.types.ts`.
|
|
89
|
+
- **MUST** use Joy tokens — no custom `font-size`, `line-height`, or `font-weight` on `.joy-text` in product CSS.
|
|
90
|
+
- **SHOULD** use **`primary-400`** (default) for standard body text.
|
|
91
|
+
- **SHOULD** use **`secondary-*`** for captions, metadata, or lower-emphasis copy.
|
|
92
|
+
- **SHOULD** use **`primary-*50`** when you need bold at a given primary step — not manual `<strong>` plus a mismatched preset.
|
|
93
|
+
- **MUST NOT** invent presets (e.g. `primary-500`, `tertiary-400`).
|
|
94
|
+
|
|
95
|
+
### Structure and layout
|
|
96
|
+
|
|
97
|
+
- **MUST** set `tagName` to reflect real heading hierarchy — don’t style an `h4` as a page title.
|
|
98
|
+
- **MUST NOT** nest interactive controls inside `VJoyText` — wrap buttons and links as siblings or use `VJoyLink`.
|
|
99
|
+
- **SHOULD** set a **`max-width`** on long copy inside `VJoyWrapper` (or other flex rows) so text wraps instead of stretching the layout.
|
|
100
|
+
|
|
101
|
+
### Do / don’t
|
|
102
|
+
|
|
103
|
+
| Do | Don’t |
|
|
104
|
+
| --- | --- |
|
|
105
|
+
| `preset="primary-600"` + `tagName="h2"` for a section title | `tagName="p"` + oversized custom CSS for headings |
|
|
106
|
+
| `secondary-400` for helper text | `primary-800` for every line on the page |
|
|
107
|
+
| `primary-450` for bold body emphasis | Random `font-weight: 700` overrides |
|
|
108
|
+
| `VJoyTitleBrand` for marketing hero titles | `VJoyText` + custom highlight backgrounds |
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Accessibility
|
|
113
|
+
|
|
114
|
+
Behaviors (what must happen), not slogans.
|
|
115
|
+
|
|
116
|
+
| Behavior | Expectation |
|
|
117
|
+
| --- | --- |
|
|
118
|
+
| Semantics | `tagName` should match the role of the content — real `h1`–`h6` for headings, `p` for paragraphs |
|
|
119
|
+
| Heading order | Don’t skip levels (e.g. `h1` then `h3`) for visual styling alone — pick the right `tagName` and `preset` |
|
|
120
|
+
| Emphasis | Use `<strong>` in the default slot or `tagName="strong"` when emphasis is meaningful, not only for bold styling |
|
|
121
|
+
| Color | Body text uses `--joy-color-text-body`; don’t rely on preset weight alone for critical distinctions |
|
|
122
|
+
| Links | Use `VJoyLink` for navigation — not unstyled `<a>` inside copy without accessible styling |
|
|
123
|
+
|
|
124
|
+
Target: **WCAG 2.2 AA** where the product requires it.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Examples
|
|
129
|
+
|
|
130
|
+
```vue
|
|
131
|
+
<script setup lang="ts">
|
|
132
|
+
import { VJoyText } from '@maltjoy/core-vue'
|
|
133
|
+
</script>
|
|
134
|
+
|
|
135
|
+
<template>
|
|
136
|
+
<!-- Default body -->
|
|
137
|
+
<VJoyText>
|
|
138
|
+
Standard body copy uses preset primary-400 by default.
|
|
139
|
+
</VJoyText>
|
|
140
|
+
|
|
141
|
+
<!-- Section heading -->
|
|
142
|
+
<VJoyText tagName="h2" preset="primary-600">
|
|
143
|
+
Account settings
|
|
144
|
+
</VJoyText>
|
|
145
|
+
|
|
146
|
+
<!-- Supporting caption -->
|
|
147
|
+
<VJoyText preset="secondary-400">
|
|
148
|
+
Last updated 3 days ago
|
|
149
|
+
</VJoyText>
|
|
150
|
+
|
|
151
|
+
<!-- Bold at same scale as primary-400 -->
|
|
152
|
+
<VJoyText preset="primary-450">
|
|
153
|
+
This line is bold primary body text.
|
|
154
|
+
</VJoyText>
|
|
155
|
+
|
|
156
|
+
<!-- Inline emphasis inside a paragraph -->
|
|
157
|
+
<VJoyText>
|
|
158
|
+
Your plan renews on <strong>15 March 2026</strong>.
|
|
159
|
+
</VJoyText>
|
|
160
|
+
</template>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
In Nuxt (or apps with auto-import), omit the import if `VJoyText` is already global.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Related
|
|
168
|
+
|
|
169
|
+
| Component | Use when |
|
|
170
|
+
| --- | --- |
|
|
171
|
+
| `VJoyTitleBrand` | Marketing or dialog titles with highlighted span treatment |
|
|
172
|
+
| `VJoyLink` | Inline or standalone text links |
|
|
173
|
+
| `VJoyLabel` | Form labels, required/optional indicators, legends |
|
|
174
|
+
| `VJoyWrapper` | Flex layout around text — remember `max-width` for long copy |
|
|
175
|
+
| `VJoyHighlight` | Callout blocks with severity styling, not plain paragraphs |
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "JoyText",
|
|
3
3
|
"displayName": "VJoyText",
|
|
4
|
-
"description": "This component
|
|
4
|
+
"description": "This component uses CSS utility classes from `@maltjoy/themes` (`dist/default.css`).\n\n**Reminder**: values ending with 50 have same size but are bold.\n\nSee \"Fonts\" section here https://doc.malt.tech/joy-storybook/?path=/docs/css-framework--docs#advanced-fonts\n\n**Warning** If you use long text within a VJoyWrapper, you'll have to set a max-width to prevent the text from breaking the layout.",
|
|
5
5
|
"category": "View",
|
|
6
6
|
"props": [
|
|
7
7
|
{
|