@aiaiai-pt/design-system 0.1.0 → 0.2.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.
@@ -1,17 +1,22 @@
1
1
  <!--
2
2
  @component Panel
3
3
 
4
- Slide-over drawer surface. Opens from the right edge.
4
+ Slide-over drawer surface. Opens from the left or right edge.
5
5
  Consumes --panel-* tokens from components.css.
6
6
 
7
- @example
7
+ @example Right (default)
8
8
  <Panel open={showEditor} title="Edit Step" onclose={() => showEditor = false}>
9
9
  Panel content here
10
10
  </Panel>
11
11
 
12
- @example Narrow
13
- <Panel open width="narrow" title="Settings" onclose={close}>
14
- Settings form
12
+ @example Left side
13
+ <Panel open side="left" title="History" onclose={() => showHistory = false}>
14
+ Navigation content
15
+ </Panel>
16
+
17
+ @example Persistent (no backdrop, inline layout)
18
+ <Panel open persistent side="left" title="History">
19
+ Always-visible sidebar content
15
20
  </Panel>
16
21
  -->
17
22
  <script module>
@@ -21,6 +26,7 @@
21
26
  <script>
22
27
  /**
23
28
  * @typedef {'default' | 'narrow' | 'wide'} Width
29
+ * @typedef {'left' | 'right'} Side
24
30
  */
25
31
 
26
32
  let {
@@ -30,6 +36,10 @@
30
36
  title,
31
37
  /** @type {Width} */
32
38
  width = 'default',
39
+ /** @type {Side} */
40
+ side = 'right',
41
+ /** @type {boolean} When true, removes backdrop and focus trap. Panel becomes an inline layout element. */
42
+ persistent = false,
33
43
  /** @type {(() => void) | undefined} */
34
44
  onclose,
35
45
  /** @type {string} */
@@ -49,8 +59,9 @@
49
59
  const FOCUSABLE = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
50
60
 
51
61
  // Focus trap: save previous focus, trap Tab, restore on close
62
+ // Skipped in persistent mode (panel is inline, not modal)
52
63
  $effect(() => {
53
- if (!open || !panelEl) return;
64
+ if (!open || !panelEl || persistent) return;
54
65
 
55
66
  const previouslyFocused = /** @type {HTMLElement | null} */ (document.activeElement);
56
67
 
@@ -95,19 +106,21 @@
95
106
  </script>
96
107
 
97
108
  {#if open}
98
- <!-- Backdrop -->
99
- <div
100
- class="panel-backdrop"
101
- onclick={handleBackdropClick}
102
- aria-hidden="true"
103
- ></div>
109
+ <!-- Backdrop (hidden in persistent mode) -->
110
+ {#if !persistent}
111
+ <div
112
+ class="panel-backdrop"
113
+ onclick={handleBackdropClick}
114
+ aria-hidden="true"
115
+ ></div>
116
+ {/if}
104
117
 
105
118
  <!-- Panel -->
106
119
  <aside
107
120
  bind:this={panelEl}
108
- class="panel panel-{width} {className}"
109
- role="dialog"
110
- aria-modal="true"
121
+ class="panel panel-{width} panel-side-{side} {persistent ? 'panel-persistent' : ''} {className}"
122
+ role={persistent ? 'complementary' : 'dialog'}
123
+ aria-modal={persistent ? undefined : 'true'}
111
124
  aria-label={!header ? title : undefined}
112
125
  aria-labelledby={header ? headerId : undefined}
113
126
  {...rest}
@@ -118,15 +131,17 @@
118
131
  {:else if title}
119
132
  <h2 class="panel-title">{title}</h2>
120
133
  {/if}
121
- <button
122
- class="panel-close"
123
- onclick={onclose}
124
- aria-label="Close panel"
125
- >
126
- <svg viewBox="0 0 16 16" fill="none" aria-hidden="true">
127
- <path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
128
- </svg>
129
- </button>
134
+ {#if !persistent}
135
+ <button
136
+ class="panel-close"
137
+ onclick={onclose}
138
+ aria-label="Close panel"
139
+ >
140
+ <svg viewBox="0 0 16 16" fill="none" aria-hidden="true">
141
+ <path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
142
+ </svg>
143
+ </button>
144
+ {/if}
130
145
  </div>
131
146
 
132
147
  <div class="panel-body">
@@ -147,16 +162,36 @@
147
162
  .panel {
148
163
  position: fixed;
149
164
  top: 0;
150
- right: 0;
151
165
  bottom: 0;
152
166
  background: var(--panel-bg);
153
- border-left: var(--panel-border);
154
167
  box-shadow: var(--panel-shadow);
155
168
  border-radius: var(--panel-radius);
156
169
  z-index: 41;
157
170
  display: flex;
158
171
  flex-direction: column;
159
- animation: slide-in var(--panel-transition);
172
+ }
173
+
174
+ .panel-side-right {
175
+ right: 0;
176
+ border-left: var(--panel-border);
177
+ animation: slide-in-right var(--panel-transition);
178
+ }
179
+
180
+ .panel-side-left {
181
+ left: 0;
182
+ border-right: var(--panel-border);
183
+ animation: slide-in-left var(--panel-transition);
184
+ }
185
+
186
+ .panel-persistent {
187
+ position: relative;
188
+ top: auto;
189
+ bottom: auto;
190
+ z-index: auto;
191
+ box-shadow: none;
192
+ flex-shrink: 0;
193
+ height: 100%;
194
+ animation: none;
160
195
  }
161
196
 
162
197
  .panel-default {
@@ -198,8 +233,8 @@
198
233
  display: flex;
199
234
  align-items: center;
200
235
  justify-content: center;
201
- width: 28px;
202
- height: 28px;
236
+ width: var(--panel-close-size);
237
+ height: var(--panel-close-size);
203
238
  border-radius: var(--radius-sm);
204
239
  color: var(--color-text-secondary);
205
240
  transition: all var(--duration-instant) var(--easing-default);
@@ -216,8 +251,8 @@
216
251
  }
217
252
 
218
253
  .panel-close svg {
219
- width: 16px;
220
- height: 16px;
254
+ width: var(--panel-close-icon-size);
255
+ height: var(--panel-close-icon-size);
221
256
  }
222
257
 
223
258
  .panel-body {
@@ -226,7 +261,7 @@
226
261
  padding: var(--panel-padding);
227
262
  }
228
263
 
229
- @keyframes slide-in {
264
+ @keyframes slide-in-right {
230
265
  from {
231
266
  transform: translateX(100%);
232
267
  }
@@ -235,6 +270,15 @@
235
270
  }
236
271
  }
237
272
 
273
+ @keyframes slide-in-left {
274
+ from {
275
+ transform: translateX(-100%);
276
+ }
277
+ to {
278
+ transform: translateX(0);
279
+ }
280
+ }
281
+
238
282
  @keyframes fade-in {
239
283
  from {
240
284
  opacity: 0;
@@ -245,7 +289,8 @@
245
289
  }
246
290
 
247
291
  @media (prefers-reduced-motion: reduce) {
248
- .panel {
292
+ .panel-side-right,
293
+ .panel-side-left {
249
294
  animation: none;
250
295
  }
251
296
 
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@aiaiai-pt/design-system",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Design system tokens and Svelte components for aiaiai products",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "https://github.com/aiaiai-pt/aiaiai-design-system.git"
9
+ "url": "https://github.com/aiaiai-pt/sistema.git"
10
10
  },
11
11
  "publishConfig": {
12
12
  "access": "public"
@@ -279,6 +279,8 @@
279
279
  --panel-padding: var(--space-lg);
280
280
  --panel-transition: var(--duration-normal) var(--easing-enter);
281
281
  --panel-backdrop: var(--color-overlay);
282
+ --panel-close-size: 28px;
283
+ --panel-close-icon-size: 16px;
282
284
 
283
285
  /* ═══════════════════════════════════════════════
284
286
  STEPPER (wizard / multi-step flow)