@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,425 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: VJoyDialog
|
|
3
|
+
status: draft
|
|
4
|
+
language: en
|
|
5
|
+
dsds: JoyDialog.dsds.json
|
|
6
|
+
dsdsVersion: "0.15.2"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Dialog
|
|
10
|
+
|
|
11
|
+
Use **`VJoyDialog`** when you need a modal overlay that interrupts the current task — confirmations, forms, multi-step flows, or focused messaging.
|
|
12
|
+
|
|
13
|
+
It teleports to `body` by default, supports header/body/footer slots, optional banner imagery, confirm/cancel CTAs, and exposes async `show()` / `hide()` methods. Use **`VJoyDialogTrigger`** when a declarative open trigger is simpler than imperative refs.
|
|
14
|
+
|
|
15
|
+
| | |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| **Code** | `VJoyDialog` from `@maltjoy/core-vue` |
|
|
18
|
+
| **Design** | [Figma — Joy Core Design System](https://www.figma.com/design/jfndp2QBJGS9yeuWbeGuvD/%F0%9F%9F%A0--Joy---Core-Design-System--official-) |
|
|
19
|
+
| **Storybook** | [VJoyDialog docs](https://doc.malt.tech/joy-storybook/?path=/docs/components-overlays-vjoydialog--docs) |
|
|
20
|
+
| **DSDS (machine)** | [`JoyDialog.dsds.json`](./JoyDialog.dsds.json) |
|
|
21
|
+
| **Live API** | `joy_get_component_info("VJoyDialog")` |
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## When to use this component
|
|
26
|
+
|
|
27
|
+
Use a dialog when the user must read, decide, or complete something before returning to the page behind it — for example confirming a destructive action, collecting a short form, or presenting a focused announcement.
|
|
28
|
+
|
|
29
|
+
Dialogs block interaction with the underlying page (modal overlay) and should be dismissed explicitly or via a clear cancel path.
|
|
30
|
+
|
|
31
|
+
### When not to use this component
|
|
32
|
+
|
|
33
|
+
| Need | Use instead |
|
|
34
|
+
| --- | --- |
|
|
35
|
+
| Slide-in panel from the edge (filters, details, long forms) | `VJoyDrawer` |
|
|
36
|
+
| Lightweight contextual hint on hover/focus | `VJoyTooltip` |
|
|
37
|
+
| Inline expandable section on the same page | `VJoyAccordion` or page layout — not a dialog |
|
|
38
|
+
| Toast / transient feedback after an action | `VJoyToast` |
|
|
39
|
+
| Custom modal markup with ad-hoc CSS | Still use `VJoyDialog` + Joy tokens — don't reinvent overlay chrome |
|
|
40
|
+
|
|
41
|
+
> **Experimental:** `patternBrand` activates a centered brand layout with decorative shapes. Treat it as experimental until promoted; confirm with design before broad rollout.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## How it works
|
|
46
|
+
|
|
47
|
+
### Anatomy
|
|
48
|
+
|
|
49
|
+
| Part | Required? | What it is |
|
|
50
|
+
| --- | --- | --- |
|
|
51
|
+
| Overlay | Yes | Semi-transparent backdrop; click dismisses unless `patternConfirm` |
|
|
52
|
+
| Container (`joy-dialog__inner`) | Yes | White card with elevation, padding, and max width |
|
|
53
|
+
| Preheader (`dialog-preheader`) | No | Short meta above the title (e.g. tag, badge) |
|
|
54
|
+
| Header (`dialog-header`) | Yes (content) | Dialog title — linked via `aria-labelledby` |
|
|
55
|
+
| Subheader (`dialog-subheader`) | No | Supporting description below the title |
|
|
56
|
+
| Close button | No* | Top-right `VJoyIconButton` (*hidden when `patternConfirm`) |
|
|
57
|
+
| Body (`dialog-body`) | Yes (content) | Main content; scrolls when tall |
|
|
58
|
+
| Footer | No | Cancel / confirm CTAs via props or slots |
|
|
59
|
+
| Banner | No | Optional top image via `bannerSrc` |
|
|
60
|
+
| Brand shapes | No | Decorative shapes when `patternBrand` is true |
|
|
61
|
+
| Indicators (`dialog-indicators`) | No | Step dots for multi-dialog flows (`VJoyIndicators`) |
|
|
62
|
+
|
|
63
|
+
### Default values
|
|
64
|
+
|
|
65
|
+
- `size` defaults to **`default`** (580px container width; `large` → 780px)
|
|
66
|
+
- `open` defaults to **`false`**
|
|
67
|
+
- `teleport` defaults to **`body`**
|
|
68
|
+
- `preventBodyScroll` defaults to **`true`** (locks page scroll while open)
|
|
69
|
+
- `closeLabel` defaults to **`"Close dialog"`**
|
|
70
|
+
- `buttonSize` defaults to **`medium`** (footer CTAs)
|
|
71
|
+
- `bannerHeight` defaults to **`250`** (px, when `bannerSrc` is set)
|
|
72
|
+
- `patternConfirm` defaults to **`false`**
|
|
73
|
+
- `patternBrand` defaults to **`false`**
|
|
74
|
+
|
|
75
|
+
Props, events, slots, and exposed methods: 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.
|
|
76
|
+
|
|
77
|
+
### Open / close lifecycle
|
|
78
|
+
|
|
79
|
+
1. **Open** — set `open` or call `show()` on the exposed ref. Body scroll is prevented when `preventBodyScroll` is true.
|
|
80
|
+
2. **Dismiss** — close icon, backdrop click, Escape key, or cancel CTA (default wiring). All fire `dialog:hide` when the leave transition starts.
|
|
81
|
+
3. **Confirm** — default confirm CTA emits `dialog:confirm` only; you still handle persistence and closing.
|
|
82
|
+
4. **Unmount while open** — emits `dialog:before-unmount` and restores body scroll.
|
|
83
|
+
|
|
84
|
+
`show()` and `hide()` are **async**. `hide({ fireHideEvent: false })` closes without emitting `dialog:hide`.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Variants
|
|
89
|
+
|
|
90
|
+
Dialogs don't have color variants. Choose layout **patterns** and **size** by context.
|
|
91
|
+
|
|
92
|
+
### Default pattern
|
|
93
|
+
|
|
94
|
+
Standard left-aligned header, optional subheader, scrollable body, footer CTAs right-aligned. Backdrop click, Escape, and close icon all dismiss.
|
|
95
|
+
|
|
96
|
+
Use for most product dialogs — forms, confirmations, informational modals.
|
|
97
|
+
|
|
98
|
+
### Confirm pattern (`patternConfirm`)
|
|
99
|
+
|
|
100
|
+
Hides the close icon, disables backdrop dismiss, and ignores Escape. The user must choose a footer CTA (typically cancel or confirm).
|
|
101
|
+
|
|
102
|
+
Use when accidental dismissal would lose work or cause harm — destructive confirms, irreversible choices, or incomplete required input.
|
|
103
|
+
|
|
104
|
+
Avoid for low-stakes content where users expect quick escape (use the default pattern).
|
|
105
|
+
|
|
106
|
+
### Brand pattern (`patternBrand`) — experimental
|
|
107
|
+
|
|
108
|
+
Centered text layout with decorative primary-colored shapes. Works with `patternConfirm`. Shapes cannot be disabled.
|
|
109
|
+
|
|
110
|
+
Use for brand moments, onboarding highlights, or marketing-style announcements approved by design.
|
|
111
|
+
|
|
112
|
+
Avoid combining with `bannerSrc` — they are not meant to work together. If you use an image in the body, set an explicit `width` on the `<img>`.
|
|
113
|
+
|
|
114
|
+
### Banner image (`bannerSrc`)
|
|
115
|
+
|
|
116
|
+
Full-width image strip at the top of the dialog card.
|
|
117
|
+
|
|
118
|
+
Use for visual context (illustration, hero image) that supports the title.
|
|
119
|
+
|
|
120
|
+
Avoid when `patternBrand` is active. Prefer Joy DAM assets with known dimensions.
|
|
121
|
+
|
|
122
|
+
### Not in the API: extra sizes
|
|
123
|
+
|
|
124
|
+
Only `default` and `large` exist in `TJoyDialogSizes`. Do not invent `small` / `medium` dialog sizes. Use `size="large"` for wider content; width tokens live in `--dialog-width` (override via CSS custom property only when design approves).
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Sizes
|
|
129
|
+
|
|
130
|
+
Container width is token-driven inside the component — **don't hardcode pixel widths** in apps.
|
|
131
|
+
|
|
132
|
+
| Size | Use when |
|
|
133
|
+
| --- | --- |
|
|
134
|
+
| `default` | Standard dialogs (580px on desktop) |
|
|
135
|
+
| `large` | Wider content — tables, two-column forms, rich media (780px on desktop) |
|
|
136
|
+
|
|
137
|
+
On viewports ≤ 767px the dialog becomes full-screen. Footer CTAs stack vertically on very narrow widths (≤ 400px).
|
|
138
|
+
|
|
139
|
+
Optional CSS overrides (use sparingly, with design approval):
|
|
140
|
+
|
|
141
|
+
- `--dialog-width` — container width
|
|
142
|
+
- `--dialog-padding` — inner padding (all sides)
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## States
|
|
147
|
+
|
|
148
|
+
| State | What the user sees / can do |
|
|
149
|
+
| --- | --- |
|
|
150
|
+
| Closed | Not in DOM flow (`v-if="isOpen"`); no overlay |
|
|
151
|
+
| Opening | Enter transition (scale + fade, 300ms) |
|
|
152
|
+
| Open | Modal overlay; focusable body; dismiss via close / backdrop / Escape (unless `patternConfirm`) |
|
|
153
|
+
| Closing | Leave transition (100ms); `dialog:hide` fires at start |
|
|
154
|
+
| Closed (after transition) | Removed from DOM; `dialog:after-hide` fires; body scroll restored |
|
|
155
|
+
| Confirm pattern | No close icon; backdrop not dismissible; Escape disabled |
|
|
156
|
+
| Scrollable body | Long content scrolls inside body (`max-height` ~580px on desktop) |
|
|
157
|
+
| Demo / docs | `demoMode` prevents hide (Storybook only — not for production) |
|
|
158
|
+
|
|
159
|
+
Prefer `loading` on footer `VJoyButton` instances during async confirm work instead of silently disabling the dialog.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Best practices
|
|
164
|
+
|
|
165
|
+
Rules use RFC 2119 strength (**MUST** / **SHOULD** / **MUST NOT** / **SHOULD NOT**).
|
|
166
|
+
|
|
167
|
+
### Hierarchy and placement
|
|
168
|
+
|
|
169
|
+
- **SHOULD** use one dialog per decision — don't stack unrelated modals.
|
|
170
|
+
- **SHOULD** use `dialog-indicators` + `VJoyIndicators` when navigating a sequence of related dialogs.
|
|
171
|
+
- **MUST NOT** use a dialog for content that fits inline on the page.
|
|
172
|
+
|
|
173
|
+
### Implementation
|
|
174
|
+
|
|
175
|
+
- **MUST** use only documented props and enum values (MCP / `JoyDialog.types.ts`).
|
|
176
|
+
- **MUST** teleport to `body` in production (`teleport` default) — `disableTeleport` is for tests/docs.
|
|
177
|
+
- **MUST** wire `dialog:hide` (or call `hide()`) when using custom `dialog-cancel` / `dialog-confirm` slots.
|
|
178
|
+
- **MUST NOT** invent props (`width`, `variant`, `theme`, …).
|
|
179
|
+
- **MUST NOT** override `.joy-dialog` chrome (background, shadow, radius, overlay) with app CSS.
|
|
180
|
+
- **MUST NOT** use `demoMode` outside Storybook.
|
|
181
|
+
|
|
182
|
+
### Interaction
|
|
183
|
+
|
|
184
|
+
- **MUST** provide a visible dismiss path in the default pattern (close icon and/or cancel CTA).
|
|
185
|
+
- **SHOULD** use `patternConfirm` only when dismissal risk is real.
|
|
186
|
+
- **SHOULD** call `show()` / `hide()` with `await` when chaining transitions or focus management.
|
|
187
|
+
- **SHOULD** listen to `dialog:after-open` before moving focus into the first field.
|
|
188
|
+
|
|
189
|
+
### Footer CTAs
|
|
190
|
+
|
|
191
|
+
- **SHOULD** use `cancelText` / `confirmText` for simple cases (default `VJoyButton` wiring).
|
|
192
|
+
- **SHOULD** use `dialog-cancel` / `dialog-confirm` slots when you need custom variants, icons, or sizes — and **MUST** call `hide()` yourself on cancel.
|
|
193
|
+
- **SHOULD** use one `main` confirm CTA per dialog surface (see `VJoyButton` guidelines).
|
|
194
|
+
|
|
195
|
+
### Do / don't
|
|
196
|
+
|
|
197
|
+
| Do | Don't |
|
|
198
|
+
| --- | --- |
|
|
199
|
+
| `VJoyDialogTrigger` for simple open buttons | Reimplement overlay + z-index stack |
|
|
200
|
+
| `patternConfirm` for destructive confirms | Default pattern with no cancel CTA |
|
|
201
|
+
| Explicit `closeLabel` when locale ≠ English default | Leave default "Close dialog" in localized apps |
|
|
202
|
+
| `size="large"` for wide tables/forms | Hardcode `width: 780px` on a wrapper |
|
|
203
|
+
| `bannerSrc` **or** `patternBrand` | Both at once |
|
|
204
|
+
| Set `width` on body images in brand pattern | Unsized images that blow layout |
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Content
|
|
209
|
+
|
|
210
|
+
Dialogs carry the highest-stakes copy on a surface. Title, description, and CTAs must be scannable and action-oriented.
|
|
211
|
+
|
|
212
|
+
### Title formula
|
|
213
|
+
|
|
214
|
+
**Short noun phrase or question** — state the decision or topic, not the implementation:
|
|
215
|
+
|
|
216
|
+
- ✅ Delete project brief?
|
|
217
|
+
- ✅ Update billing address
|
|
218
|
+
- ✅ New feature: AI suggestions
|
|
219
|
+
|
|
220
|
+
**Subheader** — one sentence of context or consequence. Don't repeat the title.
|
|
221
|
+
|
|
222
|
+
### Body copy
|
|
223
|
+
|
|
224
|
+
- **SHOULD** keep body text concise; link out for long legal or help content.
|
|
225
|
+
- **MUST** explain consequences before destructive confirms (what is deleted, whether it's reversible).
|
|
226
|
+
- **SHOULD NOT** bury the primary action below long paragraphs.
|
|
227
|
+
|
|
228
|
+
### Footer CTA rules
|
|
229
|
+
|
|
230
|
+
Follow `VJoyButton` content rules. Dialog-specific expectations:
|
|
231
|
+
|
|
232
|
+
| Strength | Rule |
|
|
233
|
+
| --- | --- |
|
|
234
|
+
| **MUST** | Confirm CTA names the outcome — ✅ `Delete project`, `Save changes` |
|
|
235
|
+
| **MUST** | Cancel / dismiss CTA is neutral — ✅ `Cancel`, `Not now` |
|
|
236
|
+
| **MUST NOT** | Vague confirm — ❌ `OK`, `Yes` (unless paired with an unmistakable title) |
|
|
237
|
+
| **MUST NOT** | Guilt-trip cancel — ❌ `No thanks`, `I don't want to save` |
|
|
238
|
+
| **SHOULD** | Destructive confirm repeats the object — ✅ `Delete 6 files` |
|
|
239
|
+
| **SHOULD** | Match title wording between header and confirm CTA |
|
|
240
|
+
| **SHOULD** | ≤ 25 characters per button label; wrap, don't truncate |
|
|
241
|
+
|
|
242
|
+
### Patterns
|
|
243
|
+
|
|
244
|
+
**Destructive confirm** — Title states the action; body states impact; `patternConfirm` with cancel + destructive-styled confirm (custom slot if needed). Example: title `Delete project brief?`, body `This cannot be undone.`, CTAs `Cancel` + `Delete project brief`.
|
|
245
|
+
|
|
246
|
+
**Informational** — Title + short body; single `main` or `primary` confirm (`Got it`, `Continue`). Default dismiss paths are enough; `patternConfirm` usually unnecessary.
|
|
247
|
+
|
|
248
|
+
**Multi-step** — Use `dialog-indicators` with `VJoyIndicators`; keep titles consistent per step; final step confirm names completion (`Finish setup`).
|
|
249
|
+
|
|
250
|
+
**Brand / promo (experimental)** — Centered copy; joyful tone allowed; still one clear primary CTA. Images need explicit dimensions.
|
|
251
|
+
|
|
252
|
+
**Localized apps** — Translate `closeLabel`, `cancelText`, `confirmText`, and all slot content. French copy may need articles/pronouns per `VJoyButton` FR guidance.
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## Accessibility
|
|
257
|
+
|
|
258
|
+
Behaviors (what must happen), not slogans.
|
|
259
|
+
|
|
260
|
+
| Behavior | Expectation |
|
|
261
|
+
| --- | --- |
|
|
262
|
+
| Role | `role="dialog"` with `aria-modal="true"` |
|
|
263
|
+
| Name | Title in `dialog-header` referenced by `aria-labelledby` (`{id}-header`) |
|
|
264
|
+
| Description | Subheader content in `#dialogDescription` when present |
|
|
265
|
+
| Close control | `VJoyIconButton` with `closeLabel` (default: "Close dialog") |
|
|
266
|
+
| Keyboard | **Escape** dismisses unless `patternConfirm` |
|
|
267
|
+
| Focus | Body region is focusable (`tabindex="0"`); move focus into dialog on open when implementing custom flows |
|
|
268
|
+
| Scroll | Page scroll locked while open (`preventBodyScroll`) |
|
|
269
|
+
| Confirm pattern | User is not trapped without a labeled footer action |
|
|
270
|
+
| Motion | Enter/leave transitions; respect `prefers-reduced-motion` at app level if required |
|
|
271
|
+
|
|
272
|
+
Target: **WCAG 2.2 AA** where the product requires it.
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## Examples
|
|
277
|
+
|
|
278
|
+
```vue
|
|
279
|
+
<script setup lang="ts">
|
|
280
|
+
import { ref } from 'vue'
|
|
281
|
+
import { VJoyDialog } from '@maltjoy/core-vue'
|
|
282
|
+
|
|
283
|
+
const dialog = ref<InstanceType<typeof VJoyDialog>>()
|
|
284
|
+
|
|
285
|
+
async function openDialog() {
|
|
286
|
+
await dialog.value?.show()
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
async function onConfirm() {
|
|
290
|
+
// persist, then close
|
|
291
|
+
await dialog.value?.hide()
|
|
292
|
+
}
|
|
293
|
+
</script>
|
|
294
|
+
|
|
295
|
+
<template>
|
|
296
|
+
<!-- Basic dialog with prop-driven CTAs -->
|
|
297
|
+
<VJoyDialog
|
|
298
|
+
ref="dialog"
|
|
299
|
+
cancel-text="Cancel"
|
|
300
|
+
confirm-text="Save changes"
|
|
301
|
+
@dialog:confirm="onConfirm"
|
|
302
|
+
@dialog:hide="() => {}"
|
|
303
|
+
>
|
|
304
|
+
<template #dialog-header>Update profile</template>
|
|
305
|
+
<template #dialog-subheader>Changes apply to your public listing.</template>
|
|
306
|
+
<template #dialog-body>
|
|
307
|
+
<!-- form fields -->
|
|
308
|
+
</template>
|
|
309
|
+
</VJoyDialog>
|
|
310
|
+
|
|
311
|
+
<VJoyButton variant="primary" label="Edit profile" @click="openDialog" />
|
|
312
|
+
|
|
313
|
+
<!-- Confirm pattern (no accidental dismiss) -->
|
|
314
|
+
<VJoyDialog
|
|
315
|
+
pattern-confirm
|
|
316
|
+
cancel-text="Cancel"
|
|
317
|
+
confirm-text="Delete project"
|
|
318
|
+
@dialog:confirm="onConfirm"
|
|
319
|
+
>
|
|
320
|
+
<template #dialog-header>Delete project brief?</template>
|
|
321
|
+
<template #dialog-body>This action cannot be undone.</template>
|
|
322
|
+
</VJoyDialog>
|
|
323
|
+
|
|
324
|
+
<!-- Custom footer CTAs (you must call hide on cancel) -->
|
|
325
|
+
<VJoyDialog ref="customDialog">
|
|
326
|
+
<template #dialog-header>Custom actions</template>
|
|
327
|
+
<template #dialog-body>…</template>
|
|
328
|
+
<template #dialog-cancel>
|
|
329
|
+
<VJoyButton variant="ghost" label="Cancel" @click="customDialog?.hide()" />
|
|
330
|
+
</template>
|
|
331
|
+
<template #dialog-confirm>
|
|
332
|
+
<VJoyButton variant="main" label="Confirm" @click="onConfirm" />
|
|
333
|
+
</template>
|
|
334
|
+
</VJoyDialog>
|
|
335
|
+
</template>
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
In Nuxt (or apps with auto-import), omit imports if `VJoyDialog` and `VJoyButton` are already global.
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
## Related
|
|
343
|
+
|
|
344
|
+
| Component | Use when |
|
|
345
|
+
| --- | --- |
|
|
346
|
+
| `VJoyDialogTrigger` | Declarative open trigger wrapping any activator |
|
|
347
|
+
| `VJoyDrawer` | Edge panel; long or exploratory content |
|
|
348
|
+
| `VJoyButton` | Footer CTAs (default or custom slots) |
|
|
349
|
+
| `VJoyIconButton` | Close control (built-in) |
|
|
350
|
+
| `VJoyIndicators` / `VJoyIndicator` | Multi-step dialog navigation |
|
|
351
|
+
| `VJoyTag` | Preheader badges (e.g. "New", "Beta") |
|
|
352
|
+
| `VJoyTitleBrand` | Brand-styled titles inside templates or dialogs |
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## For agents
|
|
357
|
+
|
|
358
|
+
Optional for readers; **required** for vibe-coding quality. Maps to `agentDocumentBlocks` in [`JoyDialog.dsds.json`](./JoyDialog.dsds.json).
|
|
359
|
+
|
|
360
|
+
### Pick the right component
|
|
361
|
+
|
|
362
|
+
| If the intent is… | Emit… | Do not emit… |
|
|
363
|
+
| --- | --- | --- |
|
|
364
|
+
| Modal decision / form / confirm | `VJoyDialog` | Custom `position: fixed` div |
|
|
365
|
+
| Side panel / filters / details | `VJoyDrawer` | `VJoyDialog` with hacked full height |
|
|
366
|
+
| Simple open from a button | `VJoyDialog` + `VJoyDialogTrigger` | Inline overlay markup |
|
|
367
|
+
| Must prevent mis-click dismiss | `patternConfirm` | Default pattern without cancel |
|
|
368
|
+
| Brand onboarding moment | `patternBrand` (experimental) | Custom decorative CSS shapes |
|
|
369
|
+
| Hero image on top | `bannerSrc` | `patternBrand` + `bannerSrc` together |
|
|
370
|
+
| Icon-only close | Built-in close `VJoyIconButton` | Raw button with `×` character |
|
|
371
|
+
|
|
372
|
+
### Hard rules
|
|
373
|
+
|
|
374
|
+
1. **MUST** call MCP (`joy_get_component_info`, `joy_get_component_types`) before generating props.
|
|
375
|
+
2. **MUST** populate `dialog-header` (accessible name) for every dialog.
|
|
376
|
+
3. **MUST** handle `hide()` when using `dialog-cancel` / `dialog-confirm` slots.
|
|
377
|
+
4. **MUST** use `cancelText` / `confirmText` only when default `VJoyButton` wiring is enough.
|
|
378
|
+
5. **MUST NOT** invent props, sizes, or variants (`size` is only `default` \| `large`).
|
|
379
|
+
6. **MUST NOT** set `demoMode` in product code.
|
|
380
|
+
7. **MUST NOT** combine `bannerSrc` with `patternBrand`.
|
|
381
|
+
8. **MUST NOT** override `.joy-dialog` overlay, shadow, radius, or z-index in app CSS.
|
|
382
|
+
9. **SHOULD** use `patternConfirm` for destructive or data-loss scenarios.
|
|
383
|
+
10. **SHOULD** set localized `closeLabel` when UI language ≠ English.
|
|
384
|
+
11. **SHOULD** `await` `show()` / `hide()` when coordinating focus or route changes.
|
|
385
|
+
|
|
386
|
+
### Slot checklist
|
|
387
|
+
|
|
388
|
+
- [ ] `dialog-header` — title present
|
|
389
|
+
- [ ] `dialog-subheader` — only if extra context needed
|
|
390
|
+
- [ ] `dialog-body` — main content
|
|
391
|
+
- [ ] `dialog-preheader` — optional meta (tag)
|
|
392
|
+
- [ ] `dialog-cancel` / `dialog-confirm` — only when customizing CTAs (+ manual `hide`)
|
|
393
|
+
- [ ] `dialog-indicators` — only for multi-step flows
|
|
394
|
+
|
|
395
|
+
### Generation checklist
|
|
396
|
+
|
|
397
|
+
- [ ] Correct component (`VJoyDialog` or named alternative)
|
|
398
|
+
- [ ] Props / enums from MCP only (`size`, `buttonSize`, booleans)
|
|
399
|
+
- [ ] No invented props / no custom dialog chrome CSS
|
|
400
|
+
- [ ] Dismiss path defined (default or `patternConfirm` + footer)
|
|
401
|
+
- [ ] Confirm CTA label names the outcome (not bare `OK`)
|
|
402
|
+
- [ ] Custom slots wire `hide()` on cancel
|
|
403
|
+
- [ ] `closeLabel` localized when needed
|
|
404
|
+
- [ ] `bannerSrc` xor `patternBrand` — never both
|
|
405
|
+
- [ ] Images in brand pattern have explicit `width`
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
## DSDS mapping
|
|
410
|
+
|
|
411
|
+
This Markdown mirrors [`JoyDialog.dsds.json`](./JoyDialog.dsds.json) (DSDS **0.15.2**).
|
|
412
|
+
|
|
413
|
+
| Section here | DSDS block |
|
|
414
|
+
| --- | --- |
|
|
415
|
+
| When to use / not | `use-cases` |
|
|
416
|
+
| Anatomy | `anatomy` |
|
|
417
|
+
| Variants / sizes / patterns | `variants` |
|
|
418
|
+
| States | `states` |
|
|
419
|
+
| Best practices / content rules | `guidelines` (+ `content`) |
|
|
420
|
+
| Accessibility | `accessibility` |
|
|
421
|
+
| Examples | `sections` |
|
|
422
|
+
| For agents | `agentDocumentBlocks` |
|
|
423
|
+
| Props detail | `api` in JSON + Joy MCP |
|
|
424
|
+
| Imports | `imports` in JSON |
|
|
425
|
+
| Token sizing | `design-specifications` in JSON (`--dialog-width`, spacing tokens) |
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: VJoyDialogTrigger
|
|
3
|
+
status: draft
|
|
4
|
+
language: en
|
|
5
|
+
dsds: JoyDialogTrigger.dsds.json
|
|
6
|
+
dsdsVersion: "0.15.2"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Dialog trigger
|
|
10
|
+
|
|
11
|
+
Use **`VJoyDialogTrigger`** when a declarative click target should open an existing **`VJoyDialog`** — for example a button or icon control wired to a dialog ref without writing a custom `@click` handler.
|
|
12
|
+
|
|
13
|
+
It renders the default slot as the activator, emits `click`, then calls the linked dialog’s async `show()` method. The trigger adds no visual chrome; styling and semantics come from the slotted control (commonly `VJoyButton` or `VJoyIconButton`).
|
|
14
|
+
|
|
15
|
+
| | |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| **Code** | `VJoyDialogTrigger` from `@maltjoy/core-vue` |
|
|
18
|
+
| **Design** | [Figma — Joy Core Design System](https://www.figma.com/design/jfndp2QBJGS9yeuWbeGuvD/%F0%9F%9F%A0--Joy---Core-Design-System--official-) |
|
|
19
|
+
| **Storybook** | [VJoyDialog docs](https://doc.malt.tech/joy-storybook/?path=/docs/components-overlays-vjoydialog--docs) (subcomponent) |
|
|
20
|
+
| **DSDS (machine)** | [`JoyDialogTrigger.dsds.json`](./JoyDialogTrigger.dsds.json) |
|
|
21
|
+
| **Live API** | `joy_get_component_info("VJoyDialogTrigger")` |
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## When to use this component
|
|
26
|
+
|
|
27
|
+
Use a dialog trigger when the user opens a modal from a visible control in the template — a labeled button, icon button, or link-style activator — and you already have a `VJoyDialog` with a template ref.
|
|
28
|
+
|
|
29
|
+
Pair **`VJoyDialog`** (content, overlay, dismiss rules) with **`VJoyDialogTrigger`** (open wiring). The trigger keeps open logic declarative: pass the dialog ref via `:dialog`, put the activator in the default slot.
|
|
30
|
+
|
|
31
|
+
You can place **multiple activators** in the default slot; each one opens the same dialog on click.
|
|
32
|
+
|
|
33
|
+
### When not to use this component
|
|
34
|
+
|
|
35
|
+
| Need | Use instead |
|
|
36
|
+
| --- | --- |
|
|
37
|
+
| Open the dialog from code (route change, API callback, timer) | `await dialogRef.value?.show()` on the `VJoyDialog` ref |
|
|
38
|
+
| Slide-in panel from the edge | `VJoyDrawer` + `VJoyDrawerTrigger` |
|
|
39
|
+
| Mobile bottom sheet | `VJoyBottomSheet` + `VJoyBottomSheetTrigger` |
|
|
40
|
+
| Lightweight hover hint | `VJoyTooltip` |
|
|
41
|
+
| Custom modal markup with ad-hoc CSS | Still use `VJoyDialog` + `VJoyDialogTrigger` — don’t reinvent overlay chrome |
|
|
42
|
+
|
|
43
|
+
> **Removed from API:** Legacy Stencil `joy-dialog-trigger` used a string `dialog` id and optional `step` for multi-step flows. **`VJoyDialogTrigger` takes a `VJoyDialog` template ref only** — no `step` prop. Control dialog content and indicators on `VJoyDialog` itself.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## How it works
|
|
48
|
+
|
|
49
|
+
### Anatomy
|
|
50
|
+
|
|
51
|
+
| Part | Required? | What it is |
|
|
52
|
+
| --- | --- | --- |
|
|
53
|
+
| Trigger wrapper | Yes | Headless Vue wrapper — no root DOM of its own beyond slotted nodes |
|
|
54
|
+
| Default slot (activator) | Yes | One or more click targets (`VJoyButton`, `<button>`, `VJoyIconButton`, …) |
|
|
55
|
+
| `dialog` prop | Yes | Template ref to the target `VJoyDialog` instance |
|
|
56
|
+
| `click` event | No* | Fires on activator click, **before** `dialog.show()` (*optional listener) |
|
|
57
|
+
|
|
58
|
+
On click, the component emits `click`, then awaits `renderedDialog.value?.show()`. A computed `renderedDialog` mirrors the `dialog` prop so the ref is read at click time — this avoids races when the dialog ref is still `null` on first mount.
|
|
59
|
+
|
|
60
|
+
### Default values
|
|
61
|
+
|
|
62
|
+
- `dialog` — **required** in practice; type is `InstanceType<typeof VJoyDialog> | null | undefined` until the ref is bound
|
|
63
|
+
|
|
64
|
+
Props, events, and slots: use Joy MCP or Storybook — this page focuses on **when** and **how**, not a full API dump.
|
|
65
|
+
|
|
66
|
+
### Composition pattern
|
|
67
|
+
|
|
68
|
+
```vue
|
|
69
|
+
<VJoyDialog ref="myDialog">…</VJoyDialog>
|
|
70
|
+
|
|
71
|
+
<VJoyDialogTrigger :dialog="myDialog">
|
|
72
|
+
<VJoyButton variant="main" label="Open settings" />
|
|
73
|
+
</VJoyDialogTrigger>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Declare `myDialog` as `ref<InstanceType<typeof VJoyDialog> | null>(null)`.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Best practices
|
|
81
|
+
|
|
82
|
+
Rules use RFC 2119 strength (**MUST** / **SHOULD** / **MUST NOT** / **SHOULD NOT**).
|
|
83
|
+
|
|
84
|
+
### Structure
|
|
85
|
+
|
|
86
|
+
- **SHOULD** use one `VJoyDialog` per overlay and pass its ref to `:dialog`.
|
|
87
|
+
- **SHOULD** put a **focusable, named** control in the default slot (`VJoyButton`, `VJoyIconButton`, or native `<button>`).
|
|
88
|
+
- **SHOULD** prefer `VJoyDialogTrigger` over inline `@click="dialogRef?.show()"` when the open action is a template-local button.
|
|
89
|
+
- **MAY** render multiple activators in the default slot when several controls should open the same dialog.
|
|
90
|
+
|
|
91
|
+
### Implementation
|
|
92
|
+
|
|
93
|
+
- **MUST** pass the `VJoyDialog` template ref to `:dialog` — not a string id.
|
|
94
|
+
- **MUST** use only documented props and events from component types / MCP.
|
|
95
|
+
- **MUST NOT** invent props (`step`, `open`, `variant`, …).
|
|
96
|
+
- **MUST NOT** add custom overlay or z-index CSS on the trigger — it has no visual surface.
|
|
97
|
+
- **SHOULD** handle dialog content, confirm/cancel, and dismiss rules on `VJoyDialog` (see [`JoyDialog.DSDS.guideline.md`](../JoyDialog/JoyDialog.DSDS.guideline.md)).
|
|
98
|
+
- **SHOULD** use imperative `show()` when opening is not tied to a slotted click target.
|
|
99
|
+
|
|
100
|
+
### Do / don’t
|
|
101
|
+
|
|
102
|
+
| Do | Don’t |
|
|
103
|
+
| --- | --- |
|
|
104
|
+
| `VJoyButton` with clear label in the slot | Empty `<div @click>` without keyboard support |
|
|
105
|
+
| `:dialog="dialogRef"` bound to `ref<InstanceType<typeof VJoyDialog>>` | String id from legacy Stencil API |
|
|
106
|
+
| `VJoyDialog` for modal content and close behavior | Duplicate dialog markup next to the trigger |
|
|
107
|
+
| `dialogRef.value?.show()` for programmatic open | `VJoyDialogTrigger` with no slotted activator |
|
|
108
|
+
| Listen to `@click` for analytics before open | Rely on the trigger to close the dialog |
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Accessibility
|
|
113
|
+
|
|
114
|
+
`VJoyDialogTrigger` is a **behavioral** wrapper. Accessible name, role, and keyboard support come from the **slotted activator**.
|
|
115
|
+
|
|
116
|
+
| Behavior | Expectation |
|
|
117
|
+
| --- | --- |
|
|
118
|
+
| Role | No role on the wrapper — the slot child provides it (e.g. `button`) |
|
|
119
|
+
| Name | Activator **MUST** have an accessible name (`label` on `VJoyButton` / `VJoyIconButton`, visible text, or `aria-label`) |
|
|
120
|
+
| Keyboard | Activator **MUST** be focusable and activatable with **Enter** / **Space** when it is a button |
|
|
121
|
+
| Focus after open | Focus management is handled by `VJoyDialog` when the overlay opens — not by the trigger |
|
|
122
|
+
| Multiple triggers | Each activator needs its own accessible name |
|
|
123
|
+
|
|
124
|
+
Target: **WCAG 2.2 AA** where the product requires it — meet requirements through the slotted control and `VJoyDialog` focus trap / dismiss behavior.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Examples
|
|
129
|
+
|
|
130
|
+
```vue
|
|
131
|
+
<script setup lang="ts">
|
|
132
|
+
import { ref } from 'vue'
|
|
133
|
+
import {
|
|
134
|
+
VJoyDialog,
|
|
135
|
+
VJoyDialogTrigger,
|
|
136
|
+
VJoyButton,
|
|
137
|
+
VJoyIconButton,
|
|
138
|
+
} from '@maltjoy/core-vue'
|
|
139
|
+
|
|
140
|
+
const settingsDialog = ref<InstanceType<typeof VJoyDialog> | null>(null)
|
|
141
|
+
|
|
142
|
+
function onTriggerClick() {
|
|
143
|
+
// Optional: analytics or guard logic — runs before show()
|
|
144
|
+
}
|
|
145
|
+
</script>
|
|
146
|
+
|
|
147
|
+
<template>
|
|
148
|
+
<VJoyDialog ref="settingsDialog" cancel-text="Cancel" confirm-text="Save">
|
|
149
|
+
<template #dialog-header>Account settings</template>
|
|
150
|
+
<template #dialog-body>Update your preferences here.</template>
|
|
151
|
+
</VJoyDialog>
|
|
152
|
+
|
|
153
|
+
<!-- Primary button activator -->
|
|
154
|
+
<VJoyDialogTrigger :dialog="settingsDialog" @click="onTriggerClick">
|
|
155
|
+
<VJoyButton variant="main" label="Open settings" />
|
|
156
|
+
</VJoyDialogTrigger>
|
|
157
|
+
|
|
158
|
+
<!-- Multiple activators, same dialog -->
|
|
159
|
+
<VJoyDialogTrigger :dialog="settingsDialog">
|
|
160
|
+
<VJoyIconButton variant="ghost" icon="settings" label="Settings" />
|
|
161
|
+
<VJoyButton variant="secondary" label="Edit profile" />
|
|
162
|
+
</VJoyDialogTrigger>
|
|
163
|
+
</template>
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
In Nuxt (or apps with auto-import), omit the import if `VJoyDialogTrigger` is already global.
|
|
167
|
+
|
|
168
|
+
For programmatic open without a trigger component:
|
|
169
|
+
|
|
170
|
+
```vue
|
|
171
|
+
<button type="button" @click="settingsDialog?.show()">Open from code</button>
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Related
|
|
177
|
+
|
|
178
|
+
| Component | Use when |
|
|
179
|
+
| --- | --- |
|
|
180
|
+
| `VJoyDialog` | Modal content, overlay, dismiss rules, async `show()` / `hide()` |
|
|
181
|
+
| `VJoyButton` | Default labeled activator in the trigger slot |
|
|
182
|
+
| `VJoyIconButton` | Icon-only activator — pair with a meaningful `label` |
|
|
183
|
+
| `VJoyDrawerTrigger` | Same declarative pattern for `VJoyDrawer` |
|
|
184
|
+
| `VJoyBottomSheetTrigger` | Same pattern for `VJoyBottomSheet` |
|
|
185
|
+
| `VJoyTooltip` | Supplementary hint on the activator, not a modal |
|
|
186
|
+
| `VJoyDrawer` | Edge panel instead of centered modal |
|