Skip to content

Commit

Permalink
feat: Time-bound banner (#255)
Browse files Browse the repository at this point in the history
* Push

* Add changeset

* Banners

* Explicitly type
  • Loading branch information
PuruVJ authored Dec 5, 2023
1 parent 0cfa3e5 commit 53b5034
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 27 deletions.
5 changes: 5 additions & 0 deletions .changeset/clean-wombats-work.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/site-kit': patch
---

feat: Time-bound banner
87 changes: 61 additions & 26 deletions packages/site-kit/src/lib/components/Banner.svelte
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
<script context="module">
const banner_preferences = persisted(
'svelte:banner-preferences',
/** @type {Record<string, boolean>} */ ({})
);
/**
* @typedef {'svelte.dev' | 'kit.svelte.dev' | 'learn.svelte.dev'} BannerScope
* @typedef {(import('svelte').ComponentProps<import('./Banner.svelte').default> & {
* content: string; scope?: BannerScope[]
* })[]} BannerData
*/
</script>

<script>
Expand All @@ -21,11 +23,39 @@
*/
export let id;
/**
* Link to the event. It must be an absolute path (https://svelte.dev/blog/runes instead of /blog/runes)
* @type {string}
*/
export let href;
/**
* When to start showing the banner
* @type {Date}
*/
export let start;
/**
* When to stop showing the banner. Banner never goes away if this value is not provided
* @type {Date}
*/
export let end = new Date(2123, 12, 1);
const banner_preferences = persisted(
'svelte:banner-preferences',
/** @type {Record<string, boolean>} */ ({})
);
let height = 0;
const time = new Date();
$: show = $banner_preferences[id] && time > start && time < end;
$: if (browser) {
document.documentElement.style.setProperty(
'--sk-banner-bottom-height',
($banner_preferences[id] ? height : 0) + 'px'
(show ? height : 0) + 'px'
);
}
Expand All @@ -34,42 +64,47 @@
});
</script>
{#if $banner_preferences[id]}
<div class="banner-bottom" bind:clientHeight={height}>
<div class="main-area">
<div class="banner-bottom" bind:clientHeight={height} class:show>
<div class="main-area">
<a {href}>
<slot />
</a>
{#if arrow}
<Icon name="arrow-right" size="1.2em" />
{/if}
</div>
<button class="close-button" on:click={() => ($banner_preferences[id] = false)}>
<Icon name="close" />
</button>
{#if arrow}
<Icon name="arrow-right" size="1.2em" />
{/if}
</div>
{/if}
<button class="close-button" on:click={() => ($banner_preferences[id] = false)}>
<Icon name="close" />
</button>
</div>
<style>
.banner-bottom {
position: relative;
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 80;
display: flex;
justify-content: center;
align-items: center;
overflow-y: auto;
}
.banner-bottom {
position: absolute;
bottom: 0;
left: 0;
right: 0;
z-index: 80;
width: 100%;
height: max-content;
transition: opacity 0.2s 0.2s var(--quint-out);
opacity: 0;
pointer-events: none;
}
.show {
pointer-events: all;
opacity: 1;
}
.banner-bottom {
Expand Down
34 changes: 34 additions & 0 deletions packages/site-kit/src/lib/components/Banners.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<script context="module">
/**
* Only to be used on non svelte.dev sites. Shouldn't be used inside svelte.dev codebase itself
* @param {import('./Banner.svelte').BannerScope} scope
* @param {import('@sveltejs/kit').RequestEvent['fetch']} fetch
* @returns {Promise<import('./Banner.svelte').BannerData>}
*/
export async function fetchBanner(scope = 'svelte.dev', fetch) {
if (scope === 'svelte.dev') return fetch('/banner.json').then((r) => r.json());
const req = await fetch('https://svelte.dev/banner.json');
if (!req.ok) {
console.warn('There was an error fetching the banner data. Check svelte.dev/banner.json');
return [];
}
return /** @type {import('./Banner.svelte').BannerData} */ (await req.json()).filter(
(banner) => !banner.scope || banner.scope?.includes(scope)
);
}
</script>
<script>
import Banner from './Banner.svelte';
/** @type {import('./Banner.svelte').BannerData} */
export let data;
</script>
{#each data as { content, href, id, start, arrow, end }}
<Banner {id} start={new Date(start)} end={end ? new Date(end) : undefined} {arrow} {href}>
{@html content}
</Banner>
{/each}
2 changes: 1 addition & 1 deletion packages/site-kit/src/lib/components/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export { default as Banners, fetchBanner } from './Banners.svelte';
export { default as Icon } from './Icon.svelte';
export { default as Icons } from './Icons.svelte';
export { default as Section } from './Section.svelte';
export { default as Shell } from './Shell.svelte';
export { default as ThemeToggle } from './ThemeToggle.svelte';
export { default as Banner } from './Banner.svelte';

0 comments on commit 53b5034

Please sign in to comment.