Skip to content

Commit b576299

Browse files
committed
0.2.2: global notifications update
1 parent 48eb754 commit b576299

File tree

14 files changed

+116
-77
lines changed

14 files changed

+116
-77
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "sveltekit-components",
3-
"version": "0.2.1",
3+
"version": "0.2.2",
44
"description": "An opinionated UI library of SvelteKit components",
55
"license": "MIT",
66
"scripts": {

src/app.html

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
<!-- SvelteKit tags -->
2929
<link rel="manifest" href="/manifest.json" />
3030

31+
<script nonce="%sveltekit.nonce%"></script>
32+
3133
%svelte.head%
3234
</head>
3335
<body>

src/lib/components/Advanced/Plausible/Plausible.svelte

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
local ? 'local' : undefined,
4242
'js'
4343
].filter(Boolean).join('.')
44+
4445
</script>
4546

4647
<svelte:head>

src/lib/components/General/Notification/Notification.svelte

+33-29
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
<script lang="ts">
22
import type { FlyParams } from 'svelte/transition'
3-
import { fly } from 'svelte/transition'
4-
import { goto } from '$app/navigation'
5-
63
import type { NotificationType } from '$lib/types'
7-
import { Notify } from '$lib/stores/notification'
4+
import { goto } from '$app/navigation'
5+
import { fly } from 'svelte/transition'
86
import { InfoIcon, CheckCircleIcon, AlertTriangleIcon, XCircleIcon, XIcon } from 'svelte-feather-icons'
7+
import notification from '$lib/stores/notification'
98
109
export let item: NotificationType = undefined
11-
export let closable: boolean = false
1210
1311
export let flyInParams: FlyParams = { x: -50 }
1412
export let flyOutParams: FlyParams = { x: -50 }
1513
16-
14+
$: item.type = item.type === undefined ? 'info' : item.type
1715
</script>
1816

1917
<div
@@ -25,37 +23,43 @@
2523
aria-live="polite"
2624
{...$$restProps}
2725
on:click
28-
on:click={() => {
29-
if (item?.href) {
30-
goto(item.href)
31-
}
32-
}}
26+
3327
on:mouseenter
3428
on:mouseleave
3529
>
36-
<header class="heading">
37-
<div class="icon">
38-
{#if item?.type}
39-
{#if item?.type === 'info'}<InfoIcon size="24" />{/if}
40-
{#if item?.type === 'success'}<CheckCircleIcon size="24" />{/if}
41-
{#if item?.type === 'warning'}<AlertTriangleIcon size="24" />{/if}
42-
{#if item?.type === 'error'}<XCircleIcon size="24" />{/if}
43-
{/if}
44-
</div>
45-
<h4 class="title">{item?.title}</h4>
46-
</header>
47-
{#if item?.description}
48-
<div class="description">
49-
{item?.description}
50-
</div>
51-
{/if}
52-
{#if closable && !item?.href}
30+
<div
31+
class="inner"
32+
on:click={() => {
33+
if (item?.href) {
34+
item.href.startsWith('http') ? window.open(item.href, '_blank') : goto(item.href)
35+
notification.close(item)
36+
}
37+
}}
38+
>
39+
<header class="heading">
40+
<div class="icon">
41+
{#if item?.type}
42+
{#if item?.type === 'info'}<InfoIcon size="24" />{/if}
43+
{#if item?.type === 'success'}<CheckCircleIcon size="24" />{/if}
44+
{#if item?.type === 'warning'}<AlertTriangleIcon size="24" />{/if}
45+
{#if item?.type === 'error'}<XCircleIcon size="24" />{/if}
46+
{/if}
47+
</div>
48+
<h4 class="title">{item?.title}</h4>
49+
</header>
50+
{#if item?.description}
51+
<div class="description">
52+
{item?.description}
53+
</div>
54+
{/if}
55+
</div>
56+
{#if item?.closable}
5357
<button
5458
type="button"
5559
class="close"
5660
aria-label="close notification"
5761
on:click={() => {
58-
Notify.close(item)
62+
notification.close(item)
5963
}}
6064
>
6165
<XIcon size="16" />
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
<script lang="ts">
22
import type { FlyParams } from 'svelte/transition'
3-
import { Notify } from '$lib/stores/notification'
4-
import { Notification, Portal } from '$lib/components'
3+
import type { NotificationPositionsType } from '$lib/types'
4+
import Notification from './Notification.svelte'
55
6-
export let position: 'top-right' | 'top-center' | 'top-left' | 'bottom-right' | 'bottom-center' | 'bottom-left' = 'top-right'
7-
export let duration: number = 5000
8-
export let closable: boolean = false
9-
6+
import notification from '$lib/stores/notification'
7+
8+
export let duration: number = 5000
9+
export let position: NotificationPositionsType = 'top-right'
1010
1111
const getFlyParamsFromPosition = (pos: string): FlyParams => {
1212
if (pos.endsWith('-right')) return { x: 50 }
@@ -16,19 +16,22 @@
1616
}
1717
1818
$: flyParams = getFlyParamsFromPosition(position)
19-
$: duration && Notify.setDuration(duration)
19+
$: position && notification.setPosition(position)
20+
$: duration && notification.setDuration(duration)
2021
</script>
2122

22-
{#if $Notify.items.length !== 0}
23-
<Portal>
24-
<div class="notification-provider {position}">
25-
<div class="area">
26-
{#each $Notify.items as item}
27-
<slot {item} {closable}>
28-
<Notification {item} {closable} flyInParams={flyParams} flyOutParams={flyParams} />
29-
</slot>
30-
{/each}
31-
</div>
23+
{#if $notification.items.length > 0}
24+
<div
25+
class="notification-provider {position}"
26+
data-duration={duration}
27+
data-position={position}
28+
>
29+
<div class="area">
30+
{#each $notification.items as item}
31+
<slot {item}>
32+
<Notification {item} flyInParams={flyParams} flyOutParams={flyParams} />
33+
</slot>
34+
{/each}
3235
</div>
33-
</Portal>
36+
</div>
3437
{/if}

src/lib/components/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export { default as Modal } from './General/Modal'
7272

7373
export { default as Notification } from './General/Notification'
7474
export { default as NotificationProvider } from './General/Notification/NotificationProvider.svelte'
75-
export { Notify } from '../stores/notification'
75+
export { default as notification } from '../stores/notification'
7676

7777
export { default as Portal } from './General/Portal'
7878

src/lib/sass/base/_typography.sass

+7-1
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,10 @@ p > code
3939
background-color: var(--bg-code)
4040
color: var(--accent)
4141
padding: .125rem .25rem
42-
border-radius: .125rem
42+
border-radius: .125rem
43+
44+
code[class*="language-"],
45+
pre[class*="language-"]
46+
font-family: 'Fira Mono', monospace !important
47+
font-size: .875rem !important
48+
line-height: 1.8

src/lib/sass/components/_general.sass

+6-3
Original file line numberDiff line numberDiff line change
@@ -734,8 +734,7 @@
734734
.notification
735735
display: flex
736736
flex-direction: column
737-
min-width: 150px
738-
max-width: 250px
737+
width: 250px
739738
min-height: 100px
740739
background-color: $accent-dark
741740
border: 1px solid $accent
@@ -747,6 +746,10 @@
747746
&.clickable
748747
cursor: pointer
749748

749+
.inner
750+
width: 100%
751+
height: 100%
752+
750753
.heading
751754
display: flex
752755
align-items: center
@@ -920,7 +923,7 @@
920923

921924
/** Tag Component **/
922925

923-
.tag:not(.snippet .tag)
926+
span.tag:not(.snippet .tag):not(.token.tag)
924927
display: inline-flex
925928
vertical-align: middle
926929
align-items: center

src/lib/stores/menu.ts

+1
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ const menuMap: MenuType = [
156156
{
157157
label: 'Notification',
158158
href: '/docs/general/notification',
159+
tag: 'update'
159160
},
160161
{
161162
label: 'Popover',

src/lib/stores/notification.ts

+15-11
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,32 @@
1-
import type { NotificationType, NotificationOptionsType } from '$lib/types'
1+
import type { NotificationType, NotificationOptionsType, NotificationPositionsType } from '$lib/types'
22
import { writable } from 'svelte/store'
33

4-
function createNotificationStore() {
4+
5+
6+
const createStore = () => {
57
let id = 0
68
const { update, subscribe } = writable({
79
duration: 5000,
10+
position: 'top-right',
811
items: []
912
})
1013

1114
return {
1215
subscribe: subscribe,
13-
show: (item: NotificationType, options?: NotificationOptionsType) =>
14-
update((n) => {
15-
id++
16-
item.id = id
16+
add: (item: NotificationType, options?: NotificationOptionsType) => update((n) => {
17+
id++
18+
item.id = id
19+
if (!item.closable && !item.href) {
1720
setTimeout(() => {
1821
update((n) => ({ ...n, items: n.items.filter((i) => i !== item) }))
1922
}, options?.duration ?? n.duration)
20-
return { ...n, items: [item, ...n.items] }
21-
}),
23+
}
24+
return { ...n, items: [item, ...n.items] }
25+
}),
2226
setDuration: (duration: number) => update((n) => ({ ...n, duration })),
23-
close: (item: NotificationType) =>
24-
update((n) => ({ ...n, items: n.items.filter((i) => i !== item) }))
27+
setPosition: (position: NotificationPositionsType) => update((n) => ({ ...n, position })),
28+
close: (item: NotificationType) => update((n) => ({ ...n, items: n.items.filter((i) => i !== item) }))
2529
}
2630
}
2731

28-
export const Notify = createNotificationStore()
32+
export default createStore()

src/lib/types.d.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,22 @@ export type Action = (
1919

2020
/** Notification */
2121

22+
export type NotificationPositionsType = 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right'
23+
24+
export interface NotificationOptionsType {
25+
duration?: number
26+
position?: NotificationPositionType
27+
}
28+
2229
export interface NotificationType {
2330
title?: string
2431
description?: string
2532
type?: 'error' | 'success' | 'warning' | 'info'
2633
href?: string
34+
closable?: boolean
2735
[key: string]: unknown
2836
}
2937

30-
export interface NotificationOptionsType {
31-
duration?: number
32-
}
33-
3438
/** Menu */
3539

3640
export interface MenuItemType {

src/routes/docs/__layout.svelte

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<script lang="ts">
22
import { afterNavigate } from '$app/navigation'
3-
import { Menu, MenuSection, MenuItem, Content } from '$lib/components'
3+
import { Menu, MenuSection, MenuItem, Content, NotificationProvider } from '$lib/components'
44
import { menu } from '$lib/stores/menu'
55
import '$lib/sass/main.sass'
6-
6+
77
afterNavigate(() => {
88
if ($menu.opened) {
99
menu.setOpened(false)
@@ -12,6 +12,7 @@
1212
1313
</script>
1414

15+
<NotificationProvider />
1516
<Menu>
1617
{#each $menu.map as section}
1718
<MenuSection label={section.label}>

src/routes/docs/general/notification.md

+16-7
Original file line numberDiff line numberDiff line change
@@ -5,33 +5,42 @@ components: ['Notification', 'NotificationProvider']
55
---
66

77
<script>
8-
import { Notify, NotificationProvider, Button, Preview } from '$lib/components'
8+
import { notification, Button, Preview } from '$lib/components'
99
</script>
1010

11-
Laborum quis proident non quis minim quis nulla nulla sint cillum duis commodo. Velit tempor elit ipsum officia ex voluptate enim. Pariatur cillum Lorem dolore magna fugiat mollit proident mollit pariatur aliquip qui. Cillum mollit anim veniam ullamco commodo ex voluptate in culpa pariatur cupidatat. Consequat do sunt nisi laborum pariatur cupidatat Lorem velit.
11+
Before you can use the notification feature, you have to set up the `NotificationProvider` in your `_layout.svelte` file:
12+
13+
```html
14+
<script>
15+
import { NotificationProvider } from 'svelte-components'
16+
</script>
17+
<NotificationProvider duration={3000} position="bottom-right" />
18+
```
19+
20+
You can set up the `duration` (in ms) and `position` globally.
1221

1322
### Default Notification
1423

1524
<Button
1625
on:click={() => {
17-
Notify.show({
26+
notification.add({
1827
title: 'Successfully saved!',
1928
description: 'This is an example for a notification.',
2029
type: 'success'
2130
})
2231
}}
2332
>Click me!</Button>
24-
<NotificationProvider duration={5000} position="top-right" closable={true} />
2533
26-
### Clickable Notification
34+
### Clickable and Closable Notification
2735

2836
<Button
2937
on:click={() => {
30-
Notify.show({
38+
notification.add({
3139
title: 'NOOb warning!',
3240
description: "You don't know what you're doing! Click here to see how you can get started.",
3341
href: '/docs/overview/getting-started',
34-
type: 'warning'
42+
type: 'warning',
43+
closable: true
3544
})
3645
}}
3746
>Click me!</Button>

svelte.config.js

+1
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ const config = {
179179
template: 'src/app.html',
180180
hooks: 'src/hooks'
181181
},
182+
floc: dev,
182183
vite: {
183184
resolve: {
184185
alias: {

0 commit comments

Comments
 (0)