@coyalabs/bts-style 1.3.10 → 1.3.12
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/README.md +193 -5
- package/dist/Base/BaseContainer.svelte +10 -2
- package/dist/Base/BasePage.svelte +1 -6
- package/dist/Base/BasePage.svelte.d.ts +0 -3
- package/dist/Base/BaseText.svelte +20 -7
- package/dist/Base/BaseText.svelte.d.ts +4 -2
- package/dist/Base/variantTypes.d.ts +3 -2
- package/dist/Base/variantTypes.js +3 -1
- package/dist/Components/Button.svelte +78 -17
- package/dist/Components/Button.svelte.d.ts +8 -0
- package/dist/Components/CodeBlock.svelte +167 -0
- package/dist/Components/CodeBlock.svelte.d.ts +40 -0
- package/dist/Components/ContextMenu.svelte +120 -31
- package/dist/Components/ContextMenu.svelte.d.ts +2 -0
- package/dist/Components/Dropdown.svelte +2 -2
- package/dist/Components/InputBox.svelte +3 -3
- package/dist/Components/LinearList.svelte +7 -2
- package/dist/Components/LoadingSpinner.svelte +58 -0
- package/dist/Components/LoadingSpinner.svelte.d.ts +30 -0
- package/dist/Components/Popup/Popup.svelte +1 -1
- package/dist/Components/ScrollContainer.svelte +95 -0
- package/dist/Components/ScrollContainer.svelte.d.ts +59 -0
- package/dist/Components/Special/SpecialAction.svelte +11 -13
- package/dist/Components/Special/SpecialAction.svelte.d.ts +2 -0
- package/dist/Components/TabBar.svelte +4 -3
- package/dist/Components/TabBar.svelte.d.ts +10 -2
- package/dist/Components/Toast/Toast.svelte +36 -11
- package/dist/Components/Toast/Toast.svelte.d.ts +6 -0
- package/dist/Components/Toggle.svelte +3 -3
- package/dist/Components/TreeDirectory.svelte +28 -10
- package/dist/Components/TreeDirectory.svelte.d.ts +36 -4
- package/dist/Structure/TextHeader.svelte +33 -4
- package/dist/Structure/TextHeader.svelte.d.ts +6 -0
- package/dist/icons.d.ts +8 -0
- package/dist/icons.js +11 -3
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -192,6 +192,9 @@ Clickable button extending BaseContainer with icon support.
|
|
|
192
192
|
- `actionIconRotation?: number` - Right icon rotation in degrees
|
|
193
193
|
- `iconSize?: string` - Left icon size (default: `'18px'`)
|
|
194
194
|
- `actionIconSize?: string` - Right icon size (default: `'18px'`)
|
|
195
|
+
- `disabled?: boolean` - Disable interaction (default: `false`)
|
|
196
|
+
- `loading?: boolean` - Show loading spinner, hide content, and disable button (default: `false`)
|
|
197
|
+
- `loadingSize?: string` - Spinner size when loading (default: `'18px'`)
|
|
195
198
|
- All BaseContainer corner radius props
|
|
196
199
|
|
|
197
200
|
**Events:**
|
|
@@ -201,6 +204,13 @@ Clickable button extending BaseContainer with icon support.
|
|
|
201
204
|
```svelte
|
|
202
205
|
<script>
|
|
203
206
|
import { Button, icons } from '@coyalabs/bts-style';
|
|
207
|
+
let isLoading = false;
|
|
208
|
+
|
|
209
|
+
async function handleClick() {
|
|
210
|
+
isLoading = true;
|
|
211
|
+
await someAsyncOperation();
|
|
212
|
+
isLoading = false;
|
|
213
|
+
}
|
|
204
214
|
</script>
|
|
205
215
|
|
|
206
216
|
<Button
|
|
@@ -216,11 +226,23 @@ Clickable button extending BaseContainer with icon support.
|
|
|
216
226
|
<Button actionIcon={null} theme="secondary">
|
|
217
227
|
Simple Button
|
|
218
228
|
</Button>
|
|
229
|
+
|
|
230
|
+
<!-- Loading state -->
|
|
231
|
+
<Button loading={isLoading} on:click={handleClick}>
|
|
232
|
+
Submit Form
|
|
233
|
+
</Button>
|
|
234
|
+
|
|
235
|
+
<!-- Disabled state -->
|
|
236
|
+
<Button disabled theme="secondary">
|
|
237
|
+
Disabled Button
|
|
238
|
+
</Button>
|
|
219
239
|
```
|
|
220
240
|
|
|
221
241
|
**States:**
|
|
222
242
|
- Hover: Subtle background lightening
|
|
223
243
|
- Active/Pressed: Visual feedback
|
|
244
|
+
- Disabled: Non-interactive, reduced opacity, `not-allowed` cursor
|
|
245
|
+
- Loading: Shows spinner, disables interaction (opacity 0.7)
|
|
224
246
|
|
|
225
247
|
---
|
|
226
248
|
|
|
@@ -255,6 +277,45 @@ Circular icon-only button with hover effects.
|
|
|
255
277
|
|
|
256
278
|
---
|
|
257
279
|
|
|
280
|
+
#### LoadingSpinner
|
|
281
|
+
|
|
282
|
+
Animated loading spinner using the light gear from the BTS theme assets. Insertable into any component (buttons, containers, inline text, etc.).
|
|
283
|
+
|
|
284
|
+
**Props:**
|
|
285
|
+
- `size?: string` - Spinner size (default: `'20px'`)
|
|
286
|
+
- `speed?: number` - Rotation speed in seconds (default: `2`)
|
|
287
|
+
- `color?: string | null` - Custom color (default: `'white'`)
|
|
288
|
+
|
|
289
|
+
**Example:**
|
|
290
|
+
```svelte
|
|
291
|
+
<script>
|
|
292
|
+
import { LoadingSpinner } from '@coyalabs/bts-style';
|
|
293
|
+
</script>
|
|
294
|
+
|
|
295
|
+
<!-- Basic usage -->
|
|
296
|
+
<LoadingSpinner />
|
|
297
|
+
|
|
298
|
+
<!-- Custom size and speed -->
|
|
299
|
+
<LoadingSpinner size="40px" speed={1.5} />
|
|
300
|
+
|
|
301
|
+
<!-- Inside a button -->
|
|
302
|
+
<Button theme="primary">
|
|
303
|
+
Loading <LoadingSpinner size="16px" />
|
|
304
|
+
</Button>
|
|
305
|
+
|
|
306
|
+
<!-- Custom color -->
|
|
307
|
+
<LoadingSpinner size="2rem" color="#FFEFF6" />
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
**Features:**
|
|
311
|
+
- Smooth infinite rotation animation
|
|
312
|
+
- Uses `inline-flex` display for easy insertion anywhere
|
|
313
|
+
- Defaults to `currentColor` to inherit parent text color
|
|
314
|
+
- Configurable rotation speed
|
|
315
|
+
- Based on the light gear asset from assetGear.js
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
258
319
|
#### InputBox
|
|
259
320
|
|
|
260
321
|
Text input field with icon support and theme matching.
|
|
@@ -282,6 +343,96 @@ Text input field with icon support and theme matching.
|
|
|
282
343
|
/>
|
|
283
344
|
```
|
|
284
345
|
|
|
346
|
+
---
|
|
347
|
+
|
|
348
|
+
#### CodeBlock
|
|
349
|
+
|
|
350
|
+
Code display component with syntax highlighting-ready styling and copy-to-clipboard functionality.
|
|
351
|
+
|
|
352
|
+
**Props:**
|
|
353
|
+
- `code: string` - Code content to display
|
|
354
|
+
- `language?: string` - Optional language label (e.g., `'javascript'`, `'python'`)
|
|
355
|
+
- `theme?: 'full' | 'primary' | 'secondary' | 'filled'` - Visual theme (default: `'secondary'`)
|
|
356
|
+
- `showCopy?: boolean` - Show copy button (default: `true`)
|
|
357
|
+
- All BaseContainer corner radius props
|
|
358
|
+
|
|
359
|
+
**Example:**
|
|
360
|
+
```svelte
|
|
361
|
+
<script>
|
|
362
|
+
import { CodeBlock } from '@coyalabs/bts-style';
|
|
363
|
+
|
|
364
|
+
const myCode = `function hello() {
|
|
365
|
+
console.log('Hello, world!');
|
|
366
|
+
}`;
|
|
367
|
+
</script>
|
|
368
|
+
|
|
369
|
+
<CodeBlock
|
|
370
|
+
code={myCode}
|
|
371
|
+
language="javascript"
|
|
372
|
+
theme="secondary"
|
|
373
|
+
/>
|
|
374
|
+
|
|
375
|
+
<!-- Without language label -->
|
|
376
|
+
<CodeBlock
|
|
377
|
+
code="npm install @coyalabs/bts-style"
|
|
378
|
+
showCopy={true}
|
|
379
|
+
/>
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
**Features:**
|
|
383
|
+
- Monospace font display (`Courier New`)
|
|
384
|
+
- Horizontal scrolling for long lines
|
|
385
|
+
- Copy button with visual feedback (check icon for 2 seconds)
|
|
386
|
+
- Optional language label in header
|
|
387
|
+
- Styled scrollbar matching theme
|
|
388
|
+
- Preserves whitespace and formatting
|
|
389
|
+
|
|
390
|
+
**Visual Design:**
|
|
391
|
+
- Code displayed in `#E3D8D8` color
|
|
392
|
+
- Language label in toned color (`#A18F8F`)
|
|
393
|
+
- Custom scrollbar with theme colors
|
|
394
|
+
- Copy button uses IconButton with toned variant
|
|
395
|
+
- Header with language and copy button (if enabled)
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
#### ScrollContainer
|
|
401
|
+
|
|
402
|
+
Reusable overflow wrapper with theme-matching custom scrollbar styling.
|
|
403
|
+
|
|
404
|
+
**Props:**
|
|
405
|
+
- `overflowX?: 'auto' | 'scroll' | 'hidden' | 'visible'` - Horizontal overflow mode (default: `'auto'`)
|
|
406
|
+
- `overflowY?: 'auto' | 'scroll' | 'hidden' | 'visible'` - Vertical overflow mode (default: `'auto'`)
|
|
407
|
+
- `width?: string` - Container width (default: `'100%'`)
|
|
408
|
+
- `height?: string` - Container height (default: `'auto'`)
|
|
409
|
+
- `maxWidth?: string` - Max width (default: `'100%'`)
|
|
410
|
+
- `maxHeight?: string` - Max height (default: `'none'`)
|
|
411
|
+
- `scrollbarSize?: string` - Scrollbar thickness/height (default: `'8px'`)
|
|
412
|
+
- `trackColor?: string` - Scrollbar track color (default: `'rgba(161, 143, 143, 0.1)'`)
|
|
413
|
+
- `thumbColor?: string` - Scrollbar thumb color (default: `'rgba(161, 143, 143, 0.3)'`)
|
|
414
|
+
- `thumbHoverColor?: string` - Scrollbar thumb hover color (default: `'rgba(161, 143, 143, 0.5)'`)
|
|
415
|
+
- `borderRadius?: string` - Scrollbar track/thumb radius (default: `'4px'`)
|
|
416
|
+
|
|
417
|
+
**Example:**
|
|
418
|
+
```svelte
|
|
419
|
+
<script>
|
|
420
|
+
import { ScrollContainer } from '@coyalabs/bts-style';
|
|
421
|
+
</script>
|
|
422
|
+
|
|
423
|
+
<ScrollContainer overflowY="auto" maxHeight="320px">
|
|
424
|
+
<div style="min-height: 640px;">
|
|
425
|
+
Scrollable content with BTS-themed scrollbar.
|
|
426
|
+
</div>
|
|
427
|
+
</ScrollContainer>
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
**Features:**
|
|
431
|
+
- Reusable themed scrollbar styles from a single component
|
|
432
|
+
- Supports both horizontal and vertical overflow use cases
|
|
433
|
+
- Works with slot content (lists, code areas, panels, etc.)
|
|
434
|
+
- Includes Firefox `scrollbar-color`/`scrollbar-width` support
|
|
435
|
+
|
|
285
436
|
|
|
286
437
|
---
|
|
287
438
|
|
|
@@ -344,13 +495,19 @@ Vertical tab navigation with support for categorized groups.
|
|
|
344
495
|
**TabItem Type:**
|
|
345
496
|
```typescript
|
|
346
497
|
type TabItem = {
|
|
347
|
-
id?: string;
|
|
348
|
-
label: string;
|
|
349
|
-
icon?: string; // Optional icon SVG
|
|
498
|
+
id?: string; // Required for tabs, omit for separators
|
|
499
|
+
label: string; // Tab/separator text
|
|
350
500
|
type?: 'tab' | 'separator'; // Default: 'tab'
|
|
501
|
+
// Icon props (spread directly onto Button):
|
|
502
|
+
icon?: string; // Icon SVG markup
|
|
503
|
+
iconRotation?: number; // Icon rotation in degrees
|
|
504
|
+
iconSize?: string; // Icon size (default: '18px')
|
|
505
|
+
iconToned?: boolean; // Use toned icon variant
|
|
351
506
|
}
|
|
352
507
|
```
|
|
353
508
|
|
|
509
|
+
Any extra properties on a tab item beyond `id`, `label`, and `type` are forwarded directly to the underlying `Button` component as props. This means all Button icon-related props (`icon`, `iconRotation`, `iconSize`, `iconToned`) can be set per-tab without needing to be individually declared.
|
|
510
|
+
|
|
354
511
|
**Example:**
|
|
355
512
|
```svelte
|
|
356
513
|
<script>
|
|
@@ -408,11 +565,12 @@ Expandable file/folder tree with recursive structure.
|
|
|
408
565
|
```typescript
|
|
409
566
|
type TreeItem = {
|
|
410
567
|
name: string;
|
|
411
|
-
type: 'file' | 'folder';
|
|
568
|
+
type: 'file' | 'folder' | 'custom';
|
|
412
569
|
children?: TreeItem[];
|
|
413
570
|
data?: any; // Custom data attached to item
|
|
414
571
|
variant?: 'full' | 'primary' | 'secondary' | 'filled' | 'special-filled'; // Theme variant
|
|
415
572
|
suffixIcon?: string; // SVG icon displayed on the right
|
|
573
|
+
isPending?: boolean; // Show pending state with reduced opacity
|
|
416
574
|
}
|
|
417
575
|
```
|
|
418
576
|
|
|
@@ -550,6 +708,24 @@ Display additional icons on the right side of items:
|
|
|
550
708
|
}
|
|
551
709
|
```
|
|
552
710
|
|
|
711
|
+
**Custom Items:**
|
|
712
|
+
Use `type: 'custom'` to render custom components via slot:
|
|
713
|
+
```svelte
|
|
714
|
+
<TreeDirectory items={[
|
|
715
|
+
{ name: 'folder', type: 'folder', children: [...] },
|
|
716
|
+
{ name: 'custom-widget', type: 'custom', data: {...} }
|
|
717
|
+
]}>
|
|
718
|
+
<svelte:fragment slot="custom" let:item let:isNested let:isLast>
|
|
719
|
+
<YourCustomComponent {item} {isNested} {isLast} />
|
|
720
|
+
</svelte:fragment>
|
|
721
|
+
</TreeDirectory>
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
**Corner Radius Behavior:**
|
|
725
|
+
- Custom items act as list terminators for corner radius calculations
|
|
726
|
+
- If the next item is of `type: 'custom'`, the current item's bottom corners will be fully rounded (25px)
|
|
727
|
+
- This creates visual separation between standard tree items and custom slot components
|
|
728
|
+
|
|
553
729
|
---
|
|
554
730
|
|
|
555
731
|
### Popup System
|
|
@@ -938,6 +1114,7 @@ A special-themed button with gradient background and optional tooltip.
|
|
|
938
1114
|
**Props:**
|
|
939
1115
|
- `label: string` - Button text
|
|
940
1116
|
- `tooltipText?: string` - Optional tooltip text displayed on the right
|
|
1117
|
+
- All Button corner radius props (`borderRadiusTopLeft`, `borderRadiusTopRight`, `borderRadiusBottomLeft`, `borderRadiusBottomRight`)
|
|
941
1118
|
|
|
942
1119
|
**Example:**
|
|
943
1120
|
```svelte
|
|
@@ -949,6 +1126,13 @@ A special-themed button with gradient background and optional tooltip.
|
|
|
949
1126
|
label="AI Generate"
|
|
950
1127
|
tooltipText="Uses AI to generate content"
|
|
951
1128
|
/>
|
|
1129
|
+
|
|
1130
|
+
<!-- With custom corners -->
|
|
1131
|
+
<SpecialAction
|
|
1132
|
+
label="AI Generate"
|
|
1133
|
+
borderRadiusTopLeft="35px"
|
|
1134
|
+
borderRadiusBottomRight="35px"
|
|
1135
|
+
/>
|
|
952
1136
|
```
|
|
953
1137
|
|
|
954
1138
|
**Features:**
|
|
@@ -1028,12 +1212,13 @@ Animated text component that reveals words sequentially with fade and blur effec
|
|
|
1028
1212
|
|
|
1029
1213
|
#### ContextMenu
|
|
1030
1214
|
|
|
1031
|
-
Categorized menu component with separator support
|
|
1215
|
+
Categorized menu component with separator support and animated scale-in from a specified corner.
|
|
1032
1216
|
|
|
1033
1217
|
**Props:**
|
|
1034
1218
|
- `items: Array<ContextMenuItem>` - Array of menu items and separators
|
|
1035
1219
|
- `selectedValue?: any` - Currently selected item value
|
|
1036
1220
|
- `onSelect?: (value: any) => void` - Callback when item is selected
|
|
1221
|
+
- `origin?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'` - Animation origin corner (default: `'top-left'`)
|
|
1037
1222
|
|
|
1038
1223
|
**ContextMenuItem Type:**
|
|
1039
1224
|
```typescript
|
|
@@ -1066,6 +1251,7 @@ type ContextMenuItem = {
|
|
|
1066
1251
|
<ContextMenu
|
|
1067
1252
|
items={menuItems}
|
|
1068
1253
|
{selectedValue}
|
|
1254
|
+
origin="bottom-right"
|
|
1069
1255
|
onSelect={(val) => handleAction(val)}
|
|
1070
1256
|
/>
|
|
1071
1257
|
```
|
|
@@ -1078,6 +1264,8 @@ type ContextMenuItem = {
|
|
|
1078
1264
|
- Filled theme container
|
|
1079
1265
|
- Automatic category spacing and borders
|
|
1080
1266
|
- Text ellipsis for long labels
|
|
1267
|
+
- Smooth scale-in animation from specified corner (350ms with backOut easing)
|
|
1268
|
+
- Scale-out animation on dismiss (200ms)
|
|
1081
1269
|
|
|
1082
1270
|
**Visual Layout:**
|
|
1083
1271
|
- Categories separated by labeled dividers
|
|
@@ -42,10 +42,10 @@
|
|
|
42
42
|
|
|
43
43
|
<style>
|
|
44
44
|
.glow-base-container {
|
|
45
|
-
width: 100%;
|
|
46
45
|
border: 2px solid rgba(255, 255, 255, 0.13);
|
|
47
46
|
padding: var(--padding);
|
|
48
47
|
box-sizing: border-box;
|
|
48
|
+
height: 100%;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
/* Theme A - Full */
|
|
@@ -79,6 +79,14 @@
|
|
|
79
79
|
inset 0px 0px 9px 2px #66588048;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
.glow-base-container[data-theme='error'] {
|
|
83
|
+
background: #331e1e;
|
|
84
|
+
border: 3px solid #563737;
|
|
85
|
+
box-shadow:
|
|
86
|
+
0px 0px 13px 0px rgba(255, 255, 255, 0.07),
|
|
87
|
+
inset 0px 0px 9px 2px #5c4b4b48;
|
|
88
|
+
}
|
|
89
|
+
|
|
82
90
|
/* Theme D - Filled */
|
|
83
91
|
.glow-base-container[data-theme='filled'] {
|
|
84
92
|
background: #161319;
|
|
@@ -87,7 +95,7 @@
|
|
|
87
95
|
inset 0px 0px 9px 2px #ffffff0a;
|
|
88
96
|
}
|
|
89
97
|
|
|
90
|
-
/* Theme
|
|
98
|
+
/* Theme F - Special Filled */
|
|
91
99
|
.glow-base-container[data-theme='special-filled'] {
|
|
92
100
|
background: linear-gradient(-78deg, #382D40 0%, #3A2B45 100%);
|
|
93
101
|
box-shadow:
|
|
@@ -12,11 +12,6 @@
|
|
|
12
12
|
*/
|
|
13
13
|
export let showBGDetails = true;
|
|
14
14
|
|
|
15
|
-
/**
|
|
16
|
-
* @type {string}
|
|
17
|
-
*/
|
|
18
|
-
export let chainColor = "#130F15";
|
|
19
|
-
|
|
20
15
|
onMount(() => {
|
|
21
16
|
// Set favicon if not already set
|
|
22
17
|
let link = document.querySelector("link[rel*='icon']") as HTMLLinkElement | null;
|
|
@@ -36,7 +31,7 @@
|
|
|
36
31
|
|
|
37
32
|
<div class="base-page">
|
|
38
33
|
{#if showBGDetails}
|
|
39
|
-
<BGDetails
|
|
34
|
+
<BGDetails />
|
|
40
35
|
{/if}
|
|
41
36
|
<div class="page-content">
|
|
42
37
|
<slot />
|
|
@@ -1,45 +1,58 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
/**
|
|
3
|
-
* @type {'title' | 'content' | 'button'}
|
|
3
|
+
* @type {'title' | 'content' | 'button' | 'code'}
|
|
4
4
|
*/
|
|
5
5
|
export let variant = 'content';
|
|
6
6
|
/**
|
|
7
7
|
* @type {string}
|
|
8
8
|
*/
|
|
9
9
|
export let textModifier = '0px';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @type {string}
|
|
13
|
+
*/
|
|
14
|
+
export let textWeightModifier = '0';
|
|
10
15
|
</script>
|
|
11
16
|
|
|
12
|
-
<span class="text" data-variant={variant} style="--text-modifier: {textModifier};">
|
|
17
|
+
<span class="text" data-variant={variant} style="--text-modifier: {textModifier}; --text-weight-modifier: {textWeightModifier};">
|
|
13
18
|
<slot />
|
|
14
19
|
</span>
|
|
15
20
|
|
|
16
21
|
<style>
|
|
17
|
-
@import url('https://fonts.googleapis.com/css2?family=Noto+Serif+KR:wght@900&display=swap');
|
|
22
|
+
@import url('https://fonts.googleapis.com/css2?family=Noto+Serif+KR:wght@200..900&display=swap');
|
|
18
23
|
@import url('https://api.fontshare.com/v2/css?f[]=satoshi@400,500,700,900&display=swap');
|
|
24
|
+
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&display=swap');
|
|
19
25
|
.text {
|
|
20
26
|
display: inline-flex;
|
|
21
27
|
align-items: center;
|
|
22
28
|
font-family: 'Satoshi', sans-serif;
|
|
29
|
+
caret-color: #544a51;
|
|
23
30
|
}
|
|
24
31
|
/* Title variant */
|
|
25
32
|
.text[data-variant='title'] {
|
|
26
33
|
font-family: 'Noto Serif KR', serif;
|
|
27
|
-
font-weight: 900;
|
|
34
|
+
font-weight: calc(900 + var(--text-weight-modifier));
|
|
28
35
|
font-size: calc(30px + var(--text-modifier));
|
|
29
36
|
color: #E3D8D8;
|
|
30
37
|
}
|
|
31
38
|
/* Content variant */
|
|
32
39
|
.text[data-variant='content'] {
|
|
33
40
|
font-family: 'Satoshi', sans-serif;
|
|
34
|
-
font-weight: 700;
|
|
41
|
+
font-weight: calc(700 + var(--text-weight-modifier));
|
|
35
42
|
font-size: calc(18px + var(--text-modifier));
|
|
36
|
-
color: #
|
|
43
|
+
color: #9e9599;
|
|
37
44
|
}
|
|
38
45
|
/* Button variant */
|
|
39
46
|
.text[data-variant='button'] {
|
|
40
47
|
font-family: 'Noto Serif KR', serif;
|
|
41
|
-
font-weight:
|
|
48
|
+
font-weight: calc(600 + var(--text-weight-modifier));
|
|
42
49
|
font-size: calc(17px + var(--text-modifier));
|
|
43
50
|
color: #E3D8D8;
|
|
44
51
|
}
|
|
52
|
+
/* Code variant */
|
|
53
|
+
.text[data-variant='code'] {
|
|
54
|
+
font-family: 'JetBrains Mono', monospace;
|
|
55
|
+
font-size: calc(14px + var(--text-modifier));
|
|
56
|
+
color: #E3D8D8;
|
|
57
|
+
}
|
|
45
58
|
</style>
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export default BaseText;
|
|
2
2
|
type BaseText = SvelteComponent<$$__sveltets_2_PropsWithChildren<{
|
|
3
|
-
variant?: "button" | "title" | "content" | undefined;
|
|
3
|
+
variant?: "button" | "code" | "title" | "content" | undefined;
|
|
4
4
|
textModifier?: string | undefined;
|
|
5
|
+
textWeightModifier?: string | undefined;
|
|
5
6
|
}, {
|
|
6
7
|
default: {};
|
|
7
8
|
}>, {
|
|
@@ -12,8 +13,9 @@ type BaseText = SvelteComponent<$$__sveltets_2_PropsWithChildren<{
|
|
|
12
13
|
$$bindings?: string | undefined;
|
|
13
14
|
};
|
|
14
15
|
declare const BaseText: $$__sveltets_2_IsomorphicComponent<$$__sveltets_2_PropsWithChildren<{
|
|
15
|
-
variant?: "button" | "title" | "content" | undefined;
|
|
16
|
+
variant?: "button" | "code" | "title" | "content" | undefined;
|
|
16
17
|
textModifier?: string | undefined;
|
|
18
|
+
textWeightModifier?: string | undefined;
|
|
17
19
|
}, {
|
|
18
20
|
default: {};
|
|
19
21
|
}>, {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @typedef {'full' | 'primary' | 'secondary' | 'filled' | 'special-filled'} BaseContainerVariant
|
|
2
|
+
* @typedef {'full' | 'primary' | 'secondary' | 'error' | 'vague' | 'filled' | 'special-filled'} BaseContainerVariant
|
|
3
3
|
*/
|
|
4
4
|
/**
|
|
5
5
|
* Default variant values as constants
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
export const VARIANT_FULL: "full";
|
|
8
8
|
export const VARIANT_PRIMARY: "primary";
|
|
9
9
|
export const VARIANT_SECONDARY: "secondary";
|
|
10
|
+
export const VARIANT_ERROR: "error";
|
|
10
11
|
export const VARIANT_VAGUE: "vague";
|
|
11
12
|
export const VARIANT_FILLED: "filled";
|
|
12
13
|
export const VARIANT_SPECIAL_FILLED: "special-filled";
|
|
13
|
-
export type BaseContainerVariant = "full" | "primary" | "secondary" | "filled" | "special-filled";
|
|
14
|
+
export type BaseContainerVariant = "full" | "primary" | "secondary" | "error" | "vague" | "filled" | "special-filled";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @typedef {'full' | 'primary' | 'secondary' | 'filled' | 'special-filled'} BaseContainerVariant
|
|
2
|
+
* @typedef {'full' | 'primary' | 'secondary' | 'error' | 'vague' | 'filled' | 'special-filled'} BaseContainerVariant
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
export const VARIANT_FULL = /** @type {const} */ ('full');
|
|
9
9
|
export const VARIANT_PRIMARY = /** @type {const} */ ('primary');
|
|
10
10
|
export const VARIANT_SECONDARY = /** @type {const} */ ('secondary');
|
|
11
|
+
export const VARIANT_ERROR = /** @type {const} */ ('error');
|
|
12
|
+
|
|
11
13
|
export const VARIANT_VAGUE = /** @type {const} */ ('vague');
|
|
12
14
|
export const VARIANT_FILLED = /** @type {const} */ ('filled');
|
|
13
15
|
export const VARIANT_SPECIAL_FILLED = /** @type {const} */ ('special-filled');
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import BaseContainer from '../Base/BaseContainer.svelte';
|
|
3
3
|
import BaseText from '../Base/BaseText.svelte';
|
|
4
4
|
import BaseIcon from '../Base/BaseIcon.svelte';
|
|
5
|
+
import LoadingSpinner from './LoadingSpinner.svelte';
|
|
5
6
|
import { icons } from '../icons';
|
|
6
7
|
import { VARIANT_FULL } from '../Base/variantTypes.js';
|
|
7
8
|
|
|
@@ -73,30 +74,59 @@
|
|
|
73
74
|
* @type {string}
|
|
74
75
|
*/
|
|
75
76
|
export let borderRadiusBottomRight = '25px';
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @type {boolean}
|
|
80
|
+
*/
|
|
81
|
+
export let loading = false;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* @type {boolean}
|
|
85
|
+
*/
|
|
86
|
+
export let disabled = false;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @type {string}
|
|
90
|
+
*/
|
|
91
|
+
export let loadingSize = '18px';
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* @type {boolean}
|
|
95
|
+
*/
|
|
96
|
+
export let hideLabel = false;
|
|
76
97
|
</script>
|
|
77
98
|
|
|
78
|
-
<button class="button-wrapper" on:click>
|
|
99
|
+
<button class="button-wrapper" on:click disabled={loading || disabled}>
|
|
79
100
|
<BaseContainer {theme} {borderRadiusTopLeft} {borderRadiusTopRight} {borderRadiusBottomLeft} {borderRadiusBottomRight}>
|
|
80
101
|
<div class="button-content">
|
|
81
|
-
|
|
82
|
-
<div class="
|
|
83
|
-
{#if icon}
|
|
84
|
-
<div class="icon-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
<
|
|
92
|
-
|
|
102
|
+
<div class="button-inner" class:loading>
|
|
103
|
+
<div class="left-content">
|
|
104
|
+
{#if icon || ($$slots.default && !hideLabel)}
|
|
105
|
+
<div class="icon-text">
|
|
106
|
+
{#if icon}
|
|
107
|
+
<div class="icon-wrapper" style="transform: rotate({iconRotation}deg)">
|
|
108
|
+
<BaseIcon variant={iconToned ? "toned" : "default"} svg={icon} size={iconSize} />
|
|
109
|
+
</div>
|
|
110
|
+
{/if}
|
|
111
|
+
{#if $$slots.default && !hideLabel}
|
|
112
|
+
<div style="transform: translateY({correctTextOffset ? '-2px' : '0px'})">
|
|
113
|
+
<BaseText variant="button">
|
|
114
|
+
<slot />
|
|
115
|
+
</BaseText>
|
|
116
|
+
</div>
|
|
117
|
+
{/if}
|
|
93
118
|
</div>
|
|
94
119
|
{/if}
|
|
95
120
|
</div>
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
121
|
+
{#if actionIcon}
|
|
122
|
+
<div class="icon-wrapper" style="transform: rotate({actionIconRotation}deg)">
|
|
123
|
+
<BaseIcon svg={actionIcon} size={actionIconSize} />
|
|
124
|
+
</div>
|
|
125
|
+
{/if}
|
|
126
|
+
</div>
|
|
127
|
+
{#if loading}
|
|
128
|
+
<div class="loading-wrapper">
|
|
129
|
+
<LoadingSpinner size={loadingSize} />
|
|
100
130
|
</div>
|
|
101
131
|
{/if}
|
|
102
132
|
</div>
|
|
@@ -109,15 +139,46 @@
|
|
|
109
139
|
cursor: pointer;
|
|
110
140
|
display: block;
|
|
111
141
|
width: 100%;
|
|
142
|
+
height: 60px;
|
|
112
143
|
user-select: none;
|
|
113
144
|
overflow: visible;
|
|
114
145
|
}
|
|
115
146
|
|
|
147
|
+
.button-wrapper:disabled {
|
|
148
|
+
opacity: 0.7;
|
|
149
|
+
pointer-events: none;
|
|
150
|
+
filter: saturate(0%);
|
|
151
|
+
}
|
|
152
|
+
|
|
116
153
|
.button-content {
|
|
154
|
+
position: relative;
|
|
155
|
+
width: 100%;
|
|
156
|
+
height: 100%;
|
|
157
|
+
display: flex;
|
|
158
|
+
align-items: center;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.button-inner {
|
|
117
162
|
display: flex;
|
|
163
|
+
width: 100%;
|
|
118
164
|
align-items: center;
|
|
119
165
|
justify-content: space-between;
|
|
120
166
|
gap: 25px;
|
|
167
|
+
transition: opacity 0.2s ease;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.button-inner.loading {
|
|
171
|
+
opacity: 0;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.loading-wrapper {
|
|
175
|
+
position: absolute;
|
|
176
|
+
top: 50%;
|
|
177
|
+
left: 50%;
|
|
178
|
+
transform: translate(-50%, -50%);
|
|
179
|
+
display: flex;
|
|
180
|
+
justify-content: center;
|
|
181
|
+
align-items: center;
|
|
121
182
|
}
|
|
122
183
|
|
|
123
184
|
.icon-text {
|
|
@@ -13,6 +13,10 @@ type Button = SvelteComponent<$$__sveltets_2_PropsWithChildren<{
|
|
|
13
13
|
iconSize?: string | undefined;
|
|
14
14
|
iconToned?: boolean | undefined;
|
|
15
15
|
actionIconSize?: string | undefined;
|
|
16
|
+
loading?: boolean | undefined;
|
|
17
|
+
disabled?: boolean | undefined;
|
|
18
|
+
loadingSize?: string | undefined;
|
|
19
|
+
hideLabel?: boolean | undefined;
|
|
16
20
|
}, {
|
|
17
21
|
default: {};
|
|
18
22
|
}>, {
|
|
@@ -38,6 +42,10 @@ declare const Button: $$__sveltets_2_IsomorphicComponent<$$__sveltets_2_PropsWit
|
|
|
38
42
|
iconSize?: string | undefined;
|
|
39
43
|
iconToned?: boolean | undefined;
|
|
40
44
|
actionIconSize?: string | undefined;
|
|
45
|
+
loading?: boolean | undefined;
|
|
46
|
+
disabled?: boolean | undefined;
|
|
47
|
+
loadingSize?: string | undefined;
|
|
48
|
+
hideLabel?: boolean | undefined;
|
|
41
49
|
}, {
|
|
42
50
|
default: {};
|
|
43
51
|
}>, {
|