@streamscloud/kit 0.9.10 → 0.9.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/dist/ui/feature-intro/cmp.feature-intro.svelte +273 -0
- package/dist/ui/feature-intro/cmp.feature-intro.svelte.d.ts +48 -0
- package/dist/ui/feature-intro/index.d.ts +2 -0
- package/dist/ui/feature-intro/index.js +1 -0
- package/dist/ui/feature-intro/types.d.ts +18 -0
- package/dist/ui/feature-intro/types.js +1 -0
- package/dist/ui/listing-card/cmp.listing-card.svelte +0 -5
- package/dist/ui/listing-card/cmp.listing-card.svelte.d.ts +1 -1
- package/dist/ui/navigation/cmp.nav-menu-header.svelte +59 -6
- package/dist/ui/navigation/cmp.nav-menu-header.svelte.d.ts +19 -2
- package/package.json +5 -1
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
<script lang="ts">import { Badge } from '../badge';
|
|
2
|
+
import { Icon, IconSlot } from '../icon';
|
|
3
|
+
import IconCheck from '@fluentui/svg-icons/icons/checkmark_12_regular.svg?raw';
|
|
4
|
+
let { eyebrow, title, description, highlights, featuresTitle, features, headingLevel = 2, media, actions } = $props();
|
|
5
|
+
const clampLevel = (level) => Math.min(Math.max(level, 1), 6);
|
|
6
|
+
const titleLevel = $derived(clampLevel(headingLevel));
|
|
7
|
+
const titleTag = $derived(`h${titleLevel}`);
|
|
8
|
+
const featuresTitleTag = $derived(`h${Math.min(titleLevel + 1, 6)}`);
|
|
9
|
+
const featureItemTag = $derived(`h${Math.min(titleLevel + 2, 6)}`);
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<section class="feature-intro">
|
|
13
|
+
<div class="feature-intro__hero">
|
|
14
|
+
<div class="feature-intro__hero-grid" class:feature-intro__hero-grid--with-media={!!media}>
|
|
15
|
+
{#if media}
|
|
16
|
+
<div class="feature-intro__media" aria-hidden="true">{@render media()}</div>
|
|
17
|
+
{/if}
|
|
18
|
+
<div class="feature-intro__body">
|
|
19
|
+
{#if eyebrow}
|
|
20
|
+
<Badge variant="accent">
|
|
21
|
+
{#if eyebrow.icon}<IconSlot icon={eyebrow.icon} size="sm" />{/if}
|
|
22
|
+
{eyebrow.label}
|
|
23
|
+
</Badge>
|
|
24
|
+
{/if}
|
|
25
|
+
<svelte:element this={titleTag} class="feature-intro__title">{title}</svelte:element>
|
|
26
|
+
{#if description}
|
|
27
|
+
<p class="feature-intro__lede">{description}</p>
|
|
28
|
+
{/if}
|
|
29
|
+
{#if actions}
|
|
30
|
+
<div class="feature-intro__actions">{@render actions()}</div>
|
|
31
|
+
{/if}
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
{#if highlights && highlights.length > 0}
|
|
36
|
+
<ul class="feature-intro__highlights">
|
|
37
|
+
{#each highlights as item, i (i)}
|
|
38
|
+
<li class="feature-intro__highlight">
|
|
39
|
+
<span class="feature-intro__highlight-check" aria-hidden="true"><Icon src={IconCheck} /></span>
|
|
40
|
+
{item}
|
|
41
|
+
</li>
|
|
42
|
+
{/each}
|
|
43
|
+
</ul>
|
|
44
|
+
{/if}
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
{#if features && features.length > 0}
|
|
48
|
+
<div class="feature-intro__features">
|
|
49
|
+
{#if featuresTitle}
|
|
50
|
+
<svelte:element this={featuresTitleTag} class="feature-intro__features-title">{featuresTitle}</svelte:element>
|
|
51
|
+
{/if}
|
|
52
|
+
<ul class="feature-intro__feature-list">
|
|
53
|
+
{#each features as feature, i (i)}
|
|
54
|
+
<li class="feature-intro__feature">
|
|
55
|
+
{#if feature.icon}
|
|
56
|
+
<div class="feature-intro__feature-icon" aria-hidden="true"><IconSlot icon={feature.icon} size="md" /></div>
|
|
57
|
+
{/if}
|
|
58
|
+
<div class="feature-intro__feature-body">
|
|
59
|
+
<svelte:element this={featureItemTag} class="feature-intro__feature-title">
|
|
60
|
+
{feature.title}
|
|
61
|
+
{#if feature.badge}<Badge variant="neutral" size="sm">{feature.badge}</Badge>{/if}
|
|
62
|
+
</svelte:element>
|
|
63
|
+
<p class="feature-intro__feature-description">{feature.description}</p>
|
|
64
|
+
</div>
|
|
65
|
+
</li>
|
|
66
|
+
{/each}
|
|
67
|
+
</ul>
|
|
68
|
+
</div>
|
|
69
|
+
{/if}
|
|
70
|
+
</section>
|
|
71
|
+
|
|
72
|
+
<!--
|
|
73
|
+
@component
|
|
74
|
+
Onboarding / feature-introduction surface for any app area — a paneled hero (eyebrow, title, lede, media + CTA snippets, optional highlights checklist) followed by an optional list of capabilities with per-row badges. All copy comes from props, so it carries no built-in strings. Renders at `100%` width; wrap in the consumer's page for background, padding and max-width.
|
|
75
|
+
|
|
76
|
+
### CSS Custom Properties
|
|
77
|
+
| Property | Description | Default |
|
|
78
|
+
|---|---|---|
|
|
79
|
+
| `--sc-kit--feature-intro--gap` | Gap between the hero and the feature list | `--sc-kit--space--12` |
|
|
80
|
+
| `--sc-kit--feature-intro--background` | Hero panel background | `--sc-kit--color--bg--panel` |
|
|
81
|
+
| `--sc-kit--feature-intro--border-color` | Hero / feature card border color | `--sc-kit--color--border` |
|
|
82
|
+
| `--sc-kit--feature-intro--radius` | Hero / feature card corner radius | `--sc-kit--radius--lg` |
|
|
83
|
+
| `--sc-kit--feature-intro--padding` | Hero panel padding | `--sc-kit--space--10` |
|
|
84
|
+
| `--sc-kit--feature-intro--hero--gap` | Gap between media and body columns | `--sc-kit--space--12` |
|
|
85
|
+
| `--sc-kit--feature-intro--media--width` | Media column width | `18.75rem` (300px) |
|
|
86
|
+
| `--sc-kit--feature-intro--media--aspect-ratio` | Media frame aspect ratio | `2 / 3` |
|
|
87
|
+
| `--sc-kit--feature-intro--media--radius` | Media frame corner radius | `--sc-kit--radius--md` |
|
|
88
|
+
| `--sc-kit--feature-intro--title--font-size` | Title font size | `--sc-kit--font-size--3xl` |
|
|
89
|
+
| `--sc-kit--feature-intro--title--color` | Title color | `--sc-kit--color--text--primary` |
|
|
90
|
+
| `--sc-kit--feature-intro--description--color` | Lede color | `--sc-kit--color--text--secondary` |
|
|
91
|
+
-->
|
|
92
|
+
|
|
93
|
+
<style>.feature-intro {
|
|
94
|
+
--_fi--gap: var(--sc-kit--feature-intro--gap, var(--sc-kit--space--12));
|
|
95
|
+
--_fi--background: var(--sc-kit--feature-intro--background, var(--sc-kit--color--bg--panel));
|
|
96
|
+
--_fi--border-color: var(--sc-kit--feature-intro--border-color, var(--sc-kit--color--border));
|
|
97
|
+
--_fi--radius: var(--sc-kit--feature-intro--radius, var(--sc-kit--radius--lg));
|
|
98
|
+
--_fi--padding: var(--sc-kit--feature-intro--padding, var(--sc-kit--space--10));
|
|
99
|
+
--_fi--hero-gap: var(--sc-kit--feature-intro--hero--gap, var(--sc-kit--space--12));
|
|
100
|
+
--_fi--media-width: var(--sc-kit--feature-intro--media--width, 18.75rem);
|
|
101
|
+
--_fi--media-aspect: var(--sc-kit--feature-intro--media--aspect-ratio, 2 / 3);
|
|
102
|
+
--_fi--media-radius: var(--sc-kit--feature-intro--media--radius, var(--sc-kit--radius--md));
|
|
103
|
+
--_fi--title-font-size: var(--sc-kit--feature-intro--title--font-size, var(--sc-kit--font-size--3xl));
|
|
104
|
+
--_fi--title-color: var(--sc-kit--feature-intro--title--color, var(--sc-kit--color--text--primary));
|
|
105
|
+
--_fi--description-color: var(--sc-kit--feature-intro--description--color, var(--sc-kit--color--text--secondary));
|
|
106
|
+
container-type: inline-size;
|
|
107
|
+
display: flex;
|
|
108
|
+
flex-direction: column;
|
|
109
|
+
gap: var(--_fi--gap);
|
|
110
|
+
width: 100%;
|
|
111
|
+
}
|
|
112
|
+
.feature-intro__hero {
|
|
113
|
+
padding: var(--_fi--padding);
|
|
114
|
+
background: var(--_fi--background);
|
|
115
|
+
border: 1px solid var(--_fi--border-color);
|
|
116
|
+
border-radius: var(--_fi--radius);
|
|
117
|
+
}
|
|
118
|
+
.feature-intro__hero-grid {
|
|
119
|
+
display: grid;
|
|
120
|
+
grid-template-columns: 1fr;
|
|
121
|
+
align-items: center;
|
|
122
|
+
gap: var(--_fi--hero-gap);
|
|
123
|
+
}
|
|
124
|
+
.feature-intro__hero-grid--with-media {
|
|
125
|
+
grid-template-columns: var(--_fi--media-width) 1fr;
|
|
126
|
+
}
|
|
127
|
+
.feature-intro__hero-grid {
|
|
128
|
+
/* Set 'container-type: inline-size;' to reference container*/
|
|
129
|
+
}
|
|
130
|
+
@container (width < 45rem) {
|
|
131
|
+
.feature-intro__hero-grid {
|
|
132
|
+
grid-template-columns: 1fr;
|
|
133
|
+
justify-items: center;
|
|
134
|
+
gap: var(--sc-kit--space--8);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
.feature-intro__media {
|
|
138
|
+
width: var(--_fi--media-width);
|
|
139
|
+
max-width: 100%;
|
|
140
|
+
aspect-ratio: var(--_fi--media-aspect);
|
|
141
|
+
overflow: hidden;
|
|
142
|
+
border-radius: var(--_fi--media-radius);
|
|
143
|
+
background: var(--sc-kit--color--bg--field-alt);
|
|
144
|
+
border: 1px solid var(--_fi--border-color);
|
|
145
|
+
}
|
|
146
|
+
.feature-intro__media :global(img),
|
|
147
|
+
.feature-intro__media :global(video) {
|
|
148
|
+
display: block;
|
|
149
|
+
width: 100%;
|
|
150
|
+
height: 100%;
|
|
151
|
+
object-fit: cover;
|
|
152
|
+
}
|
|
153
|
+
.feature-intro__body {
|
|
154
|
+
display: flex;
|
|
155
|
+
flex-direction: column;
|
|
156
|
+
align-items: flex-start;
|
|
157
|
+
gap: var(--sc-kit--space--4);
|
|
158
|
+
text-align: left;
|
|
159
|
+
min-width: 0;
|
|
160
|
+
/* Set 'container-type: inline-size;' to reference container*/
|
|
161
|
+
}
|
|
162
|
+
@container (width < 45rem) {
|
|
163
|
+
.feature-intro__body {
|
|
164
|
+
align-items: center;
|
|
165
|
+
text-align: center;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
.feature-intro__title {
|
|
169
|
+
margin: 0;
|
|
170
|
+
font-size: var(--_fi--title-font-size);
|
|
171
|
+
font-weight: var(--sc-kit--font-weight--semibold);
|
|
172
|
+
line-height: var(--sc-kit--leading--tight);
|
|
173
|
+
letter-spacing: var(--sc-kit--letter-spacing--tight);
|
|
174
|
+
color: var(--_fi--title-color);
|
|
175
|
+
}
|
|
176
|
+
.feature-intro__lede {
|
|
177
|
+
margin: 0;
|
|
178
|
+
font-size: var(--sc-kit--font-size--md);
|
|
179
|
+
line-height: var(--sc-kit--leading--relaxed);
|
|
180
|
+
color: var(--_fi--description-color);
|
|
181
|
+
}
|
|
182
|
+
.feature-intro__actions {
|
|
183
|
+
display: flex;
|
|
184
|
+
flex-wrap: wrap;
|
|
185
|
+
align-items: center;
|
|
186
|
+
gap: var(--sc-kit--space--4);
|
|
187
|
+
margin-top: var(--sc-kit--space--2);
|
|
188
|
+
}
|
|
189
|
+
.feature-intro__highlights {
|
|
190
|
+
list-style: none;
|
|
191
|
+
margin: var(--sc-kit--space--8) 0 0;
|
|
192
|
+
padding: var(--sc-kit--space--5) 0 0;
|
|
193
|
+
border-top: 1px solid var(--_fi--border-color);
|
|
194
|
+
display: flex;
|
|
195
|
+
flex-wrap: wrap;
|
|
196
|
+
justify-content: center;
|
|
197
|
+
gap: var(--sc-kit--space--2) var(--sc-kit--space--6);
|
|
198
|
+
}
|
|
199
|
+
.feature-intro__highlight {
|
|
200
|
+
display: inline-flex;
|
|
201
|
+
align-items: center;
|
|
202
|
+
gap: var(--sc-kit--space--2);
|
|
203
|
+
font-size: var(--sc-kit--font-size--sm);
|
|
204
|
+
color: var(--sc-kit--color--text--secondary);
|
|
205
|
+
}
|
|
206
|
+
.feature-intro__highlight-check {
|
|
207
|
+
flex-shrink: 0;
|
|
208
|
+
display: inline-flex;
|
|
209
|
+
align-items: center;
|
|
210
|
+
justify-content: center;
|
|
211
|
+
width: 1rem;
|
|
212
|
+
height: 1rem;
|
|
213
|
+
border-radius: var(--sc-kit--radius--circle);
|
|
214
|
+
background: var(--sc-kit--color--success--soft);
|
|
215
|
+
color: var(--sc-kit--color--success);
|
|
216
|
+
--sc-kit--icon--size: 0.75rem;
|
|
217
|
+
}
|
|
218
|
+
.feature-intro__features-title {
|
|
219
|
+
margin: 0 0 var(--sc-kit--space--4);
|
|
220
|
+
font-size: var(--sc-kit--font-size--sm);
|
|
221
|
+
font-weight: var(--sc-kit--font-weight--semibold);
|
|
222
|
+
letter-spacing: var(--sc-kit--letter-spacing--wide);
|
|
223
|
+
text-transform: uppercase;
|
|
224
|
+
color: var(--sc-kit--color--text--secondary);
|
|
225
|
+
}
|
|
226
|
+
.feature-intro__feature-list {
|
|
227
|
+
list-style: none;
|
|
228
|
+
margin: 0;
|
|
229
|
+
padding: 0;
|
|
230
|
+
display: flex;
|
|
231
|
+
flex-direction: column;
|
|
232
|
+
gap: var(--sc-kit--space--2);
|
|
233
|
+
}
|
|
234
|
+
.feature-intro__feature {
|
|
235
|
+
display: flex;
|
|
236
|
+
align-items: flex-start;
|
|
237
|
+
gap: var(--sc-kit--space--4);
|
|
238
|
+
padding: var(--sc-kit--space--5);
|
|
239
|
+
border: 1px solid var(--_fi--border-color);
|
|
240
|
+
border-radius: var(--_fi--radius);
|
|
241
|
+
background: var(--_fi--background);
|
|
242
|
+
}
|
|
243
|
+
.feature-intro__feature-icon {
|
|
244
|
+
flex-shrink: 0;
|
|
245
|
+
display: flex;
|
|
246
|
+
align-items: center;
|
|
247
|
+
justify-content: center;
|
|
248
|
+
width: 2.25rem;
|
|
249
|
+
height: 2.25rem;
|
|
250
|
+
border-radius: var(--sc-kit--radius--md);
|
|
251
|
+
background: var(--sc-kit--color--bg--field-alt);
|
|
252
|
+
color: var(--sc-kit--color--text--primary);
|
|
253
|
+
}
|
|
254
|
+
.feature-intro__feature-body {
|
|
255
|
+
flex: 1;
|
|
256
|
+
min-width: 0;
|
|
257
|
+
}
|
|
258
|
+
.feature-intro__feature-title {
|
|
259
|
+
display: flex;
|
|
260
|
+
align-items: center;
|
|
261
|
+
flex-wrap: wrap;
|
|
262
|
+
gap: var(--sc-kit--space--2);
|
|
263
|
+
margin: 0 0 var(--sc-kit--space--1);
|
|
264
|
+
font-size: var(--sc-kit--font-size--md);
|
|
265
|
+
font-weight: var(--sc-kit--font-weight--semibold);
|
|
266
|
+
color: var(--sc-kit--color--text--primary);
|
|
267
|
+
}
|
|
268
|
+
.feature-intro__feature-description {
|
|
269
|
+
margin: 0;
|
|
270
|
+
font-size: var(--sc-kit--font-size--sm);
|
|
271
|
+
line-height: var(--sc-kit--leading--normal);
|
|
272
|
+
color: var(--sc-kit--color--text--secondary);
|
|
273
|
+
}</style>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { FeatureIntroEyebrow, FeatureIntroItem } from './types';
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
type Props = {
|
|
4
|
+
/** Accent chip above the title — names the area or product (e.g. "Content Lab"). */
|
|
5
|
+
eyebrow?: FeatureIntroEyebrow;
|
|
6
|
+
/** Main heading. */
|
|
7
|
+
title: string;
|
|
8
|
+
/** Supporting paragraph beneath the title. */
|
|
9
|
+
description?: string;
|
|
10
|
+
/** Short proof points rendered as a checklist below the hero. */
|
|
11
|
+
highlights?: string[];
|
|
12
|
+
/** Label above the feature list (e.g. a localized "What's included"). Omit to hide it. */
|
|
13
|
+
featuresTitle?: string;
|
|
14
|
+
/** Capabilities to list out. Omit (or pass `[]`) to render the hero alone. */
|
|
15
|
+
features?: FeatureIntroItem[];
|
|
16
|
+
/** Heading level of the title; the features-title and feature headings nest one and two levels below it (each capped at h6). Keep to 2–4 when features are present, or the sub-headings collapse onto the same level. @default 2 */
|
|
17
|
+
headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
18
|
+
/**
|
|
19
|
+
* Hero media — an `<img>`, kit `<Image>`, video, or illustration. Fills the media frame (`object-fit: cover`).
|
|
20
|
+
* Images must carry `alt=""` — the frame is `aria-hidden` and decorative; the meaning lives in the title.
|
|
21
|
+
* Omit for a single-column hero.
|
|
22
|
+
*/
|
|
23
|
+
media?: Snippet;
|
|
24
|
+
/** Call-to-action area, typically a kit `<Button type="anchor" href={...}>`. */
|
|
25
|
+
actions?: Snippet;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Onboarding / feature-introduction surface for any app area — a paneled hero (eyebrow, title, lede, media + CTA snippets, optional highlights checklist) followed by an optional list of capabilities with per-row badges. All copy comes from props, so it carries no built-in strings. Renders at `100%` width; wrap in the consumer's page for background, padding and max-width.
|
|
29
|
+
*
|
|
30
|
+
* ### CSS Custom Properties
|
|
31
|
+
* | Property | Description | Default |
|
|
32
|
+
* |---|---|---|
|
|
33
|
+
* | `--sc-kit--feature-intro--gap` | Gap between the hero and the feature list | `--sc-kit--space--12` |
|
|
34
|
+
* | `--sc-kit--feature-intro--background` | Hero panel background | `--sc-kit--color--bg--panel` |
|
|
35
|
+
* | `--sc-kit--feature-intro--border-color` | Hero / feature card border color | `--sc-kit--color--border` |
|
|
36
|
+
* | `--sc-kit--feature-intro--radius` | Hero / feature card corner radius | `--sc-kit--radius--lg` |
|
|
37
|
+
* | `--sc-kit--feature-intro--padding` | Hero panel padding | `--sc-kit--space--10` |
|
|
38
|
+
* | `--sc-kit--feature-intro--hero--gap` | Gap between media and body columns | `--sc-kit--space--12` |
|
|
39
|
+
* | `--sc-kit--feature-intro--media--width` | Media column width | `18.75rem` (300px) |
|
|
40
|
+
* | `--sc-kit--feature-intro--media--aspect-ratio` | Media frame aspect ratio | `2 / 3` |
|
|
41
|
+
* | `--sc-kit--feature-intro--media--radius` | Media frame corner radius | `--sc-kit--radius--md` |
|
|
42
|
+
* | `--sc-kit--feature-intro--title--font-size` | Title font size | `--sc-kit--font-size--3xl` |
|
|
43
|
+
* | `--sc-kit--feature-intro--title--color` | Title color | `--sc-kit--color--text--primary` |
|
|
44
|
+
* | `--sc-kit--feature-intro--description--color` | Lede color | `--sc-kit--color--text--secondary` |
|
|
45
|
+
*/
|
|
46
|
+
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
47
|
+
type Cmp = ReturnType<typeof Cmp>;
|
|
48
|
+
export default Cmp;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as FeatureIntro } from './cmp.feature-intro.svelte';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { IconProp } from '../icon';
|
|
2
|
+
/** Eyebrow chip shown above the FeatureIntro title — names the area or product. */
|
|
3
|
+
export type FeatureIntroEyebrow = {
|
|
4
|
+
label: string;
|
|
5
|
+
/** Leading icon — string SVG source, `{ src, color?, size? }` object, or custom snippet. */
|
|
6
|
+
icon?: IconProp;
|
|
7
|
+
};
|
|
8
|
+
/** A single capability row in the FeatureIntro feature list. */
|
|
9
|
+
export type FeatureIntroItem = {
|
|
10
|
+
/** Leading icon — string SVG source, `{ src, color?, size? }` object, or custom snippet. */
|
|
11
|
+
icon?: IconProp;
|
|
12
|
+
/** Feature name. */
|
|
13
|
+
title: string;
|
|
14
|
+
/** One- to two-sentence explanation of the feature. */
|
|
15
|
+
description: string;
|
|
16
|
+
/** Optional pill rendered after the title (e.g. a localized "Coming soon"). Supply the text yourself — the kit adds no copy of its own. */
|
|
17
|
+
badge?: string;
|
|
18
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -103,11 +103,6 @@ card a click target without nesting `<button>` elements with the action snippet.
|
|
|
103
103
|
overflow: hidden;
|
|
104
104
|
pointer-events: none;
|
|
105
105
|
}
|
|
106
|
-
.listing-card__preview :global(img),
|
|
107
|
-
.listing-card__preview :global(svg) {
|
|
108
|
-
max-width: 100%;
|
|
109
|
-
max-height: 100%;
|
|
110
|
-
}
|
|
111
106
|
.listing-card__body {
|
|
112
107
|
position: relative;
|
|
113
108
|
z-index: 1;
|
|
@@ -8,7 +8,7 @@ type Props = {
|
|
|
8
8
|
label: string;
|
|
9
9
|
tone?: StatusTone;
|
|
10
10
|
};
|
|
11
|
-
/** Top preview area — image, illustration, screenshot, gradient. Omit to skip the preview. */
|
|
11
|
+
/** Top preview area — image, illustration, screenshot, gradient. Consumer sizes its own content (e.g. `width:100%`). Omit to skip the preview. */
|
|
12
12
|
preview?: Snippet;
|
|
13
13
|
/** Action slot, typically a kit `<Button size="sm" variant="outline">`. */
|
|
14
14
|
action?: Snippet;
|
|
@@ -1,17 +1,70 @@
|
|
|
1
|
-
<script lang="ts">const { label } = $props();
|
|
1
|
+
<script lang="ts">const { label, fontFamily = 'mono', tone = 'primary', divider = false } = $props();
|
|
2
|
+
export {};
|
|
2
3
|
</script>
|
|
3
4
|
|
|
4
|
-
<div
|
|
5
|
+
<div
|
|
6
|
+
class="nav-menu-header"
|
|
7
|
+
class:nav-menu-header--mono={fontFamily === 'mono'}
|
|
8
|
+
class:nav-menu-header--sans={fontFamily === 'sans'}
|
|
9
|
+
class:nav-menu-header--display={fontFamily === 'display'}
|
|
10
|
+
class:nav-menu-header--primary={tone === 'primary'}
|
|
11
|
+
class:nav-menu-header--secondary={tone === 'secondary'}
|
|
12
|
+
class:nav-menu-header--divided={divider}>
|
|
13
|
+
{label}
|
|
14
|
+
</div>
|
|
5
15
|
|
|
6
16
|
<!--
|
|
7
17
|
@component
|
|
8
|
-
NavMenuHeader — group label rendered above a stack of `NavMenuItem`s.
|
|
9
|
-
`
|
|
18
|
+
NavMenuHeader — group label rendered above a stack of `NavMenuItem`s. Monospace 400 by default;
|
|
19
|
+
non-mono families default to weight 500. `tone` switches the text between primary and secondary.
|
|
20
|
+
Use one per `NavMenuGroup`. Pass `divider` to draw a bottom separator (same style as
|
|
21
|
+
`NavMenuDivider`), so the header itself groups the items below it without a standalone divider and
|
|
22
|
+
wider spacing.
|
|
23
|
+
|
|
24
|
+
### CSS Custom Properties
|
|
25
|
+
| Property | Description | Default |
|
|
26
|
+
|---|---|---|
|
|
27
|
+
| `--sc-kit--nav-menu-header--font-family` | Label font family | `var(--sc-kit--font--mono)` |
|
|
28
|
+
| `--sc-kit--nav-menu-header--font-weight` | Label font weight | `400` (mono) / `500` (other families) |
|
|
29
|
+
| `--sc-kit--nav-menu-header--color` | Label text color | `var(--sc-kit--color--text--primary)` (tone-dependent) |
|
|
10
30
|
-->
|
|
11
31
|
<style>.nav-menu-header {
|
|
32
|
+
--_nav-menu-header--font-family: var(--sc-kit--nav-menu-header--font-family, var(--_nav-menu-header--font-family-default, var(--sc-kit--font--mono)));
|
|
33
|
+
--_nav-menu-header--font-weight: var(
|
|
34
|
+
--sc-kit--nav-menu-header--font-weight,
|
|
35
|
+
var(--_nav-menu-header--font-weight-default, var(--sc-kit--font-weight--regular))
|
|
36
|
+
);
|
|
37
|
+
--_nav-menu-header--color: var(--sc-kit--nav-menu-header--color, var(--_nav-menu-header--color-default, var(--sc-kit--color--text--primary)));
|
|
12
38
|
padding: var(--sc-kit--space--2) var(--sc-kit--space--5);
|
|
39
|
+
font-family: var(--_nav-menu-header--font-family), sans-serif;
|
|
13
40
|
font-size: var(--sc-kit--font-size--md);
|
|
14
|
-
font-weight: var(--
|
|
41
|
+
font-weight: var(--_nav-menu-header--font-weight);
|
|
15
42
|
line-height: var(--sc-kit--leading--tight);
|
|
16
|
-
color: var(--
|
|
43
|
+
color: var(--_nav-menu-header--color);
|
|
44
|
+
}
|
|
45
|
+
.nav-menu-header--mono {
|
|
46
|
+
--_nav-menu-header--font-family-default: var(--sc-kit--font--mono);
|
|
47
|
+
--_nav-menu-header--font-weight-default: var(--sc-kit--font-weight--regular);
|
|
48
|
+
}
|
|
49
|
+
.nav-menu-header--sans {
|
|
50
|
+
--_nav-menu-header--font-family-default: var(--sc-kit--font--sans);
|
|
51
|
+
--_nav-menu-header--font-weight-default: var(--sc-kit--font-weight--medium);
|
|
52
|
+
}
|
|
53
|
+
.nav-menu-header--display {
|
|
54
|
+
--_nav-menu-header--font-family-default: var(--sc-kit--font--display);
|
|
55
|
+
--_nav-menu-header--font-weight-default: var(--sc-kit--font-weight--medium);
|
|
56
|
+
}
|
|
57
|
+
.nav-menu-header--primary {
|
|
58
|
+
--_nav-menu-header--color-default: var(--sc-kit--color--text--primary);
|
|
59
|
+
}
|
|
60
|
+
.nav-menu-header--secondary {
|
|
61
|
+
--_nav-menu-header--color-default: var(--sc-kit--color--text--secondary);
|
|
62
|
+
}
|
|
63
|
+
.nav-menu-header--divided::after {
|
|
64
|
+
content: "";
|
|
65
|
+
display: block;
|
|
66
|
+
height: 1px;
|
|
67
|
+
margin-block-start: var(--sc-kit--space--2);
|
|
68
|
+
margin-inline: calc(var(--sc-kit--space--4) - var(--sc-kit--space--5));
|
|
69
|
+
background: var(--sc-kit--color--border);
|
|
17
70
|
}</style>
|
|
@@ -1,9 +1,26 @@
|
|
|
1
|
+
import type { KitFontFamily } from '../../fonts';
|
|
1
2
|
type Props = {
|
|
2
3
|
label: string;
|
|
4
|
+
/** Label font family; each family carries its own default weight (mono → 400, others → 500). Overridable via `--sc-kit--nav-menu-header--font-family`. @default 'mono' */
|
|
5
|
+
fontFamily?: KitFontFamily;
|
|
6
|
+
/** Text tone. Overridable via `--sc-kit--nav-menu-header--color`. @default 'primary' */
|
|
7
|
+
tone?: 'primary' | 'secondary';
|
|
8
|
+
/** Draw a bottom separator (same style as `NavMenuDivider`) under the label. @default false */
|
|
9
|
+
divider?: boolean;
|
|
3
10
|
};
|
|
4
11
|
/**
|
|
5
|
-
* NavMenuHeader — group label rendered above a stack of `NavMenuItem`s.
|
|
6
|
-
* `
|
|
12
|
+
* NavMenuHeader — group label rendered above a stack of `NavMenuItem`s. Monospace 400 by default;
|
|
13
|
+
* non-mono families default to weight 500. `tone` switches the text between primary and secondary.
|
|
14
|
+
* Use one per `NavMenuGroup`. Pass `divider` to draw a bottom separator (same style as
|
|
15
|
+
* `NavMenuDivider`), so the header itself groups the items below it without a standalone divider and
|
|
16
|
+
* wider spacing.
|
|
17
|
+
*
|
|
18
|
+
* ### CSS Custom Properties
|
|
19
|
+
* | Property | Description | Default |
|
|
20
|
+
* |---|---|---|
|
|
21
|
+
* | `--sc-kit--nav-menu-header--font-family` | Label font family | `var(--sc-kit--font--mono)` |
|
|
22
|
+
* | `--sc-kit--nav-menu-header--font-weight` | Label font weight | `400` (mono) / `500` (other families) |
|
|
23
|
+
* | `--sc-kit--nav-menu-header--color` | Label text color | `var(--sc-kit--color--text--primary)` (tone-dependent) |
|
|
7
24
|
*/
|
|
8
25
|
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
9
26
|
type Cmp = ReturnType<typeof Cmp>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@streamscloud/kit",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.12",
|
|
4
4
|
"author": "StreamsCloud",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -175,6 +175,10 @@
|
|
|
175
175
|
"types": "./dist/ui/empty-state/index.d.ts",
|
|
176
176
|
"svelte": "./dist/ui/empty-state/index.js"
|
|
177
177
|
},
|
|
178
|
+
"./ui/feature-intro": {
|
|
179
|
+
"types": "./dist/ui/feature-intro/index.d.ts",
|
|
180
|
+
"svelte": "./dist/ui/feature-intro/index.js"
|
|
181
|
+
},
|
|
178
182
|
"./ui/file-uploader": {
|
|
179
183
|
"types": "./dist/ui/file-uploader/index.d.ts",
|
|
180
184
|
"svelte": "./dist/ui/file-uploader/index.js"
|