picocrank 1.22.1 → 1.22.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "picocrank",
3
- "version": "1.22.1",
3
+ "version": "1.22.2",
4
4
  "description": "A set of zero dependency Vue components built on the Femtocrank global CSS theme.",
5
5
  "main": "vite.config.js",
6
6
  "scripts": {
@@ -21,14 +21,14 @@
21
21
  "@hugeicons/core-free-icons": "^4.2.3",
22
22
  "@hugeicons/vue": "^1.0.7",
23
23
  "@vitejs/plugin-vue": "^6.0.8",
24
- "femtocrank": "^2.5.1",
24
+ "femtocrank": "^2.5.2",
25
25
  "unplugin-vue-components": "^32.1.0",
26
- "vite": "^8.2.0",
27
- "vue": "^3.5.40",
26
+ "vite": "^8.2.1",
27
+ "vue": "^3.5.41",
28
28
  "vue-router": "^5.2.0"
29
29
  },
30
30
  "devDependencies": {
31
- "semantic-release": "^25.0.8"
31
+ "semantic-release": "^25.0.9"
32
32
  },
33
33
  "homepage": "https://github.com/jamesread/picocrank#readme"
34
34
  }
package/router.js CHANGED
@@ -14,6 +14,7 @@ import { LayoutGridIcon } from '@hugeicons/core-free-icons';
14
14
  import { StatusIcon } from '@hugeicons/core-free-icons';
15
15
  import { PaintBoardIcon } from '@hugeicons/core-free-icons';
16
16
  import { UserIcon } from '@hugeicons/core-free-icons';
17
+ import { InformationCircleIcon } from '@hugeicons/core-free-icons';
17
18
 
18
19
  const routes = [
19
20
  {
@@ -136,6 +137,15 @@ const routes = [
136
137
  icon: StatusIcon,
137
138
  }
138
139
  },
140
+ {
141
+ name: 'DialogExample',
142
+ path: '/dialog-example',
143
+ component: () => import('./vue/views/DialogExample.vue'),
144
+ meta: {
145
+ title: 'Dialog',
146
+ icon: InformationCircleIcon,
147
+ }
148
+ },
139
149
  {
140
150
  name: 'TabsExample',
141
151
  path: '/tabs-example',
package/vue/views/App.vue CHANGED
@@ -198,6 +198,7 @@
198
198
 
199
199
  navigation.value.addSection('Feedback & status', { name: 'nav-feedback' })
200
200
  navigation.value.addRouterLink('StatusExample', 'Status & notifications')
201
+ navigation.value.addRouterLink('DialogExample', 'Dialog')
201
202
 
202
203
  navigation.value.addSection('Patterns', { name: 'nav-patterns' })
203
204
  navigation.value.addCallback('Callback example', helloWorld, { icon: Pin02Icon })
@@ -0,0 +1,123 @@
1
+ <template>
2
+ <Section
3
+ title="Dialog"
4
+ subtitle="Native HTML dialog element with showModal()"
5
+ >
6
+ <p>
7
+ The <code>&lt;dialog&gt;</code> element provides accessible modal and
8
+ non-modal overlays without a third-party library. Femtocrank styles the
9
+ element globally; use <code>showModal()</code> for a modal with backdrop,
10
+ or <code>show()</code> for a non-modal panel.
11
+ </p>
12
+ </Section>
13
+
14
+ <Section title="Modal dialog" subtitle="Opens with showModal() and closes on backdrop click">
15
+ <div role="toolbar" class="dialog-actions">
16
+ <button type="button" @click="openModal">Open modal</button>
17
+ </div>
18
+
19
+ <dialog
20
+ ref="modalRef"
21
+ class="example-dialog"
22
+ @close="onModalClose"
23
+ @click="onBackdropClick($event, modalRef)"
24
+ >
25
+ <div class="dialog-panel" @click.stop>
26
+ <h3>Confirm action</h3>
27
+ <p>
28
+ This modal uses the native dialog API. Press Escape or click outside
29
+ to dismiss, or choose an action below.
30
+ </p>
31
+ <form method="dialog" class="dialog-form">
32
+ <div role="toolbar" class="dialog-actions">
33
+ <button type="submit" value="cancel" class="neutral">Cancel</button>
34
+ <button type="submit" value="confirm" class="good">Confirm</button>
35
+ </div>
36
+ </form>
37
+ </div>
38
+ </dialog>
39
+
40
+ <p v-if="modalResult" class="subtle">{{ modalResult }}</p>
41
+ </Section>
42
+
43
+ <Section title="Non-modal dialog" subtitle="Stays open while the page remains interactive">
44
+ <div role="toolbar" class="dialog-actions">
45
+ <button type="button" class="neutral" @click="openPanel">Open panel</button>
46
+ <button type="button" class="bad" :disabled="!panelRef?.open" @click="closePanel">
47
+ Close panel
48
+ </button>
49
+ </div>
50
+
51
+ <dialog ref="panelRef" class="example-dialog example-dialog-panel">
52
+ <div class="dialog-panel">
53
+ <h3>Side note</h3>
54
+ <p>
55
+ Non-modal dialogs use <code>show()</code> instead of
56
+ <code>showModal()</code>. They do not trap focus or dim the page.
57
+ </p>
58
+ <button type="button" class="neutral" @click="closePanel">Dismiss</button>
59
+ </div>
60
+ </dialog>
61
+ </Section>
62
+ </template>
63
+
64
+ <script setup>
65
+ import { ref } from 'vue'
66
+ import Section from '../components/Section.vue'
67
+
68
+ const modalRef = ref(null)
69
+ const panelRef = ref(null)
70
+ const modalResult = ref('')
71
+
72
+ function openModal() {
73
+ modalRef.value?.showModal()
74
+ }
75
+
76
+ function onModalClose(event) {
77
+ const value = event.target?.returnValue
78
+ if (value === 'confirm') {
79
+ modalResult.value = 'Action confirmed.'
80
+ } else {
81
+ modalResult.value = 'Dialog closed without confirming.'
82
+ }
83
+ }
84
+
85
+ function onBackdropClick(event, dialog) {
86
+ if (event.target === dialog) {
87
+ dialog.close('cancel')
88
+ }
89
+ }
90
+
91
+ function openPanel() {
92
+ panelRef.value?.show()
93
+ }
94
+
95
+ function closePanel() {
96
+ panelRef.value?.close()
97
+ }
98
+ </script>
99
+
100
+ <style scoped>
101
+ .dialog-actions {
102
+ display: flex;
103
+ flex-wrap: wrap;
104
+ gap: 0.5rem;
105
+ }
106
+
107
+ .dialog-panel h3 {
108
+ margin: 0 0 0.5rem;
109
+ }
110
+
111
+ .dialog-panel p {
112
+ margin: 0 0 1rem;
113
+ }
114
+
115
+ .dialog-form {
116
+ margin: 0;
117
+ }
118
+
119
+ .example-dialog-panel {
120
+ margin-block-start: 1rem;
121
+ max-width: 24rem;
122
+ }
123
+ </style>