lutra 0.1.67 → 0.1.69
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/dist/components/AspectRatio.svelte +19 -9
- package/dist/components/AspectRatio.svelte.d.ts +2 -1
- package/dist/components/Avatar.svelte +5 -8
- package/dist/components/Close.svelte +24 -27
- package/dist/components/Close.svelte.d.ts +2 -0
- package/dist/components/ContextTip.svelte +3 -2
- package/dist/components/Dialog.svelte +38 -0
- package/dist/components/Icon.svelte +3 -3
- package/dist/components/IconButton.svelte +10 -22
- package/dist/components/Image.svelte +2 -2
- package/dist/components/Indicator.svelte +2 -1
- package/dist/components/Inset.svelte +13 -0
- package/dist/components/Layout.svelte +7 -3
- package/dist/components/Layout.svelte.d.ts +3 -2
- package/dist/components/MenuDropdown.svelte +12 -2
- package/dist/components/MenuItem.svelte +30 -14
- package/dist/components/MenuItem.svelte.d.ts +6 -0
- package/dist/components/Modal.svelte +36 -20
- package/dist/components/Popover.svelte +39 -12
- package/dist/components/TabbedContent.svelte +1 -1
- package/dist/components/TabbedContentItem.svelte +14 -0
- package/dist/components/TabbedContentItem.svelte.d.ts +4 -0
- package/dist/components/Table.svelte +69 -0
- package/dist/components/Table.svelte.d.ts +7 -0
- package/dist/components/Tabs.svelte +44 -36
- package/dist/components/Tag.svelte +53 -13
- package/dist/components/Tag.svelte.d.ts +4 -0
- package/dist/components/Theme.svelte +121 -94
- package/dist/components/Theme.svelte.d.ts +7 -6
- package/dist/components/Toast.svelte +11 -8
- package/dist/components/Tooltip.svelte +17 -10
- package/dist/css/1-props.css +64 -51
- package/dist/css/2-init.css +503 -0
- package/dist/css/{2-base.css → 3-base.css} +42 -131
- package/dist/css/{3-typo.css → 4-typo.css} +3 -1
- package/dist/css/lutra.css +7 -6
- package/dist/css/themes/DefaultTheme.css +16 -4
- package/dist/form/Button.svelte +20 -0
- package/dist/form/Button.svelte.d.ts +9 -0
- package/dist/form/Datepicker.svelte +13 -0
- package/dist/form/Datepicker.svelte.d.ts +3 -0
- package/dist/form/FieldContent.svelte +18 -9
- package/dist/form/FieldError.svelte +1 -1
- package/dist/form/Fieldset.svelte +19 -11
- package/dist/form/Form.svelte +137 -63
- package/dist/form/Form.svelte.d.ts +21 -0
- package/dist/form/FormActions.svelte +21 -3
- package/dist/form/FormActions.svelte.d.ts +3 -0
- package/dist/form/FormSection.svelte +22 -20
- package/dist/form/ImageUpload.svelte +50 -30
- package/dist/form/ImageUpload.svelte.d.ts +14 -0
- package/dist/form/Input.svelte +62 -30
- package/dist/form/Input.svelte.d.ts +0 -1
- package/dist/form/InputLength.svelte +5 -5
- package/dist/form/Label.svelte +6 -6
- package/dist/form/LogoUpload.svelte +24 -10
- package/dist/form/Select.svelte +23 -10
- package/dist/form/Select.svelte.d.ts +6 -6
- package/dist/form/Textarea.svelte +11 -1
- package/dist/form/client.svelte.js +0 -2
- package/dist/state/Persisted.svelte.d.ts +6 -0
- package/dist/state/Persisted.svelte.js +29 -0
- package/dist/state/theme.svelte.d.ts +7 -0
- package/dist/state/theme.svelte.js +14 -0
- package/dist/types.d.ts +6 -23
- package/dist/types.js +0 -17
- package/dist/util/color.js +2 -2
- package/package.json +5 -4
- package/dist/config.d.ts +0 -30
- package/dist/config.js +0 -18
- /package/dist/css/{4-layout.css → 5-layout.css} +0 -0
- /package/dist/css/{5-media.css → 6-media.css} +0 -0
|
@@ -3,8 +3,24 @@
|
|
|
3
3
|
import { BROWSER } from "esm-env";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* @description
|
|
7
|
+
* A base popover component using the native Popover API and CSS Anchor Positioning.
|
|
8
|
+
* Use as a foundation for dropdowns, tooltips, contextual help, etc.
|
|
9
|
+
* Supports trigger snippets, external anchors, placement with fallbacks, and light dismiss.
|
|
10
|
+
* @cssprop --popover-background - Background color. (Default: var(--surface-background))
|
|
11
|
+
* @cssprop --popover-border - Border shorthand. (Default: var(--surface-border))
|
|
12
|
+
* @cssprop --popover-border-radius - Border radius. (Default: var(--surface-border-radius))
|
|
13
|
+
* @cssprop --popover-shadow - Box shadow. (Default: var(--surface-shadow))
|
|
14
|
+
* @cssprop --popover-width - Width of the popover. (Default: max-content)
|
|
15
|
+
* @cssprop --popover-max-width - Maximum width. (Default: calc(100vw - 2rem))
|
|
16
|
+
* @cssprop --popover-max-height - Maximum height. (Default: calc(100vh - 2rem))
|
|
17
|
+
* @example
|
|
18
|
+
* <Popover placement="bottom-start">
|
|
19
|
+
* {#snippet trigger({ toggle, triggerAttrs })}
|
|
20
|
+
* <button {...triggerAttrs}>Open</button>
|
|
21
|
+
* {/snippet}
|
|
22
|
+
* <p>Popover content</p>
|
|
23
|
+
* </Popover>
|
|
8
24
|
*/
|
|
9
25
|
let {
|
|
10
26
|
open = $bindable(false),
|
|
@@ -218,23 +234,34 @@
|
|
|
218
234
|
}
|
|
219
235
|
|
|
220
236
|
.Popover:popover-open {
|
|
221
|
-
|
|
237
|
+
opacity: 1;
|
|
238
|
+
translate: 0 0;
|
|
239
|
+
transition:
|
|
240
|
+
opacity var(--transition-duration-fast) ease-out,
|
|
241
|
+
translate var(--transition-duration-fast) ease-out,
|
|
242
|
+
display var(--transition-duration-fast) allow-discrete;
|
|
222
243
|
}
|
|
223
244
|
|
|
224
|
-
|
|
225
|
-
|
|
245
|
+
.Popover:not(:popover-open) {
|
|
246
|
+
opacity: 0;
|
|
247
|
+
translate: 0 calc(-1 * var(--space-xxs));
|
|
248
|
+
transition:
|
|
249
|
+
opacity var(--transition-duration-fast) ease-in,
|
|
250
|
+
translate var(--transition-duration-fast) ease-in,
|
|
251
|
+
display var(--transition-duration-fast) allow-discrete;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
@starting-style {
|
|
255
|
+
.Popover:popover-open {
|
|
226
256
|
opacity: 0;
|
|
227
|
-
|
|
228
|
-
}
|
|
229
|
-
to {
|
|
230
|
-
opacity: 1;
|
|
231
|
-
transform: translateY(0);
|
|
257
|
+
translate: 0 calc(-1 * var(--space-xxs));
|
|
232
258
|
}
|
|
233
259
|
}
|
|
234
260
|
|
|
235
261
|
@media (prefers-reduced-motion: reduce) {
|
|
236
|
-
.Popover:popover-open
|
|
237
|
-
|
|
262
|
+
.Popover:popover-open,
|
|
263
|
+
.Popover:not(:popover-open) {
|
|
264
|
+
transition: none;
|
|
238
265
|
}
|
|
239
266
|
}
|
|
240
267
|
</style>
|
|
@@ -1,15 +1,29 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { getContext, type Snippet } from "svelte";
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* @description
|
|
6
|
+
* A single tab panel within a TabbedContent. Registers itself with the parent TabbedContent via context.
|
|
7
|
+
* @example
|
|
8
|
+
* <TabbedContent>
|
|
9
|
+
* <TabbedContentItem label="First">
|
|
10
|
+
* <p>First tab content</p>
|
|
11
|
+
* </TabbedContentItem>
|
|
12
|
+
* </TabbedContent>
|
|
13
|
+
*/
|
|
4
14
|
let {
|
|
5
15
|
id,
|
|
6
16
|
label,
|
|
7
17
|
href,
|
|
8
18
|
children,
|
|
9
19
|
}: {
|
|
20
|
+
/** Unique identifier for this tab. Defaults to a slug of `label`. */
|
|
10
21
|
id?: string;
|
|
22
|
+
/** The label displayed in the tab bar. */
|
|
11
23
|
label: string;
|
|
24
|
+
/** Optional URL hash for this tab. */
|
|
12
25
|
href?: string;
|
|
26
|
+
/** The content of this tab panel. */
|
|
13
27
|
children: Snippet;
|
|
14
28
|
} = $props();
|
|
15
29
|
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { type Snippet } from "svelte";
|
|
2
2
|
type $$ComponentProps = {
|
|
3
|
+
/** Unique identifier for this tab. Defaults to a slug of `label`. */
|
|
3
4
|
id?: string;
|
|
5
|
+
/** The label displayed in the tab bar. */
|
|
4
6
|
label: string;
|
|
7
|
+
/** Optional URL hash for this tab. */
|
|
5
8
|
href?: string;
|
|
9
|
+
/** The content of this tab panel. */
|
|
6
10
|
children: Snippet;
|
|
7
11
|
};
|
|
8
12
|
declare const TabbedContentItem: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { getContext, type Snippet } from "svelte";
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* @description
|
|
6
|
+
* A table wrapper that provides containment, rounding, hover highlights, and zebra striping.
|
|
7
|
+
* Styling is provided by the table tokens in the CSS layer. The `contained` prop can be set via context.
|
|
8
|
+
* @example
|
|
9
|
+
* <Table contained rounded hoverable>
|
|
10
|
+
* <thead><tr><th>Name</th><th>Value</th></tr></thead>
|
|
11
|
+
* <tbody><tr><td>Alpha</td><td>1</td></tr><tr><td>Beta</td><td>2</td></tr></tbody>
|
|
12
|
+
* </Table>
|
|
13
|
+
*/
|
|
4
14
|
let {
|
|
5
15
|
colored,
|
|
6
16
|
contained,
|
|
@@ -10,12 +20,19 @@
|
|
|
10
20
|
fullWidth,
|
|
11
21
|
children,
|
|
12
22
|
}: {
|
|
23
|
+
/** Enable alternating row background colors. */
|
|
13
24
|
colored?: boolean;
|
|
25
|
+
/** Wrap the table in a border. Inherits from `lutra.table.contained` or `lutra.contained` context. */
|
|
14
26
|
contained?: boolean;
|
|
27
|
+
/** Round the corners of the container when contained. */
|
|
15
28
|
rounded?: boolean;
|
|
29
|
+
/** Apply a negative inline margin to align table borders with surrounding content. */
|
|
16
30
|
hang?: boolean;
|
|
31
|
+
/** Highlight rows on hover. */
|
|
17
32
|
hoverable?: boolean;
|
|
33
|
+
/** Force the table to full width. */
|
|
18
34
|
fullWidth?: boolean;
|
|
35
|
+
/** Table content (thead, tbody, etc.). */
|
|
19
36
|
children: Snippet;
|
|
20
37
|
} = $props();
|
|
21
38
|
|
|
@@ -39,3 +56,55 @@
|
|
|
39
56
|
{@render children()}
|
|
40
57
|
</table>
|
|
41
58
|
</div>
|
|
59
|
+
|
|
60
|
+
<style>
|
|
61
|
+
.table-container {
|
|
62
|
+
overflow: clip;
|
|
63
|
+
}
|
|
64
|
+
.table-container.contained {
|
|
65
|
+
border: var(--table-border-size) var(--table-border-style) var(--table-border-color);
|
|
66
|
+
}
|
|
67
|
+
.table-container.rounded {
|
|
68
|
+
border-radius: var(--table-border-radius);
|
|
69
|
+
}
|
|
70
|
+
.table-container.hang {
|
|
71
|
+
margin-inline: calc(-1 * var(--table-cell-padding-inline));
|
|
72
|
+
}
|
|
73
|
+
table {
|
|
74
|
+
border-collapse: collapse;
|
|
75
|
+
width: 100%;
|
|
76
|
+
}
|
|
77
|
+
:global(th),
|
|
78
|
+
:global(td) {
|
|
79
|
+
padding-block: var(--table-cell-padding-block);
|
|
80
|
+
padding-inline: var(--table-cell-padding-inline);
|
|
81
|
+
text-align: start;
|
|
82
|
+
vertical-align: top;
|
|
83
|
+
color: var(--table-cell-color);
|
|
84
|
+
}
|
|
85
|
+
.contained :global(th),
|
|
86
|
+
.contained :global(td) {
|
|
87
|
+
border: none;
|
|
88
|
+
}
|
|
89
|
+
table:not(.contained) :global(th),
|
|
90
|
+
table:not(.contained) :global(td) {
|
|
91
|
+
border: var(--table-border-size) var(--table-border-style) var(--table-border-color);
|
|
92
|
+
}
|
|
93
|
+
:global(th) {
|
|
94
|
+
background-color: var(--table-header-background);
|
|
95
|
+
color: var(--table-header-color);
|
|
96
|
+
font-weight: var(--table-header-font-weight);
|
|
97
|
+
}
|
|
98
|
+
:global(tbody tr) {
|
|
99
|
+
background-color: var(--table-row-background);
|
|
100
|
+
}
|
|
101
|
+
.colored :global(tbody tr:nth-child(even)) {
|
|
102
|
+
background-color: var(--table-row-background-even);
|
|
103
|
+
}
|
|
104
|
+
.hoverable :global(tbody tr:hover) {
|
|
105
|
+
background-color: var(--table-row-background-hover);
|
|
106
|
+
}
|
|
107
|
+
.fullWidth {
|
|
108
|
+
width: 100%;
|
|
109
|
+
}
|
|
110
|
+
</style>
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import { type Snippet } from "svelte";
|
|
2
2
|
type $$ComponentProps = {
|
|
3
|
+
/** Enable alternating row background colors. */
|
|
3
4
|
colored?: boolean;
|
|
5
|
+
/** Wrap the table in a border. Inherits from `lutra.table.contained` or `lutra.contained` context. */
|
|
4
6
|
contained?: boolean;
|
|
7
|
+
/** Round the corners of the container when contained. */
|
|
5
8
|
rounded?: boolean;
|
|
9
|
+
/** Apply a negative inline margin to align table borders with surrounding content. */
|
|
6
10
|
hang?: boolean;
|
|
11
|
+
/** Highlight rows on hover. */
|
|
7
12
|
hoverable?: boolean;
|
|
13
|
+
/** Force the table to full width. */
|
|
8
14
|
fullWidth?: boolean;
|
|
15
|
+
/** Table content (thead, tbody, etc.). */
|
|
9
16
|
children: Snippet;
|
|
10
17
|
};
|
|
11
18
|
declare const Table: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
3
|
-
import { page } from "$app/
|
|
2
|
+
import { BROWSER } from 'esm-env';
|
|
3
|
+
import { page } from "$app/state";
|
|
4
4
|
import type { TabItem } from "./MenuTypes.js";
|
|
5
5
|
import { onMount } from "svelte";
|
|
6
6
|
|
|
@@ -8,6 +8,19 @@
|
|
|
8
8
|
* @description
|
|
9
9
|
* A tabbed navigation menu used to navigate between pages or sections of content.
|
|
10
10
|
* Clicking a tab will change the URL or trigger a JavaScript event.
|
|
11
|
+
* @cssprop --tab-background-color - Background color of the tab bar. (Default: var(--menu-background-color))
|
|
12
|
+
* @cssprop --tab-background-color-hover - Background color of a tab on hover. (Default: var(--menu-background-color-hover))
|
|
13
|
+
* @cssprop --tab-background-color-active - Background color of the active tab. (Default: var(--background-selected))
|
|
14
|
+
* @cssprop --tab-text-color - Text color of tabs. (Default: var(--menu-text-color))
|
|
15
|
+
* @cssprop --tab-text-color-active - Text color of the active tab. (Default: var(--text-color-heading))
|
|
16
|
+
* @cssprop --tab-border-size - Border width. (Default: var(--menu-border-size))
|
|
17
|
+
* @cssprop --tab-border-style - Border style. (Default: var(--menu-border-style))
|
|
18
|
+
* @cssprop --tab-border-color - Border color. (Default: var(--menu-border-color))
|
|
19
|
+
* @cssprop --tab-border-radius - Border radius when rounded. (Default: var(--menu-border-radius))
|
|
20
|
+
* @cssprop --tab-gap - Gap between tabs when not contained. (Default: var(--space-md))
|
|
21
|
+
* @cssprop --tab-padding - Padding of each tab. (Default: var(--space-sm) var(--space-xs))
|
|
22
|
+
* @cssprop --tab-font-size - Font size of each tab label. (Default: var(--font-size-sm))
|
|
23
|
+
* @cssprop --tab-letter-spacing - Letter spacing of each tab label. (Default: -0.05ch)
|
|
11
24
|
* @example
|
|
12
25
|
* <Tabs contained rounded items={[
|
|
13
26
|
* {
|
|
@@ -58,21 +71,15 @@
|
|
|
58
71
|
|
|
59
72
|
let activeIndex = $derived.by(() => {
|
|
60
73
|
return items.findIndex((item, index) => {
|
|
61
|
-
console.log(item.href);
|
|
62
74
|
if(!item.href) return false;
|
|
63
|
-
// check if href ends in *
|
|
64
75
|
if(item.href.endsWith('*')) {
|
|
65
|
-
return
|
|
76
|
+
return page.url.pathname.startsWith(item.href.slice(0, -1));
|
|
66
77
|
} else {
|
|
67
|
-
return
|
|
78
|
+
return page.url.pathname.endsWith(item.href);
|
|
68
79
|
}
|
|
69
80
|
})
|
|
70
81
|
});
|
|
71
82
|
|
|
72
|
-
$effect(() => {
|
|
73
|
-
console.log(activeIndex);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
83
|
let loaded = $state(false);
|
|
77
84
|
|
|
78
85
|
onMount(async () => {
|
|
@@ -81,7 +88,7 @@
|
|
|
81
88
|
});
|
|
82
89
|
|
|
83
90
|
let underlineStyle = $derived.by(() => {
|
|
84
|
-
if(
|
|
91
|
+
if(BROWSER && underline && loaded) {
|
|
85
92
|
let active = items[activeIndex];
|
|
86
93
|
let activeElement: HTMLElement | null = document.querySelector(`#${id} li[data-index="${activeIndex}"]`);
|
|
87
94
|
if(activeElement) {
|
|
@@ -126,15 +133,14 @@
|
|
|
126
133
|
<style>
|
|
127
134
|
.Tabs {
|
|
128
135
|
display: flex;
|
|
129
|
-
|
|
130
|
-
background: var(--menu-bg);
|
|
136
|
+
background: var(--tab-background-color, var(--menu-background-color));
|
|
131
137
|
overflow: clip;
|
|
132
138
|
}
|
|
133
139
|
.Tabs.contained {
|
|
134
|
-
border: var(--menu-border);
|
|
140
|
+
border: var(--tab-border-size, var(--menu-border-size)) var(--tab-border-style, var(--menu-border-style)) var(--tab-border-color, var(--menu-border-color));
|
|
135
141
|
}
|
|
136
142
|
.Tabs.rounded {
|
|
137
|
-
border-radius: var(--border-radius);
|
|
143
|
+
border-radius: var(--tab-border-radius, var(--menu-border-radius));
|
|
138
144
|
}
|
|
139
145
|
menu, li {
|
|
140
146
|
list-style: none;
|
|
@@ -148,9 +154,9 @@
|
|
|
148
154
|
align-items: center;
|
|
149
155
|
justify-content: flex-start;
|
|
150
156
|
padding: 0;
|
|
151
|
-
gap: var(--gap,
|
|
157
|
+
gap: var(--tab-gap, var(--space-md));
|
|
152
158
|
inline-size: 100%;
|
|
153
|
-
border-block-end: var(--menu-border);
|
|
159
|
+
border-block-end: var(--tab-border-size, var(--menu-border-size)) var(--tab-border-style, var(--menu-border-style)) var(--tab-border-color, var(--menu-border-color));
|
|
154
160
|
}
|
|
155
161
|
.Tabs.contained menu {
|
|
156
162
|
gap: 0;
|
|
@@ -161,15 +167,15 @@
|
|
|
161
167
|
a,
|
|
162
168
|
button {
|
|
163
169
|
display: block;
|
|
164
|
-
padding: var(--padding,
|
|
165
|
-
color: var(--menu-text);
|
|
166
|
-
transition: all var(--
|
|
167
|
-
font-weight:
|
|
168
|
-
font-size: var(--font-size,
|
|
169
|
-
letter-spacing: -0.05ch;
|
|
170
|
+
padding: var(--tab-padding, var(--space-sm) var(--space-xs));
|
|
171
|
+
color: var(--tab-text-color, var(--menu-text-color));
|
|
172
|
+
transition: all var(--transition-duration-fast);
|
|
173
|
+
font-weight: var(--font-weight-normal);
|
|
174
|
+
font-size: var(--tab-font-size, var(--font-size-sm));
|
|
175
|
+
letter-spacing: var(--tab-letter-spacing, -0.05ch);
|
|
170
176
|
background: transparent;
|
|
171
177
|
border: none;
|
|
172
|
-
border-block-end:
|
|
178
|
+
border-block-end: var(--border-size-thick) solid transparent;
|
|
173
179
|
cursor: pointer;
|
|
174
180
|
text-decoration: none;
|
|
175
181
|
}
|
|
@@ -178,7 +184,7 @@
|
|
|
178
184
|
}
|
|
179
185
|
.Tabs.contained li {
|
|
180
186
|
flex-grow: 1;
|
|
181
|
-
border-inline-end: var(--menu-border);
|
|
187
|
+
border-inline-end: var(--tab-border-size, var(--menu-border-size)) var(--tab-border-style, var(--menu-border-style)) var(--tab-border-color, var(--menu-border-color));
|
|
182
188
|
flex-basis: auto;
|
|
183
189
|
}
|
|
184
190
|
.Tabs.contained menu li:last-of-type {
|
|
@@ -189,28 +195,30 @@
|
|
|
189
195
|
flex-grow: 1;
|
|
190
196
|
inline-size: 100%;
|
|
191
197
|
text-align: center;
|
|
192
|
-
padding-block-start: calc(
|
|
193
|
-
color: var(--menu-text);
|
|
194
|
-
font-weight:
|
|
198
|
+
padding-block-start: calc(var(--space-sm) + var(--border-size-thick));
|
|
199
|
+
color: var(--tab-text-color, var(--menu-text-color));
|
|
200
|
+
font-weight: var(--font-weight-medium);
|
|
195
201
|
}
|
|
196
202
|
a:hover,
|
|
197
|
-
button:hover
|
|
198
|
-
|
|
199
|
-
|
|
203
|
+
button:hover,
|
|
204
|
+
a:focus-visible,
|
|
205
|
+
button:focus-visible {
|
|
206
|
+
background-color: var(--tab-background-color-hover, var(--menu-background-color-hover));
|
|
207
|
+
outline: none;
|
|
200
208
|
}
|
|
201
209
|
li[aria-current="page"] a,
|
|
202
210
|
li[aria-current="page"] button {
|
|
203
|
-
background: var(--
|
|
204
|
-
color: var(--
|
|
211
|
+
background: var(--tab-background-color-active, var(--background-selected));
|
|
212
|
+
color: var(--tab-text-color-active, var(--text-color-heading));
|
|
205
213
|
opacity: 1;
|
|
206
214
|
}
|
|
207
215
|
.Underline {
|
|
208
|
-
height:
|
|
209
|
-
background-color: var(--
|
|
216
|
+
height: var(--border-size-thick);
|
|
217
|
+
background-color: var(--tab-text-color-active, var(--text-color-heading));
|
|
210
218
|
position: absolute;
|
|
211
219
|
bottom: 0;
|
|
212
220
|
left: 0;
|
|
213
|
-
transition: all
|
|
221
|
+
transition: all var(--transition-duration-fast) ease-out;
|
|
214
222
|
opacity: 0;
|
|
215
223
|
}
|
|
216
224
|
</style>
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
* A tag is a small piece of information that can be used to categorize or label an item. You can pick between `rounded`, `pill` or `rectangle` shapes. The font size and padding are relative to the parent element by default.
|
|
8
8
|
* Changing the font size without changing the padding will cause padding to be scaled with the font size. This can be changed by setting the `--padding` CSS prop.
|
|
9
9
|
* You can pass a `href` to make the tag a link, or an `onclick` function to make it a button. If you pass a `href`, you can also pass a `target` to specify the target of the link.
|
|
10
|
+
* @cssprop --prefix-padding - The padding of the prefix content. (Default: var(--space-xxs))
|
|
11
|
+
* @cssprop --suffix-padding - The padding of the suffix content. (Default: var(--space-xxs))
|
|
10
12
|
* @cssprop --font-size - The font size of the tag. (Default: 1em)
|
|
11
13
|
* @cssprop --font-weight - The font weight of the tag. (Default: 500)
|
|
12
14
|
* @cssprop --padding - The padding of the tag. (Default: 0.25em 0.5em)
|
|
@@ -26,6 +28,8 @@
|
|
|
26
28
|
href,
|
|
27
29
|
target,
|
|
28
30
|
children,
|
|
31
|
+
prefix,
|
|
32
|
+
suffix
|
|
29
33
|
}: {
|
|
30
34
|
/** Use a mono-spaced font for the tag. */
|
|
31
35
|
code?: boolean;
|
|
@@ -41,6 +45,10 @@
|
|
|
41
45
|
target?: string;
|
|
42
46
|
/** The content of the tag. */
|
|
43
47
|
children: Snippet;
|
|
48
|
+
/** Prefix content, to display before the tag. */
|
|
49
|
+
prefix?: string | Snippet;
|
|
50
|
+
/** Suffix content, to display after the tag. */
|
|
51
|
+
suffix?: string | Snippet;
|
|
44
52
|
} = $props();
|
|
45
53
|
let isSet = $derived(color ? isStatusColor(color) : true);
|
|
46
54
|
</script>
|
|
@@ -51,30 +59,61 @@
|
|
|
51
59
|
</em>
|
|
52
60
|
{/snippet}
|
|
53
61
|
|
|
62
|
+
{#snippet _prefix()}
|
|
63
|
+
{#if prefix}
|
|
64
|
+
<span class="Prefix">
|
|
65
|
+
{#if typeof prefix === 'string'}
|
|
66
|
+
{prefix}
|
|
67
|
+
{:else}
|
|
68
|
+
{@render prefix()}
|
|
69
|
+
{/if}
|
|
70
|
+
</span>
|
|
71
|
+
{/if}
|
|
72
|
+
{/snippet}
|
|
73
|
+
|
|
74
|
+
{#snippet _suffix()}
|
|
75
|
+
{#if suffix}
|
|
76
|
+
<span class="Suffix">
|
|
77
|
+
{#if typeof suffix === 'string'}
|
|
78
|
+
{suffix}
|
|
79
|
+
{:else}
|
|
80
|
+
{@render suffix()}
|
|
81
|
+
{/if}
|
|
82
|
+
</span>
|
|
83
|
+
{/if}
|
|
84
|
+
{/snippet}
|
|
85
|
+
|
|
54
86
|
{#if href}
|
|
55
87
|
<a {href} {target} class:code class="Tag Link {shape}" style="--bgColor: {!isSet ? color : 'var(--status-'+color+'-background)'}; --textColor: {!isSet ? color : 'var(--status-'+color+'-color)'};" onclick={onclick}>
|
|
88
|
+
{@render _prefix()}
|
|
56
89
|
{@render content()}
|
|
90
|
+
{@render _suffix()}
|
|
57
91
|
</a>
|
|
58
92
|
{:else if onclick}
|
|
59
93
|
<button type="button" class:code class="Tag {shape}" style="--bgColor: {!isSet ? color : 'var(--status-'+color+'-background)'}; --textColor: {!isSet ? color : 'var(--status-'+color+'-color)'};" onclick={onclick}>
|
|
94
|
+
{@render _prefix()}
|
|
60
95
|
{@render content()}
|
|
96
|
+
{@render _suffix()}
|
|
61
97
|
</button>
|
|
62
98
|
{:else}
|
|
63
99
|
<span class:code class="Tag {shape}" style="--bgColor: {!isSet ? color : 'var(--status-'+color+'-background)'}; --textColor: {!isSet ? color : 'var(--status-'+color+'-color)'};">
|
|
100
|
+
{@render _prefix()}
|
|
64
101
|
{@render content()}
|
|
102
|
+
{@render _suffix()}
|
|
65
103
|
</span>
|
|
66
104
|
{/if}
|
|
67
105
|
|
|
68
106
|
<style>
|
|
69
107
|
.Tag {
|
|
70
108
|
display: inline-flex;
|
|
109
|
+
align-items: center;
|
|
71
110
|
padding: var(--padding, 0.5em 0.5em);
|
|
72
|
-
font-weight: var(--font-weight,
|
|
111
|
+
font-weight: var(--font-weight, var(--font-weight-normal));
|
|
73
112
|
background: var(--bgColor);
|
|
74
|
-
border-radius: var(--border-radius);
|
|
113
|
+
border-radius: var(--border-radius-base);
|
|
75
114
|
font-size: var(--font-size, 0.85em);
|
|
76
115
|
vertical-align: var(--vertical-align, baseline);
|
|
77
|
-
border:
|
|
116
|
+
border: var(--border-size-thin) solid color-mix(in oklch, var(--bgColor) 95%, var(--mix-target, black) 5%);
|
|
78
117
|
}
|
|
79
118
|
.Tag.rectangle {
|
|
80
119
|
border-radius: 0;
|
|
@@ -87,26 +126,27 @@
|
|
|
87
126
|
padding: var(--padding, 0.15em 0.35em);
|
|
88
127
|
font-size: 1em;
|
|
89
128
|
line-height: 1em;
|
|
90
|
-
background: var(--
|
|
91
|
-
color: var(--textColor);
|
|
92
|
-
border: var(--border
|
|
129
|
+
background: var(--code-background);
|
|
130
|
+
color: var(--textColor, var(--code-color));
|
|
131
|
+
border: var(--code-border-size) var(--code-border-style) var(--code-border-color);
|
|
93
132
|
}
|
|
94
133
|
em {
|
|
95
134
|
font-style: normal;
|
|
96
|
-
left: 50%;
|
|
97
135
|
text-box: trim-both cap alphabetic;
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
136
|
+
}
|
|
137
|
+
.Prefix {
|
|
138
|
+
padding-inline-end: var(--prefix-padding, var(--space-xxs));
|
|
139
|
+
}
|
|
140
|
+
.Suffix {
|
|
141
|
+
padding-inline-start: var(--suffix-padding, var(--space-xxs));
|
|
101
142
|
}
|
|
102
143
|
a:hover, button:hover {
|
|
103
|
-
|
|
104
|
-
background-color: var(--bgColor2);
|
|
144
|
+
background-color: color-mix(in oklch, var(--bgColor) 87%, white 13%);
|
|
105
145
|
cursor: pointer;
|
|
106
146
|
}
|
|
107
147
|
@media (prefers-contrast: more) {
|
|
108
148
|
.Tag {
|
|
109
|
-
border:
|
|
149
|
+
border: var(--border-size-thin) solid color-mix(in oklch, var(--bgColor) 50%, var(--mix-target, black) 50%);
|
|
110
150
|
}
|
|
111
151
|
em {
|
|
112
152
|
opacity: 0.99;
|
|
@@ -15,6 +15,10 @@ type $$ComponentProps = {
|
|
|
15
15
|
target?: string;
|
|
16
16
|
/** The content of the tag. */
|
|
17
17
|
children: Snippet;
|
|
18
|
+
/** Prefix content, to display before the tag. */
|
|
19
|
+
prefix?: string | Snippet;
|
|
20
|
+
/** Suffix content, to display after the tag. */
|
|
21
|
+
suffix?: string | Snippet;
|
|
18
22
|
};
|
|
19
23
|
declare const Tag: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
20
24
|
type Tag = ReturnType<typeof Tag>;
|