@miozu/jera 0.4.3 → 0.4.5

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.
@@ -2,6 +2,7 @@
2
2
  @component Button
3
3
 
4
4
  A polymorphic button component with variants, sizes, and loading states.
5
+ Styled with transparent backgrounds and colored borders (Miozu design language).
5
6
 
6
7
  @example
7
8
  <Button>Click me</Button>
@@ -10,12 +11,8 @@
10
11
  <Button loading>Loading...</Button>
11
12
  -->
12
13
  <script>
13
- import { cn } from '../../utils/cn.svelte.js';
14
-
15
14
  let {
16
15
  children,
17
- iconLeft,
18
- iconRight,
19
16
  variant = 'primary',
20
17
  size = 'md',
21
18
  disabled = false,
@@ -29,29 +26,17 @@
29
26
  } = $props();
30
27
 
31
28
  const isLink = $derived(!!href);
32
- const isIconOnly = $derived(!children && (!!iconLeft || !!iconRight));
33
29
  const isDisabled = $derived(disabled || loading);
34
30
 
35
- const buttonClass = $derived(
36
- cn(
37
- 'btn',
38
- `btn-${variant}`,
39
- `btn-${size}`,
40
- fullWidth && 'btn-full',
41
- isIconOnly && 'btn-icon-only',
42
- className
43
- )
44
- );
45
-
46
31
  const spinnerSize = $derived({
47
- xs: 12, sm: 14, md: 16, lg: 18, xl: 20
48
- }[size]);
32
+ xs: 12, sm: 14, md: 16, lg: 18
33
+ }[size] || 16);
49
34
  </script>
50
35
 
51
36
  {#if isLink}
52
37
  <a
53
38
  {href}
54
- class={buttonClass}
39
+ class="jera-btn {variant} {size} {fullWidth ? 'full-width' : ''} {className}"
55
40
  aria-disabled={isDisabled || undefined}
56
41
  role="button"
57
42
  {...restProps}
@@ -61,20 +46,15 @@
61
46
  <circle cx="12" cy="12" r="10" opacity="0.25" />
62
47
  <path d="M12 2a10 10 0 0 1 10 10" opacity="0.75" />
63
48
  </svg>
64
- {:else if iconLeft}
65
- <span class="btn-icon">{@render iconLeft()}</span>
66
49
  {/if}
67
50
  {#if children}
68
51
  <span class={loading ? 'btn-content-loading' : ''}>{@render children()}</span>
69
52
  {/if}
70
- {#if iconRight && !loading}
71
- <span class="btn-icon">{@render iconRight()}</span>
72
- {/if}
73
53
  </a>
74
54
  {:else}
75
55
  <button
76
56
  {type}
77
- class={buttonClass}
57
+ class="jera-btn {variant} {size} {fullWidth ? 'full-width' : ''} {className}"
78
58
  disabled={isDisabled}
79
59
  aria-busy={loading || undefined}
80
60
  {onclick}
@@ -85,123 +65,194 @@
85
65
  <circle cx="12" cy="12" r="10" opacity="0.25" />
86
66
  <path d="M12 2a10 10 0 0 1 10 10" opacity="0.75" />
87
67
  </svg>
88
- {:else if iconLeft}
89
- <span class="btn-icon">{@render iconLeft()}</span>
90
68
  {/if}
91
69
  {#if children}
92
70
  <span class={loading ? 'btn-content-loading' : ''}>{@render children()}</span>
93
71
  {/if}
94
- {#if iconRight && !loading}
95
- <span class="btn-icon">{@render iconRight()}</span>
96
- {/if}
97
72
  </button>
98
73
  {/if}
99
74
 
100
75
  <style>
101
- /* Base button styles */
102
- .btn {
76
+ /* Base button styles - matches dash.selify.ai */
77
+ .jera-btn {
103
78
  display: inline-flex;
104
79
  align-items: center;
105
80
  justify-content: center;
106
- gap: 0.5rem;
81
+ gap: 0.625rem; /* gap-2.5 */
82
+ padding: 0.5rem 1rem; /* py-2 px-4 default */
83
+ font-size: 0.875rem; /* text-sm default */
107
84
  font-weight: 500;
108
- border-radius: var(--radius-lg, 0.5rem);
109
- border: 1px solid transparent;
110
85
  cursor: pointer;
111
86
  user-select: none;
112
- transition: all 150ms ease-out;
87
+ white-space: nowrap;
88
+ transition: all 200ms ease-out;
89
+ background: transparent;
90
+ border-radius: 0.25rem; /* 4px default */
113
91
  }
114
92
 
115
- .btn:focus-visible {
116
- outline: none;
117
- box-shadow: 0 0 0 2px var(--color-base00), 0 0 0 4px var(--color-base0D);
93
+ .jera-btn:focus-visible {
94
+ outline: 2px solid var(--color-base0D, #83a598);
95
+ outline-offset: 2px;
118
96
  }
119
97
 
120
- .btn:disabled {
121
- opacity: 0.5;
98
+ .jera-btn:disabled,
99
+ .jera-btn[aria-disabled='true'] {
100
+ opacity: 0.4;
122
101
  cursor: not-allowed;
123
102
  pointer-events: none;
103
+ filter: saturate(0.5);
124
104
  }
125
105
 
126
- /* Variants */
127
- .btn-primary {
128
- background-color: var(--color-base0D);
129
- color: var(--color-base07);
106
+ /* ============================================
107
+ VARIANTS - Transparent bg + colored borders
108
+ ============================================ */
109
+
110
+ /* Primary - Blue accent, main CTAs */
111
+ .primary {
112
+ background-color: color-mix(in srgb, var(--color-base0D, #83a598) 10%, transparent);
113
+ color: var(--color-base0D, #83a598);
114
+ border: 1px solid color-mix(in srgb, var(--color-base0D, #83a598) 40%, transparent);
130
115
  }
131
- .btn-primary:hover {
132
- filter: brightness(1.1);
116
+
117
+ .primary:hover:not(:disabled) {
118
+ background-color: color-mix(in srgb, var(--color-base0D, #83a598) 20%, transparent);
119
+ border-color: color-mix(in srgb, var(--color-base0D, #83a598) 60%, transparent);
133
120
  }
134
- .btn-primary:active {
135
- filter: brightness(0.95);
121
+
122
+ .primary:active:not(:disabled) {
123
+ background-color: color-mix(in srgb, var(--color-base0D, #83a598) 30%, transparent);
124
+ border-color: color-mix(in srgb, var(--color-base0D, #83a598) 80%, transparent);
125
+ transform: scale(0.98);
136
126
  }
137
127
 
138
- .btn-secondary {
139
- background-color: var(--color-base02);
140
- color: var(--color-base07);
141
- border-color: var(--color-base03);
128
+ /* Secondary - Gray background, secondary actions */
129
+ .secondary {
130
+ background-color: color-mix(in srgb, var(--color-base02, #504945) 30%, transparent);
131
+ color: var(--color-base06, #ebdbb2);
132
+ border: 1px solid var(--color-base03, #665c54);
142
133
  }
143
- .btn-secondary:hover {
144
- background-color: var(--color-base03);
134
+
135
+ .secondary:hover:not(:disabled) {
136
+ background-color: color-mix(in srgb, var(--color-base03, #665c54) 40%, transparent);
137
+ border-color: var(--color-base03, #665c54);
145
138
  }
146
139
 
147
- .btn-ghost {
140
+ .secondary:active:not(:disabled) {
141
+ background-color: color-mix(in srgb, var(--color-base03, #665c54) 50%, transparent);
142
+ border-color: var(--color-base04, #7c6f64);
143
+ transform: scale(0.98);
144
+ }
145
+
146
+ /* Outline - Transparent with visible border */
147
+ .outline {
148
148
  background-color: transparent;
149
- color: var(--color-base05);
149
+ color: var(--color-base06, #ebdbb2);
150
+ border: 1px solid var(--color-base03, #665c54);
151
+ }
152
+
153
+ .outline:hover:not(:disabled) {
154
+ background-color: color-mix(in srgb, var(--color-base03, #665c54) 20%, transparent);
155
+ border-color: var(--color-base03, #665c54);
150
156
  }
151
- .btn-ghost:hover {
152
- background-color: var(--color-base02);
157
+
158
+ .outline:active:not(:disabled) {
159
+ background-color: color-mix(in srgb, var(--color-base03, #665c54) 30%, transparent);
160
+ border-color: var(--color-base04, #7c6f64);
161
+ transform: scale(0.98);
153
162
  }
154
163
 
155
- .btn-outline {
164
+ /* Ghost - Minimal, no border */
165
+ .ghost {
156
166
  background-color: transparent;
157
- color: var(--color-base0D);
158
- border-color: color-mix(in srgb, var(--color-base0D) 40%, transparent);
167
+ color: var(--color-base05, #d5c4a1);
168
+ border: 1px solid transparent;
159
169
  }
160
- .btn-outline:hover {
161
- background-color: color-mix(in srgb, var(--color-base0D) 5%, transparent);
162
- border-color: var(--color-base0D);
170
+
171
+ .ghost:hover:not(:disabled) {
172
+ background-color: color-mix(in srgb, var(--color-base02, #504945) 30%, transparent);
173
+ color: var(--color-base06, #ebdbb2);
163
174
  }
164
175
 
165
- .btn-danger {
166
- background-color: var(--color-base08);
167
- color: var(--color-base07);
176
+ .ghost:active:not(:disabled) {
177
+ background-color: color-mix(in srgb, var(--color-base02, #504945) 40%, transparent);
178
+ color: var(--color-base06, #ebdbb2);
179
+ transform: scale(0.98);
168
180
  }
169
- .btn-danger:hover {
170
- filter: brightness(1.1);
181
+
182
+ /* Success - Green accent */
183
+ .success {
184
+ background-color: color-mix(in srgb, var(--color-base0B, #b8bb26) 10%, transparent);
185
+ color: var(--color-base0B, #b8bb26);
186
+ border: 1px solid color-mix(in srgb, var(--color-base0B, #b8bb26) 40%, transparent);
171
187
  }
172
188
 
173
- .btn-success {
174
- background-color: var(--color-base0B);
175
- color: var(--color-base07);
189
+ .success:hover:not(:disabled) {
190
+ background-color: color-mix(in srgb, var(--color-base0B, #b8bb26) 20%, transparent);
191
+ border-color: color-mix(in srgb, var(--color-base0B, #b8bb26) 60%, transparent);
176
192
  }
177
- .btn-success:hover {
178
- filter: brightness(1.1);
193
+
194
+ .success:active:not(:disabled) {
195
+ background-color: color-mix(in srgb, var(--color-base0B, #b8bb26) 30%, transparent);
196
+ border-color: color-mix(in srgb, var(--color-base0B, #b8bb26) 80%, transparent);
197
+ transform: scale(0.98);
179
198
  }
180
199
 
181
- /* Sizes */
182
- .btn-xs { height: 1.75rem; padding: 0 0.625rem; font-size: 0.75rem; }
183
- .btn-sm { height: 2rem; padding: 0 0.75rem; font-size: 0.875rem; }
184
- .btn-md { height: 2.5rem; padding: 0 1rem; font-size: 0.875rem; }
185
- .btn-lg { height: 3rem; padding: 0 1.5rem; font-size: 1rem; }
186
- .btn-xl { height: 3.5rem; padding: 0 2rem; font-size: 1.125rem; }
200
+ /* Danger - Red accent */
201
+ .danger {
202
+ background-color: color-mix(in srgb, var(--color-base08, #fb4934) 10%, transparent);
203
+ color: var(--color-base08, #fb4934);
204
+ border: 1px solid color-mix(in srgb, var(--color-base08, #fb4934) 20%, transparent);
205
+ }
187
206
 
188
- /* Modifiers */
189
- .btn-full { width: 100%; }
190
- .btn-icon-only { aspect-ratio: 1; padding: 0; }
191
- .btn-icon-only.btn-xs { width: 1.75rem; }
192
- .btn-icon-only.btn-sm { width: 2rem; }
193
- .btn-icon-only.btn-md { width: 2.5rem; }
194
- .btn-icon-only.btn-lg { width: 3rem; }
195
- .btn-icon-only.btn-xl { width: 3.5rem; }
207
+ .danger:hover:not(:disabled) {
208
+ background-color: color-mix(in srgb, var(--color-base08, #fb4934) 20%, transparent);
209
+ border-color: color-mix(in srgb, var(--color-base08, #fb4934) 40%, transparent);
210
+ }
196
211
 
197
- /* Icon and spinner */
198
- .btn-icon {
199
- display: inline-flex;
200
- flex-shrink: 0;
212
+ .danger:active:not(:disabled) {
213
+ background-color: color-mix(in srgb, var(--color-base08, #fb4934) 30%, transparent);
214
+ border-color: color-mix(in srgb, var(--color-base08, #fb4934) 60%, transparent);
215
+ transform: scale(0.98);
216
+ }
217
+
218
+ /* ============================================
219
+ SIZES - matches dash.selify.ai Button exactly
220
+ ============================================ */
221
+ .xs {
222
+ padding: 0.25rem 0.5rem; /* py-1 px-2 */
223
+ font-size: 0.75rem; /* text-xs */
224
+ border-radius: 0.125rem; /* 2px */
225
+ }
226
+
227
+ .sm {
228
+ padding: 0.375rem 0.75rem; /* py-1.5 px-3 */
229
+ font-size: 0.875rem; /* text-sm */
230
+ border-radius: 0.125rem; /* 2px */
231
+ }
232
+
233
+ .md {
234
+ padding: 0.5rem 1rem; /* py-2 px-4 */
235
+ font-size: 1rem; /* text-base */
236
+ border-radius: 0.25rem; /* 4px */
237
+ }
238
+
239
+ .lg {
240
+ padding: 0.75rem 1.25rem; /* py-3 px-5 */
241
+ font-size: 1.125rem; /* text-lg */
242
+ border-radius: 0.375rem; /* 6px */
243
+ }
244
+
245
+ /* ============================================
246
+ MODIFIERS
247
+ ============================================ */
248
+ .full-width {
249
+ width: 100%;
201
250
  }
202
251
 
252
+ /* Spinner */
203
253
  .btn-spinner {
204
254
  animation: spin 1s linear infinite;
255
+ flex-shrink: 0;
205
256
  }
206
257
 
207
258
  .btn-content-loading {
@@ -209,6 +260,8 @@
209
260
  }
210
261
 
211
262
  @keyframes spin {
212
- to { transform: rotate(360deg); }
263
+ to {
264
+ transform: rotate(360deg);
265
+ }
213
266
  }
214
267
  </style>
package/src/index.js CHANGED
@@ -116,6 +116,14 @@ export { default as NavigationCustomBlock } from './components/navigation/blocks
116
116
  // Enterprise Components
117
117
  export { default as WorkspaceMenu } from './components/navigation/WorkspaceMenu.svelte';
118
118
 
119
+ // LeftBar Components (Admin-style sidebar)
120
+ export { default as LeftBar } from './components/navigation/LeftBar.svelte';
121
+ export { default as LeftBarSection } from './components/navigation/LeftBarSection.svelte';
122
+ export { default as LeftBarItem } from './components/navigation/LeftBarItem.svelte';
123
+ export { default as LeftBarToggle } from './components/navigation/LeftBarToggle.svelte';
124
+ export { default as LeftBarPopover } from './components/navigation/LeftBarPopover.svelte';
125
+ export { default as DropdownContainer } from './components/navigation/DropdownContainer.svelte';
126
+
119
127
  // ============================================
120
128
  // COMPONENTS - Documentation
121
129
  // ============================================