srcdev-nuxt-components 9.2.8 → 9.2.10
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/.claude/commands/create-release-notes.md +34 -0
- package/.claude/settings.json +3 -1
- package/.claude/skills/index.md +0 -1
- package/app/assets/styles/setup/01.config/_head.css +5 -7
- package/app/components/02.molecules/expandable/expanding-panel/ExpandingPanel.vue +16 -4
- package/app/components/02.molecules/expandable/expanding-panel/tests/ExpandingPanel.spec.ts +47 -0
- package/app/components/02.molecules/pricing-card/PricingCard.vue +3 -0
- package/package.json +1 -1
- package/.claude/skills/create-release-notes.md +0 -48
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Produce release notes as a fenced markdown block, scoped to commits since the last release
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Produce release notes for the commits since the last `chore(release):` commit. Always output them as a single fenced ` ```markdown ` code block so the content can be copied directly into a git tag, GitHub release, or changelog — never render it as plain markdown.
|
|
6
|
+
|
|
7
|
+
Steps:
|
|
8
|
+
|
|
9
|
+
1. **Determine the range.** Run `git log --oneline -20` and find the most recent `chore(release): release vX.Y.Z` commit — that's the boundary. Also check `package.json` for the current version if you need to confirm what's already shipped vs pending.
|
|
10
|
+
2. **Review each commit since that boundary.** Run `git show <commit> --stat` (and the message) for each one to understand what changed. Skip other `chore(release):` commits themselves, and skip purely internal/tooling commits (e.g. adding slash commands, promoting doc gotchas) unless they're user-facing.
|
|
11
|
+
3. **Draft the notes** using the format below. Only include sections that have content — omit empty headings. Keep each bullet to one line where possible. Lead with the most user-facing changes (New, Fixed) before internal ones (Changed, Documentation). Fold minor follow-up commits (e.g. a test/docs completion commit for a feature shipped a commit earlier) into the same bullet as the feature rather than giving them their own line — unless the follow-up is substantial enough to warrant one.
|
|
12
|
+
4. **Output** the result wrapped in a ` ```markdown ` fence. Do not commit, tag, or push anything — this command only produces text for review.
|
|
13
|
+
|
|
14
|
+
## Format
|
|
15
|
+
|
|
16
|
+
```markdown
|
|
17
|
+
## vX.Y.Z
|
|
18
|
+
|
|
19
|
+
### New
|
|
20
|
+
|
|
21
|
+
- **`ComponentOrComposableName`** — one-line description of what it does and why it exists
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- Short description of what was wrong and what was corrected
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- Short description of intentional behaviour or API changes
|
|
30
|
+
|
|
31
|
+
### Documentation
|
|
32
|
+
|
|
33
|
+
- **`skill-name` skill** — new/updated: what it covers
|
|
34
|
+
```
|
package/.claude/settings.json
CHANGED
|
@@ -96,7 +96,9 @@
|
|
|
96
96
|
"Bash(git reset *)",
|
|
97
97
|
"Read(//Users/simoncornforth/.claude/**)",
|
|
98
98
|
"Bash(git push *)",
|
|
99
|
-
"Bash(node -e \"JSON.parse\\(require\\('fs'\\).readFileSync\\('.vscode/srcdev-component-pricing-card.code-snippets','utf8'\\)\\); console.log\\('valid json'\\)\")"
|
|
99
|
+
"Bash(node -e \"JSON.parse\\(require\\('fs'\\).readFileSync\\('.vscode/srcdev-component-pricing-card.code-snippets','utf8'\\)\\); console.log\\('valid json'\\)\")",
|
|
100
|
+
"Bash(rm /Users/simoncornforth/websites/nuxt-components/.claude/skills/create-release-notes.md)",
|
|
101
|
+
"Bash(node -e \"console.log\\('sanity: file exists and readable'\\)\")"
|
|
100
102
|
],
|
|
101
103
|
"additionalDirectories": [
|
|
102
104
|
"/Users/simoncornforth/websites/instepreflexology",
|
package/.claude/skills/index.md
CHANGED
|
@@ -48,7 +48,6 @@ Each skill is a single markdown file named `<area>-<task>.md`.
|
|
|
48
48
|
├── robots-env-aware.md — @nuxtjs/robots: allow crawling on prod domain only, block on preview/staging via env var
|
|
49
49
|
├── new-app-scaffold.md — scaffold a new Nuxt consumer app extending this layer (package.json, nuxt.config, app structure, CLAUDE.md)
|
|
50
50
|
├── qa-panel.md — collapsible panel for toggling component props live on a page (always on for /pages/ui/ demo pages; gate with isDev in consuming apps)
|
|
51
|
-
├── create-release-notes.md — produce release notes as a fenced markdown block from git log (named to avoid colliding with the built-in /release-notes command)
|
|
52
51
|
├── pull-request-description.md — produce a PR description as a fenced markdown block from git diff vs main
|
|
53
52
|
├── using-component-skills.md — discover and use component skills in consumer apps: where skills land, browsing patterns, workflow for deciding build vs. compose
|
|
54
53
|
├── composable-canonical-url.md — useCanonicalUrl: set <link rel="canonical"> from runtimeConfig.public.canonicalHost; layout setup, node types
|
|
@@ -24,7 +24,6 @@ html {
|
|
|
24
24
|
color: var(--colour-text-default);
|
|
25
25
|
font-family: var(--font-family);
|
|
26
26
|
font-size: var(--step-4);
|
|
27
|
-
/* min-height: 100dvh; */
|
|
28
27
|
transition:
|
|
29
28
|
background-color 0.4s ease,
|
|
30
29
|
color 0.4s ease;
|
|
@@ -33,12 +32,11 @@ html {
|
|
|
33
32
|
|
|
34
33
|
#__nuxt {
|
|
35
34
|
height: 100%;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
35
|
+
.page-layout {
|
|
36
|
+
min-block-size: 100svh;
|
|
37
|
+
display: grid;
|
|
38
|
+
grid-template-rows: auto 1fr auto;
|
|
39
|
+
align-items: start;
|
|
42
40
|
}
|
|
43
41
|
}
|
|
44
42
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="expanding-panel" :class="[elementClasses, { 'content-is-on-top': contentIsOnTop }]">
|
|
2
|
+
<div ref="rootEl" class="expanding-panel" :class="[elementClasses, { 'content-is-on-top': contentIsOnTop }]">
|
|
3
3
|
<details class="expanding-panel-details" :name :open @toggle="onDetailsToggle">
|
|
4
4
|
<summary
|
|
5
5
|
:id="`id-${name}-trigger`"
|
|
@@ -32,6 +32,8 @@
|
|
|
32
32
|
</template>
|
|
33
33
|
|
|
34
34
|
<script setup lang="ts">
|
|
35
|
+
import { onClickOutside } from "@vueuse/core";
|
|
36
|
+
|
|
35
37
|
interface Props {
|
|
36
38
|
name?: string;
|
|
37
39
|
animationDuration?: number;
|
|
@@ -56,6 +58,17 @@ const open = computed(() => props.forceOpened || isPanelOpen.value);
|
|
|
56
58
|
|
|
57
59
|
const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
|
|
58
60
|
|
|
61
|
+
// contentIsOnTop panels behave like a dropdown/overlay (e.g. ContentDocs' mobile nav) rather
|
|
62
|
+
// than an inline accordion — clicking outside is the expected way to dismiss those, matching
|
|
63
|
+
// native <select>/menu behaviour. Not wanted for ordinary accordions (forceOpened is always
|
|
64
|
+
// false here too — a forceOpened panel isn't meant to be dismissible by any interaction).
|
|
65
|
+
const rootEl = ref<HTMLElement | null>(null);
|
|
66
|
+
onClickOutside(rootEl, () => {
|
|
67
|
+
if (props.contentIsOnTop && !props.forceOpened && isPanelOpen.value) {
|
|
68
|
+
isPanelOpen.value = false;
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
59
72
|
if (import.meta.dev) {
|
|
60
73
|
watch(
|
|
61
74
|
() => props.contentIsOnTop,
|
|
@@ -97,10 +110,9 @@ const onDetailsToggle = (event: Event) => {
|
|
|
97
110
|
cursor: pointer;
|
|
98
111
|
}
|
|
99
112
|
.expanding-panel-summary {
|
|
100
|
-
display:
|
|
113
|
+
display: grid;
|
|
101
114
|
align-items: center;
|
|
102
|
-
|
|
103
|
-
flex-direction: row;
|
|
115
|
+
grid-template-columns: 1fr auto;
|
|
104
116
|
gap: var(--expanding-panel-summary-gap, 1rem);
|
|
105
117
|
list-style: none;
|
|
106
118
|
user-select: none;
|
|
@@ -427,6 +427,53 @@ describe("ExpandingPanel", () => {
|
|
|
427
427
|
expect(vm.isPanelOpen).toBe(true);
|
|
428
428
|
});
|
|
429
429
|
|
|
430
|
+
it("closes an open contentIsOnTop panel on outside click", async () => {
|
|
431
|
+
const wrapper = await mountSuspended(ExpandingPanel, {
|
|
432
|
+
props: { name: "content-on-top-outside-click", contentIsOnTop: true },
|
|
433
|
+
attachTo: document.body,
|
|
434
|
+
});
|
|
435
|
+
const vm = wrapper.vm as unknown as ExpandingPanelInstance;
|
|
436
|
+
|
|
437
|
+
await wrapper.find("summary").trigger("click");
|
|
438
|
+
expect(vm.isPanelOpen).toBe(true);
|
|
439
|
+
|
|
440
|
+
document.body.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
|
441
|
+
await nextTick();
|
|
442
|
+
|
|
443
|
+
expect(vm.isPanelOpen).toBe(false);
|
|
444
|
+
wrapper.unmount();
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
it("does not close on outside click when contentIsOnTop is false (ordinary accordion)", async () => {
|
|
448
|
+
const wrapper = await mountSuspended(ExpandingPanel, {
|
|
449
|
+
props: { name: "content-on-top-outside-click-inline" },
|
|
450
|
+
attachTo: document.body,
|
|
451
|
+
});
|
|
452
|
+
const vm = wrapper.vm as unknown as ExpandingPanelInstance;
|
|
453
|
+
|
|
454
|
+
await wrapper.find("summary").trigger("click");
|
|
455
|
+
expect(vm.isPanelOpen).toBe(true);
|
|
456
|
+
|
|
457
|
+
document.body.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
|
458
|
+
await nextTick();
|
|
459
|
+
|
|
460
|
+
expect(vm.isPanelOpen).toBe(true);
|
|
461
|
+
wrapper.unmount();
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
it("does not close a forceOpened contentIsOnTop panel on outside click", async () => {
|
|
465
|
+
const wrapper = await mountSuspended(ExpandingPanel, {
|
|
466
|
+
props: { name: "content-on-top-outside-click-forced", contentIsOnTop: true, forceOpened: true },
|
|
467
|
+
attachTo: document.body,
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
document.body.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
|
471
|
+
await nextTick();
|
|
472
|
+
|
|
473
|
+
expect(wrapper.find("details").attributes("open")).toBeDefined();
|
|
474
|
+
wrapper.unmount();
|
|
475
|
+
});
|
|
476
|
+
|
|
430
477
|
// ─── name prop / useId fallback ───────────────────────────────────────────
|
|
431
478
|
|
|
432
479
|
it("uses the provided name in ARIA attributes", async () => {
|
|
@@ -141,6 +141,9 @@ watch(
|
|
|
141
141
|
top: -0.6rem;
|
|
142
142
|
left: 50%;
|
|
143
143
|
transform: translateX(-50%);
|
|
144
|
+
/* Above .pricing-card__ribbon-clip (z-index: 1) — without this the badge has no stacking
|
|
145
|
+
context of its own and the ribbon, which does, paints over it regardless of DOM order. */
|
|
146
|
+
z-index: 2;
|
|
144
147
|
|
|
145
148
|
display: inline-block;
|
|
146
149
|
padding: 0.4rem 1rem;
|
package/package.json
CHANGED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
# Release Notes
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
When asked to create release notes, always produce a fenced markdown code block (` ```markdown `) so the content can be copied and pasted directly into a git tag, GitHub release, or changelog.
|
|
6
|
-
|
|
7
|
-
## Steps
|
|
8
|
-
|
|
9
|
-
### 1. Determine the version
|
|
10
|
-
|
|
11
|
-
Run `git log --oneline -8` to find the most recent release commit and the commits since the previous release.
|
|
12
|
-
|
|
13
|
-
### 2. Review the diff
|
|
14
|
-
|
|
15
|
-
Run `git show <commit> --stat` for each commit since the last release to understand what changed.
|
|
16
|
-
|
|
17
|
-
### 3. Produce a fenced markdown block
|
|
18
|
-
|
|
19
|
-
Always wrap the output in a ` ```markdown ` code fence — never render it as plain markdown. This ensures the user can copy the raw text without formatting being stripped.
|
|
20
|
-
|
|
21
|
-
## Format
|
|
22
|
-
|
|
23
|
-
```markdown
|
|
24
|
-
## vX.Y.Z
|
|
25
|
-
|
|
26
|
-
### New
|
|
27
|
-
|
|
28
|
-
- **`ComponentOrComposableName`** — one-line description of what it does and why it exists
|
|
29
|
-
|
|
30
|
-
### Fixed
|
|
31
|
-
|
|
32
|
-
- Short description of what was wrong and what was corrected
|
|
33
|
-
|
|
34
|
-
### Changed
|
|
35
|
-
|
|
36
|
-
- Short description of intentional behaviour or API changes
|
|
37
|
-
|
|
38
|
-
### Documentation
|
|
39
|
-
|
|
40
|
-
- **`skill-name` skill** — new/updated: what it covers
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## Notes
|
|
44
|
-
|
|
45
|
-
- Only include sections that have content — omit empty headings
|
|
46
|
-
- Keep each bullet to one line where possible
|
|
47
|
-
- Lead with the most user-facing changes (New, Fixed) before internal ones (Documentation, Tests)
|
|
48
|
-
- Test additions warrant their own section only when substantial; otherwise fold into the relevant New/Fixed bullet
|