@reshape-biotech/design-system 2.7.39 → 2.7.41
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/nav/Nav.stories.svelte +351 -0
- package/dist/components/nav/Nav.stories.svelte.d.ts +27 -0
- package/dist/components/nav/Nav.svelte +143 -0
- package/dist/components/nav/Nav.svelte.d.ts +30 -0
- package/dist/components/nav/NavItem.svelte +166 -0
- package/dist/components/nav/NavItem.svelte.d.ts +14 -0
- package/dist/components/nav/NavItemGroup.svelte +13 -0
- package/dist/components/nav/NavItemGroup.svelte.d.ts +7 -0
- package/dist/components/nav/index.d.ts +3 -0
- package/dist/components/nav/index.js +3 -0
- package/dist/components/notifications/Notifications.svelte +3 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
<script module>
|
|
2
|
+
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
3
|
+
import { Bell, UserCircle, Question, Plus, DotsThree, MagnifyingGlass, House, CirclesFour, Folder, Cube, BookOpen } from 'phosphor-svelte';
|
|
4
|
+
import { Icon } from '../icons/index.js';
|
|
5
|
+
import AnalysisIcon from '../icons/AnalysisIcon.svelte';
|
|
6
|
+
import Button from '../button/Button.svelte';
|
|
7
|
+
import { Tag } from '../tag/index.js';
|
|
8
|
+
import { IconButton } from '../icon-button/index.js';
|
|
9
|
+
import Nav from './Nav.svelte';
|
|
10
|
+
|
|
11
|
+
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
|
|
12
|
+
const { Story } = defineMeta({
|
|
13
|
+
title: 'Components/Nav',
|
|
14
|
+
parameters: {
|
|
15
|
+
layout: 'fullscreen',
|
|
16
|
+
},
|
|
17
|
+
component: Nav,
|
|
18
|
+
tags: ['autodocs'],
|
|
19
|
+
});
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<Story name="Basic" asChild>
|
|
23
|
+
<div class="flex items-center justify-center bg-base p-8">
|
|
24
|
+
<div class="flex h-[600px] w-full max-w-5xl overflow-hidden rounded-lg shadow-menu">
|
|
25
|
+
<Nav company="My App">
|
|
26
|
+
{#snippet main({ collapsed, NavItem })}
|
|
27
|
+
<NavItem {collapsed}>
|
|
28
|
+
{#snippet icon()}
|
|
29
|
+
<Icon icon={House} />
|
|
30
|
+
{/snippet}
|
|
31
|
+
Home
|
|
32
|
+
</NavItem>
|
|
33
|
+
<NavItem {collapsed} active>
|
|
34
|
+
{#snippet icon()}
|
|
35
|
+
<Icon icon={Folder} />
|
|
36
|
+
{/snippet}
|
|
37
|
+
Projects
|
|
38
|
+
</NavItem>
|
|
39
|
+
<NavItem {collapsed}>
|
|
40
|
+
{#snippet icon()}
|
|
41
|
+
<Icon icon={BookOpen} />
|
|
42
|
+
{/snippet}
|
|
43
|
+
Library
|
|
44
|
+
</NavItem>
|
|
45
|
+
{/snippet}
|
|
46
|
+
</Nav>
|
|
47
|
+
<main class="flex-1 overflow-y-auto bg-surface p-6">
|
|
48
|
+
<div class="space-y-4">
|
|
49
|
+
<h3 class="font-semibold">Basic sidebar</h3>
|
|
50
|
+
<p class="text-secondary">
|
|
51
|
+
A simple sidebar with just the essentials.
|
|
52
|
+
</p>
|
|
53
|
+
</div>
|
|
54
|
+
</main>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
</Story>
|
|
58
|
+
|
|
59
|
+
<Story name="Discovery sidebar" asChild>
|
|
60
|
+
<div class="flex items-center justify-center bg-base p-8">
|
|
61
|
+
<div class="flex h-[600px] w-full max-w-5xl overflow-hidden rounded-lg shadow-menu">
|
|
62
|
+
<Nav company="Reshape Gigalab">
|
|
63
|
+
{#snippet workspaceMenu({ Dropdown })}
|
|
64
|
+
<Dropdown.Item>
|
|
65
|
+
<span>Workspace settings</span>
|
|
66
|
+
</Dropdown.Item>
|
|
67
|
+
<Dropdown.Item>
|
|
68
|
+
<span>Manage profile</span>
|
|
69
|
+
</Dropdown.Item>
|
|
70
|
+
<Dropdown.Separator />
|
|
71
|
+
<Dropdown.Item>
|
|
72
|
+
<span>Log out</span>
|
|
73
|
+
</Dropdown.Item>
|
|
74
|
+
{/snippet}
|
|
75
|
+
{#snippet top({ collapsed, NavItem })}
|
|
76
|
+
<Button variant="primary" class="w-full">
|
|
77
|
+
{#snippet children()}
|
|
78
|
+
<div class="flex items-center gap-2">
|
|
79
|
+
<Icon icon={Plus} />
|
|
80
|
+
{#if !collapsed}
|
|
81
|
+
<span>Create new</span>
|
|
82
|
+
{/if}
|
|
83
|
+
</div>
|
|
84
|
+
{/snippet}
|
|
85
|
+
</Button>
|
|
86
|
+
{/snippet}
|
|
87
|
+
{#snippet main({ collapsed, NavItem })}
|
|
88
|
+
<NavItem {collapsed}>
|
|
89
|
+
{#snippet icon()}
|
|
90
|
+
<Icon icon={House} />
|
|
91
|
+
{/snippet}
|
|
92
|
+
Home
|
|
93
|
+
</NavItem>
|
|
94
|
+
<NavItem {collapsed}>
|
|
95
|
+
{#snippet icon()}
|
|
96
|
+
<Icon icon={CirclesFour} />
|
|
97
|
+
{/snippet}
|
|
98
|
+
Jobs
|
|
99
|
+
</NavItem>
|
|
100
|
+
<NavItem {collapsed}>
|
|
101
|
+
{#snippet icon()}
|
|
102
|
+
<Icon icon={Folder} />
|
|
103
|
+
{/snippet}
|
|
104
|
+
Projects
|
|
105
|
+
</NavItem>
|
|
106
|
+
<NavItem active {collapsed}>
|
|
107
|
+
{#snippet icon()}
|
|
108
|
+
<Icon icon={Cube} />
|
|
109
|
+
{/snippet}
|
|
110
|
+
Devices
|
|
111
|
+
</NavItem>
|
|
112
|
+
<NavItem {collapsed}>
|
|
113
|
+
{#snippet icon()}
|
|
114
|
+
<Icon icon={BookOpen} />
|
|
115
|
+
{/snippet}
|
|
116
|
+
Library
|
|
117
|
+
</NavItem>
|
|
118
|
+
{/snippet}
|
|
119
|
+
{#snippet footer({ collapsed, NavItem })}
|
|
120
|
+
<NavItem {collapsed}>
|
|
121
|
+
{#snippet icon()}
|
|
122
|
+
<Icon icon={Question} />
|
|
123
|
+
{/snippet}
|
|
124
|
+
Help & support
|
|
125
|
+
</NavItem>
|
|
126
|
+
{/snippet}
|
|
127
|
+
</Nav>
|
|
128
|
+
<main class="flex-1 overflow-y-auto bg-surface p-6">
|
|
129
|
+
<div class="space-y-4">
|
|
130
|
+
<h3 class="font-semibold">Discovery sidebar</h3>
|
|
131
|
+
<p class="text-secondary">
|
|
132
|
+
This is an example of how the navigation sidebar is used in Discovery platform.
|
|
133
|
+
</p>
|
|
134
|
+
</div>
|
|
135
|
+
</main>
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
</Story>
|
|
139
|
+
|
|
140
|
+
<Story name="Quality sidebar" asChild>
|
|
141
|
+
<div class="flex items-center justify-center bg-base p-8">
|
|
142
|
+
<div class="flex h-[600px] w-full max-w-5xl overflow-hidden rounded-lg shadow-menu">
|
|
143
|
+
<Nav company="Reshape Gigalab">
|
|
144
|
+
{#snippet top({ collapsed, NavItem })}
|
|
145
|
+
<NavItem {collapsed}>
|
|
146
|
+
{#snippet icon()}
|
|
147
|
+
<Icon icon={MagnifyingGlass} color="secondary" />
|
|
148
|
+
{/snippet}
|
|
149
|
+
Search
|
|
150
|
+
</NavItem>
|
|
151
|
+
<NavItem {collapsed}>
|
|
152
|
+
{#snippet icon()}
|
|
153
|
+
<Icon icon={Bell} color="secondary" />
|
|
154
|
+
{/snippet}
|
|
155
|
+
Notifications
|
|
156
|
+
</NavItem>
|
|
157
|
+
{/snippet}
|
|
158
|
+
{#snippet main({ collapsed, NavItem, NavItemGroup })}
|
|
159
|
+
<NavItemGroup name="Analyses" {collapsed} />
|
|
160
|
+
<NavItem {collapsed}>
|
|
161
|
+
{#snippet icon()}
|
|
162
|
+
<AnalysisIcon model="pipeline_small_colonies" />
|
|
163
|
+
{/snippet}
|
|
164
|
+
Enterobacteriaceae
|
|
165
|
+
{#snippet rightSlot()}
|
|
166
|
+
<IconButton
|
|
167
|
+
variant="transparent"
|
|
168
|
+
size="xs"
|
|
169
|
+
rounded={false}
|
|
170
|
+
>
|
|
171
|
+
<Icon icon={DotsThree} color="secondary" />
|
|
172
|
+
</IconButton>
|
|
173
|
+
{/snippet}
|
|
174
|
+
</NavItem>
|
|
175
|
+
<NavItem {collapsed} active>
|
|
176
|
+
{#snippet icon()}
|
|
177
|
+
<AnalysisIcon model="pipeline_halos" />
|
|
178
|
+
{/snippet}
|
|
179
|
+
Halo
|
|
180
|
+
{#snippet rightSlot()}
|
|
181
|
+
<Tag variant="success" size="xs">Active</Tag>
|
|
182
|
+
{/snippet}
|
|
183
|
+
</NavItem>
|
|
184
|
+
<NavItem {collapsed}>
|
|
185
|
+
{#snippet icon()}
|
|
186
|
+
<AnalysisIcon model="pipeline_large_colonies" />
|
|
187
|
+
{/snippet}
|
|
188
|
+
Large colonies
|
|
189
|
+
{#snippet rightSlot()}
|
|
190
|
+
<IconButton
|
|
191
|
+
variant="transparent"
|
|
192
|
+
size="xs"
|
|
193
|
+
rounded={false}
|
|
194
|
+
>
|
|
195
|
+
<Icon icon={DotsThree} color="secondary" />
|
|
196
|
+
</IconButton>
|
|
197
|
+
{/snippet}
|
|
198
|
+
</NavItem>
|
|
199
|
+
{/snippet}
|
|
200
|
+
{#snippet footer({ collapsed, NavItem })}
|
|
201
|
+
<NavItem {collapsed}>
|
|
202
|
+
{#snippet icon()}
|
|
203
|
+
<Icon icon={UserCircle} />
|
|
204
|
+
{/snippet}
|
|
205
|
+
Profile
|
|
206
|
+
</NavItem>
|
|
207
|
+
<NavItem {collapsed}>
|
|
208
|
+
{#snippet icon()}
|
|
209
|
+
<Icon icon={Question} />
|
|
210
|
+
{/snippet}
|
|
211
|
+
Help
|
|
212
|
+
</NavItem>
|
|
213
|
+
{/snippet}
|
|
214
|
+
</Nav>
|
|
215
|
+
<main class="flex-1 overflow-y-auto bg-surface p-6">
|
|
216
|
+
<div class="space-y-4">
|
|
217
|
+
<h3 class="font-semibold">Quality sidebar</h3>
|
|
218
|
+
<p class="text-secondary">
|
|
219
|
+
This is an example of how the navigation sidebar is used in the Quality platform.
|
|
220
|
+
</p>
|
|
221
|
+
</div>
|
|
222
|
+
</main>
|
|
223
|
+
</div>
|
|
224
|
+
</div>
|
|
225
|
+
</Story>
|
|
226
|
+
|
|
227
|
+
<Story name="Quality sidebar - Many analyses" asChild>
|
|
228
|
+
<div class="flex items-center justify-center bg-base p-8">
|
|
229
|
+
<div class="flex h-[600px] w-full max-w-5xl overflow-hidden rounded-lg shadow-menu">
|
|
230
|
+
<Nav company="Reshape Gigalab">
|
|
231
|
+
{#snippet top({ collapsed, NavItem })}
|
|
232
|
+
<NavItem {collapsed}>
|
|
233
|
+
{#snippet icon()}
|
|
234
|
+
<Icon icon={MagnifyingGlass} color="secondary" />
|
|
235
|
+
{/snippet}
|
|
236
|
+
Search
|
|
237
|
+
</NavItem>
|
|
238
|
+
<NavItem {collapsed}>
|
|
239
|
+
{#snippet icon()}
|
|
240
|
+
<Icon icon={Bell} color="secondary" />
|
|
241
|
+
{/snippet}
|
|
242
|
+
Notifications
|
|
243
|
+
</NavItem>
|
|
244
|
+
{/snippet}
|
|
245
|
+
{#snippet main({ collapsed, NavItem, NavItemGroup })}
|
|
246
|
+
<NavItemGroup name="Analyses" {collapsed} />
|
|
247
|
+
<NavItem {collapsed}>
|
|
248
|
+
{#snippet icon()}
|
|
249
|
+
<AnalysisIcon model="pipeline_small_colonies" />
|
|
250
|
+
{/snippet}
|
|
251
|
+
Enterobacteriaceae
|
|
252
|
+
</NavItem>
|
|
253
|
+
<NavItem {collapsed} active>
|
|
254
|
+
{#snippet icon()}
|
|
255
|
+
<AnalysisIcon model="pipeline_halos" />
|
|
256
|
+
{/snippet}
|
|
257
|
+
Halo
|
|
258
|
+
</NavItem>
|
|
259
|
+
<NavItem {collapsed}>
|
|
260
|
+
{#snippet icon()}
|
|
261
|
+
<AnalysisIcon model="pipeline_large_colonies" />
|
|
262
|
+
{/snippet}
|
|
263
|
+
Large colonies
|
|
264
|
+
</NavItem>
|
|
265
|
+
<NavItem {collapsed}>
|
|
266
|
+
{#snippet icon()}
|
|
267
|
+
<AnalysisIcon model="pipeline_microbial_colonies" />
|
|
268
|
+
{/snippet}
|
|
269
|
+
Microbial colonies
|
|
270
|
+
</NavItem>
|
|
271
|
+
<NavItem {collapsed}>
|
|
272
|
+
{#snippet icon()}
|
|
273
|
+
<AnalysisIcon model="sgs_enteros" />
|
|
274
|
+
{/snippet}
|
|
275
|
+
SGS Enteros
|
|
276
|
+
</NavItem>
|
|
277
|
+
<NavItem {collapsed}>
|
|
278
|
+
{#snippet icon()}
|
|
279
|
+
<AnalysisIcon model="general_germination_rate_with_tracking" />
|
|
280
|
+
{/snippet}
|
|
281
|
+
Germination rate (with tracking)
|
|
282
|
+
</NavItem>
|
|
283
|
+
<NavItem {collapsed}>
|
|
284
|
+
{#snippet icon()}
|
|
285
|
+
<AnalysisIcon model="general_germination_rate_without_tracking" />
|
|
286
|
+
{/snippet}
|
|
287
|
+
Germination rate (without tracking)
|
|
288
|
+
</NavItem>
|
|
289
|
+
<NavItem {collapsed}>
|
|
290
|
+
{#snippet icon()}
|
|
291
|
+
<AnalysisIcon model="pipeline_insects" />
|
|
292
|
+
{/snippet}
|
|
293
|
+
Insects
|
|
294
|
+
</NavItem>
|
|
295
|
+
<NavItem {collapsed}>
|
|
296
|
+
{#snippet icon()}
|
|
297
|
+
<AnalysisIcon model="pipeline_colony_formation" />
|
|
298
|
+
{/snippet}
|
|
299
|
+
Colony formation
|
|
300
|
+
</NavItem>
|
|
301
|
+
<NavItem {collapsed}>
|
|
302
|
+
{#snippet icon()}
|
|
303
|
+
<AnalysisIcon model="pipeline_radial_growth" />
|
|
304
|
+
{/snippet}
|
|
305
|
+
Radial growth
|
|
306
|
+
</NavItem>
|
|
307
|
+
<NavItem {collapsed}>
|
|
308
|
+
{#snippet icon()}
|
|
309
|
+
<AnalysisIcon model="syngenta_health_score_crw" />
|
|
310
|
+
{/snippet}
|
|
311
|
+
Health score CRW
|
|
312
|
+
</NavItem>
|
|
313
|
+
<NavItem {collapsed}>
|
|
314
|
+
{#snippet icon()}
|
|
315
|
+
<AnalysisIcon model="pipeline_seed_germination" />
|
|
316
|
+
{/snippet}
|
|
317
|
+
Seed germination
|
|
318
|
+
</NavItem>
|
|
319
|
+
<NavItem {collapsed}>
|
|
320
|
+
{#snippet icon()}
|
|
321
|
+
<AnalysisIcon model="syngenta_health_score_faw" />
|
|
322
|
+
{/snippet}
|
|
323
|
+
Health score FAW
|
|
324
|
+
</NavItem>
|
|
325
|
+
{/snippet}
|
|
326
|
+
{#snippet footer({ collapsed, NavItem })}
|
|
327
|
+
<NavItem {collapsed}>
|
|
328
|
+
{#snippet icon()}
|
|
329
|
+
<Icon icon={UserCircle} />
|
|
330
|
+
{/snippet}
|
|
331
|
+
Profile
|
|
332
|
+
</NavItem>
|
|
333
|
+
<NavItem {collapsed}>
|
|
334
|
+
{#snippet icon()}
|
|
335
|
+
<Icon icon={Question} />
|
|
336
|
+
{/snippet}
|
|
337
|
+
Help
|
|
338
|
+
</NavItem>
|
|
339
|
+
{/snippet}
|
|
340
|
+
</Nav>
|
|
341
|
+
<main class="flex-1 overflow-y-auto bg-surface p-6">
|
|
342
|
+
<div class="space-y-4">
|
|
343
|
+
<h3 class="font-semibold">Quality sidebar - Many analyses</h3>
|
|
344
|
+
<p class="text-secondary">
|
|
345
|
+
This story demonstrates scrolling behavior with many analysis items. The main section should scroll while the header, top, and footer sections remain sticky.
|
|
346
|
+
</p>
|
|
347
|
+
</div>
|
|
348
|
+
</main>
|
|
349
|
+
</div>
|
|
350
|
+
</div>
|
|
351
|
+
</Story>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export default Nav;
|
|
2
|
+
type Nav = SvelteComponent<{
|
|
3
|
+
[x: string]: never;
|
|
4
|
+
}, {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
}, {}> & {
|
|
7
|
+
$$bindings?: string | undefined;
|
|
8
|
+
};
|
|
9
|
+
declare const Nav: $$__sveltets_2_IsomorphicComponent<{
|
|
10
|
+
[x: string]: never;
|
|
11
|
+
}, {
|
|
12
|
+
[evt: string]: CustomEvent<any>;
|
|
13
|
+
}, {}, {}, string>;
|
|
14
|
+
import Nav from './Nav.svelte';
|
|
15
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
16
|
+
new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
|
|
17
|
+
$$bindings?: Bindings;
|
|
18
|
+
} & Exports;
|
|
19
|
+
(internal: unknown, props: {
|
|
20
|
+
$$events?: Events;
|
|
21
|
+
$$slots?: Slots;
|
|
22
|
+
}): Exports & {
|
|
23
|
+
$set?: any;
|
|
24
|
+
$on?: any;
|
|
25
|
+
};
|
|
26
|
+
z_$$bindings?: Bindings;
|
|
27
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import Logo from '../logo/Logo.svelte';
|
|
4
|
+
import { CaretRight, CaretLeft, CaretDown } from 'phosphor-svelte';
|
|
5
|
+
import { Icon } from '../icons/index.js';
|
|
6
|
+
import NavItem from './NavItem.svelte';
|
|
7
|
+
import NavItemGroup from './NavItemGroup.svelte';
|
|
8
|
+
import { IconButton } from '../icon-button/index.js';
|
|
9
|
+
import { Tooltip } from '../tooltip/index.js';
|
|
10
|
+
import * as Dropdown from '../dropdown/index.js';
|
|
11
|
+
|
|
12
|
+
type Props = {
|
|
13
|
+
top?: Snippet<[{ collapsed: boolean; NavItem: typeof NavItem }]>;
|
|
14
|
+
main?: Snippet<
|
|
15
|
+
[{ collapsed: boolean; NavItem: typeof NavItem; NavItemGroup: typeof NavItemGroup }]
|
|
16
|
+
>;
|
|
17
|
+
footer?: Snippet<[{ collapsed: boolean; NavItem: typeof NavItem }]>;
|
|
18
|
+
workspaceMenu?: Snippet<[{ Dropdown: typeof Dropdown }]>;
|
|
19
|
+
defaultCollapsed?: boolean;
|
|
20
|
+
company?: string;
|
|
21
|
+
hasBackground?: boolean;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const { top, main, footer, workspaceMenu, defaultCollapsed, company, hasBackground = true }: Props = $props();
|
|
25
|
+
let collapsed = $state(defaultCollapsed ?? false);
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<div role="navigation" aria-label="Main navigation" class="nav border-static sticky top-0 flex h-full w-56 flex-col p-2 shrink-0 transition-all" class:collapsed class:bg-base={hasBackground} class:bg-transparent={!hasBackground} class:border-r={hasBackground}>
|
|
29
|
+
<div
|
|
30
|
+
class="nav-toggle absolute right-0 top-4 flex translate-x-1/2 rounded-full border border-interactive bg-surface shadow-input opacity-0 transition-opacity delay-300"
|
|
31
|
+
>
|
|
32
|
+
<Tooltip placement="right">
|
|
33
|
+
{#snippet trigger()}
|
|
34
|
+
<IconButton
|
|
35
|
+
variant="transparent"
|
|
36
|
+
size="xs"
|
|
37
|
+
onclick={() => (collapsed = !collapsed)}
|
|
38
|
+
>
|
|
39
|
+
{#if collapsed}
|
|
40
|
+
<Icon icon={CaretRight} />
|
|
41
|
+
{:else}
|
|
42
|
+
<Icon icon={CaretLeft} />
|
|
43
|
+
{/if}
|
|
44
|
+
</IconButton>
|
|
45
|
+
{/snippet}
|
|
46
|
+
{#snippet content()}
|
|
47
|
+
{collapsed ? 'Expand sidebar' : 'Collapse sidebar'}
|
|
48
|
+
{/snippet}
|
|
49
|
+
</Tooltip>
|
|
50
|
+
</div>
|
|
51
|
+
<div class="flex-shrink-0 mb-3 @container">
|
|
52
|
+
{#if workspaceMenu}
|
|
53
|
+
<Dropdown.Root>
|
|
54
|
+
<Dropdown.Trigger>
|
|
55
|
+
{#snippet child({ props }: { props: Record<string, any> })}
|
|
56
|
+
<button
|
|
57
|
+
{...props}
|
|
58
|
+
class="flex w-full min-w-0 items-center gap-1 rounded-lg transition-colors hover:bg-neutral"
|
|
59
|
+
>
|
|
60
|
+
<div class="flex size-10 shrink-0 items-center justify-center">
|
|
61
|
+
<Logo size="xs" />
|
|
62
|
+
</div>
|
|
63
|
+
<span class="@[100px]:flex hidden w-full items-center gap-2 truncate">
|
|
64
|
+
<span class="font-medium truncate">{company}</span>
|
|
65
|
+
<Icon icon={CaretDown} size={14} color="secondary" class="@[100px]:block hidden shrink-0" />
|
|
66
|
+
</span>
|
|
67
|
+
</button>
|
|
68
|
+
{/snippet}
|
|
69
|
+
</Dropdown.Trigger>
|
|
70
|
+
<Dropdown.Portal>
|
|
71
|
+
<Dropdown.Content align="start" class="min-w-52">
|
|
72
|
+
{@render workspaceMenu({ Dropdown })}
|
|
73
|
+
</Dropdown.Content>
|
|
74
|
+
</Dropdown.Portal>
|
|
75
|
+
</Dropdown.Root>
|
|
76
|
+
{:else}
|
|
77
|
+
<div class="flex w-full items-center gap-1">
|
|
78
|
+
<div class="flex size-10 shrink-0 items-center justify-center">
|
|
79
|
+
<Logo size="xs" />
|
|
80
|
+
</div>
|
|
81
|
+
<span class="font-medium truncate">{company}</span>
|
|
82
|
+
</div>
|
|
83
|
+
{/if}
|
|
84
|
+
</div>
|
|
85
|
+
|
|
86
|
+
{#if top}
|
|
87
|
+
<div class="flex-shrink-0 mb-3">
|
|
88
|
+
<div class="section">
|
|
89
|
+
{@render top({ collapsed, NavItem })}
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
{/if}
|
|
93
|
+
|
|
94
|
+
{#if main}
|
|
95
|
+
<div class="flex-1 relative min-h-0 main-section-wrapper">
|
|
96
|
+
<div class="h-full overflow-y-auto overflow-x-hidden">
|
|
97
|
+
<div class="section">
|
|
98
|
+
{@render main({ collapsed, NavItem, NavItemGroup })}
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
{/if}
|
|
103
|
+
|
|
104
|
+
{#if footer}
|
|
105
|
+
<div class="flex-shrink-0 pb-2 mt-3">
|
|
106
|
+
<div class="section">
|
|
107
|
+
{@render footer({ collapsed, NavItem })}
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
{/if}
|
|
111
|
+
</div>
|
|
112
|
+
|
|
113
|
+
<style>
|
|
114
|
+
.nav:hover .nav-toggle {
|
|
115
|
+
opacity: 1;
|
|
116
|
+
transition-property: opacity;
|
|
117
|
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
118
|
+
transition-duration: 150ms;
|
|
119
|
+
transition-delay: 0s;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.main-section-wrapper::after {
|
|
123
|
+
content: '';
|
|
124
|
+
pointer-events: none;
|
|
125
|
+
position: absolute;
|
|
126
|
+
bottom: 0px;
|
|
127
|
+
left: 0px;
|
|
128
|
+
right: 0px;
|
|
129
|
+
z-index: 10;
|
|
130
|
+
height: 1.5rem;
|
|
131
|
+
background: linear-gradient(to bottom, transparent, #f9f9fa);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.section {
|
|
135
|
+
display: flex;
|
|
136
|
+
flex-direction: column;
|
|
137
|
+
gap: 0.25rem;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.collapsed {
|
|
141
|
+
width: 3.5rem;
|
|
142
|
+
}
|
|
143
|
+
</style>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import NavItem from './NavItem.svelte';
|
|
3
|
+
import NavItemGroup from './NavItemGroup.svelte';
|
|
4
|
+
import * as Dropdown from '../dropdown/index.js';
|
|
5
|
+
type Props = {
|
|
6
|
+
top?: Snippet<[{
|
|
7
|
+
collapsed: boolean;
|
|
8
|
+
NavItem: typeof NavItem;
|
|
9
|
+
}]>;
|
|
10
|
+
main?: Snippet<[
|
|
11
|
+
{
|
|
12
|
+
collapsed: boolean;
|
|
13
|
+
NavItem: typeof NavItem;
|
|
14
|
+
NavItemGroup: typeof NavItemGroup;
|
|
15
|
+
}
|
|
16
|
+
]>;
|
|
17
|
+
footer?: Snippet<[{
|
|
18
|
+
collapsed: boolean;
|
|
19
|
+
NavItem: typeof NavItem;
|
|
20
|
+
}]>;
|
|
21
|
+
workspaceMenu?: Snippet<[{
|
|
22
|
+
Dropdown: typeof Dropdown;
|
|
23
|
+
}]>;
|
|
24
|
+
defaultCollapsed?: boolean;
|
|
25
|
+
company?: string;
|
|
26
|
+
hasBackground?: boolean;
|
|
27
|
+
};
|
|
28
|
+
declare const Nav: import("svelte").Component<Props, {}, "">;
|
|
29
|
+
type Nav = ReturnType<typeof Nav>;
|
|
30
|
+
export default Nav;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import { Tooltip } from '../tooltip/index.js';
|
|
4
|
+
|
|
5
|
+
type Props = {
|
|
6
|
+
onclick?: () => void;
|
|
7
|
+
href?: string;
|
|
8
|
+
active?: boolean;
|
|
9
|
+
icon?: Snippet;
|
|
10
|
+
children?: Snippet;
|
|
11
|
+
class?: string;
|
|
12
|
+
collapsed?: boolean;
|
|
13
|
+
rightSlot?: Snippet;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const {
|
|
17
|
+
onclick,
|
|
18
|
+
href,
|
|
19
|
+
active,
|
|
20
|
+
icon,
|
|
21
|
+
children,
|
|
22
|
+
class: className,
|
|
23
|
+
collapsed = false,
|
|
24
|
+
rightSlot,
|
|
25
|
+
}: Props = $props();
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
{#snippet navItemContent()}
|
|
29
|
+
<div class="flex w-full items-center justify-between gap-3">
|
|
30
|
+
<div class="flex min-w-0 flex-1 items-center gap-3">
|
|
31
|
+
{#if icon}
|
|
32
|
+
<div class="flex h-4 w-4 flex-shrink-0 items-center justify-center">
|
|
33
|
+
{@render icon()}
|
|
34
|
+
</div>
|
|
35
|
+
{/if}
|
|
36
|
+
<div class="@[100px]:block hidden truncate pr-0">
|
|
37
|
+
{@render children?.()}
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
{#if rightSlot && !collapsed}
|
|
41
|
+
<div class="flex flex-shrink-0 items-center gap-2">
|
|
42
|
+
{@render rightSlot()}
|
|
43
|
+
</div>
|
|
44
|
+
{/if}
|
|
45
|
+
</div>
|
|
46
|
+
{/snippet}
|
|
47
|
+
|
|
48
|
+
{#snippet navItemContainer()}
|
|
49
|
+
{#if href}
|
|
50
|
+
<a
|
|
51
|
+
class="nav-item-container {className}"
|
|
52
|
+
class:active
|
|
53
|
+
class:collapsed
|
|
54
|
+
{href}
|
|
55
|
+
{onclick}
|
|
56
|
+
>
|
|
57
|
+
{@render navItemContent()}
|
|
58
|
+
</a>
|
|
59
|
+
{:else}
|
|
60
|
+
<button
|
|
61
|
+
type="button"
|
|
62
|
+
tabindex="0"
|
|
63
|
+
class="nav-item-container {className}"
|
|
64
|
+
class:active
|
|
65
|
+
class:collapsed
|
|
66
|
+
{onclick}
|
|
67
|
+
>
|
|
68
|
+
{@render navItemContent()}
|
|
69
|
+
</button>
|
|
70
|
+
{/if}
|
|
71
|
+
{/snippet}
|
|
72
|
+
|
|
73
|
+
{#if collapsed && children}
|
|
74
|
+
<Tooltip placement="right" showArrow={true}>
|
|
75
|
+
{#snippet trigger()}
|
|
76
|
+
{@render navItemContainer()}
|
|
77
|
+
{/snippet}
|
|
78
|
+
{#snippet content()}
|
|
79
|
+
<div class="flex flex-row items-center gap-2">
|
|
80
|
+
{@render children?.()}
|
|
81
|
+
</div>
|
|
82
|
+
{/snippet}
|
|
83
|
+
</Tooltip>
|
|
84
|
+
{:else}
|
|
85
|
+
{@render navItemContainer()}
|
|
86
|
+
{/if}
|
|
87
|
+
|
|
88
|
+
<style>
|
|
89
|
+
.nav-item-container {
|
|
90
|
+
|
|
91
|
+
display: flex;
|
|
92
|
+
|
|
93
|
+
height: 2.5rem;
|
|
94
|
+
|
|
95
|
+
width: 100%;
|
|
96
|
+
|
|
97
|
+
min-width: 2.5rem;
|
|
98
|
+
|
|
99
|
+
cursor: pointer;
|
|
100
|
+
|
|
101
|
+
align-items: center;
|
|
102
|
+
|
|
103
|
+
border-radius: 0.5rem;
|
|
104
|
+
|
|
105
|
+
background-color: transparent;
|
|
106
|
+
|
|
107
|
+
padding: 0.75rem;
|
|
108
|
+
|
|
109
|
+
padding-right: 0.5rem;
|
|
110
|
+
|
|
111
|
+
font-size: 0.875rem;
|
|
112
|
+
|
|
113
|
+
line-height: 1.25rem;
|
|
114
|
+
|
|
115
|
+
font-weight: 500;
|
|
116
|
+
|
|
117
|
+
--tw-text-opacity: 1;
|
|
118
|
+
|
|
119
|
+
color: rgb(89 94 106 / var(--tw-text-opacity, 1));
|
|
120
|
+
|
|
121
|
+
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
|
|
122
|
+
|
|
123
|
+
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
|
|
124
|
+
|
|
125
|
+
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
|
|
126
|
+
|
|
127
|
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
128
|
+
|
|
129
|
+
transition-duration: 150ms;
|
|
130
|
+
|
|
131
|
+
container-type: inline-size
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.nav-item-container:hover {
|
|
135
|
+
|
|
136
|
+
background-color: #12192a0A;
|
|
137
|
+
|
|
138
|
+
--tw-text-opacity: 1;
|
|
139
|
+
|
|
140
|
+
color: rgb(18 25 42 / var(--tw-text-opacity, 1))
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.nav-item-container.active {
|
|
144
|
+
|
|
145
|
+
background-color: #12192a0A;
|
|
146
|
+
|
|
147
|
+
--tw-text-opacity: 1;
|
|
148
|
+
|
|
149
|
+
color: rgb(18 25 42 / var(--tw-text-opacity, 1))
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.nav-item-container.collapsed {
|
|
153
|
+
|
|
154
|
+
width: 2.5rem;
|
|
155
|
+
|
|
156
|
+
justify-content: center
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
a.nav-item-container {
|
|
160
|
+
|
|
161
|
+
color: inherit;
|
|
162
|
+
|
|
163
|
+
text-decoration-line: none
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
</style>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
type Props = {
|
|
3
|
+
onclick?: () => void;
|
|
4
|
+
href?: string;
|
|
5
|
+
active?: boolean;
|
|
6
|
+
icon?: Snippet;
|
|
7
|
+
children?: Snippet;
|
|
8
|
+
class?: string;
|
|
9
|
+
collapsed?: boolean;
|
|
10
|
+
rightSlot?: Snippet;
|
|
11
|
+
};
|
|
12
|
+
declare const NavItem: import("svelte").Component<Props, {}, "">;
|
|
13
|
+
type NavItem = ReturnType<typeof NavItem>;
|
|
14
|
+
export default NavItem;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
type Props = {
|
|
3
|
+
name: string;
|
|
4
|
+
collapsed?: boolean;
|
|
5
|
+
};
|
|
6
|
+
const { name, collapsed = false }: Props = $props();
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
{#if !collapsed}
|
|
10
|
+
<div class="nav-item-group">
|
|
11
|
+
<p class="text-label text-tertiary h-6 pl-3 mt-2 font-medium">{name}</p>
|
|
12
|
+
</div>
|
|
13
|
+
{/if}
|
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
import Toast from '../toast/Toast.svelte';
|
|
6
6
|
</script>
|
|
7
7
|
|
|
8
|
-
<div
|
|
8
|
+
<div
|
|
9
|
+
class="fixed left-0 right-0 top-2 z-[60] mx-auto flex w-fit flex-col items-center justify-start"
|
|
10
|
+
>
|
|
9
11
|
{#each $notifications as notification (notification.id)}
|
|
10
12
|
<div animate:flip transition:fly={{ y: -10 }}>
|
|
11
13
|
<Toast {notification} />
|
package/dist/index.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ export * from './components/markdown/index.js';
|
|
|
23
23
|
export * as Modal from './components/modal/index.js';
|
|
24
24
|
export * from './components/manual-cfu-counter/index.js';
|
|
25
25
|
export * from './components/multi-cfu-counter/index.js';
|
|
26
|
+
export * from './components/nav/index.js';
|
|
26
27
|
export * from './components/notification-popup/index.js';
|
|
27
28
|
export * from './components/notifications/index.js';
|
|
28
29
|
export * from './components/pill/index.js';
|
package/dist/index.js
CHANGED
|
@@ -24,6 +24,7 @@ export * from './components/markdown/index.js';
|
|
|
24
24
|
export * as Modal from './components/modal/index.js';
|
|
25
25
|
export * from './components/manual-cfu-counter/index.js';
|
|
26
26
|
export * from './components/multi-cfu-counter/index.js';
|
|
27
|
+
export * from './components/nav/index.js';
|
|
27
28
|
export * from './components/notification-popup/index.js';
|
|
28
29
|
export * from './components/notifications/index.js';
|
|
29
30
|
export * from './components/pill/index.js';
|