Skip to content

Commit 3994336

Browse files
authored
style examples (#111)
1 parent 2b14990 commit 3994336

File tree

15 files changed

+357
-141
lines changed

15 files changed

+357
-141
lines changed

examples/sveltekit-example/package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,13 @@
1212
"format": "prettier --write ."
1313
},
1414
"dependencies": {
15+
"@tailwindcss/typography": "0.5.16",
16+
"@tailwindcss/vite": "4.0.15",
1517
"@vercel/edge": "^1.2.1",
1618
"@vercel/toolbar": "0.1.15",
19+
"cookie": "^0.6.0",
1720
"flags": "workspace:*",
18-
"cookie": "^0.6.0"
21+
"tailwindcss": "4.0.15"
1922
},
2023
"devDependencies": {
2124
"@sveltejs/adapter-vercel": "^5.6.0",
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
@import 'tailwindcss';
2+
@plugin "@tailwindcss/typography";

examples/sveltekit-example/src/app.html

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
<meta name="viewport" content="width=device-width, initial-scale=1" />
77
%sveltekit.head%
88
</head>
9-
<body data-sveltekit-preload-data="hover">
9+
<body
10+
data-sveltekit-preload-data="hover"
11+
class="antialiased prose lg:prose-lg dark:prose-invert px-4 m-0"
12+
>
1013
<div style="display: contents">%sveltekit.body%</div>
1114
</body>
1215
</html>

examples/sveltekit-example/src/lib/flags.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export const firstMarketingABTest = flag<boolean, Entities>({
5050
if (!entities?.visitorId) return false;
5151

5252
// Use any kind of deterministic method that runs on the visitorId
53-
return /^[a-n0-5]/i.test(entities?.visitorId);
53+
return /^[a-m0-4]/i.test(entities?.visitorId);
5454
}
5555
});
5656

@@ -62,6 +62,6 @@ export const secondMarketingABTest = flag<boolean, Entities>({
6262
if (!entities?.visitorId) return false;
6363

6464
// Use any kind of deterministic method that runs on the visitorId
65-
return /[a-n0-5]$/i.test(entities.visitorId);
65+
return /[a-m0-4]$/i.test(entities.visitorId);
6666
}
6767
});
Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,14 @@
11
<script lang="ts">
2+
import '../app.css';
23
import { mountVercelToolbar } from '@vercel/toolbar/vite';
34
import { onMount } from 'svelte';
45
import type { LayoutProps } from './$types';
5-
import { page } from '$app/state';
66
77
onMount(() => mountVercelToolbar());
88
99
let { children }: LayoutProps = $props();
1010
</script>
1111

12-
{#if page.url.pathname !== '/'}
13-
<header>
14-
<nav>
15-
<a href="/">Back to homepage</a>
16-
</nav>
17-
</header>
18-
{/if}
19-
20-
<main>
12+
<main class="mx-4 my-2">
2113
{@render children()}
2214
</main>
Lines changed: 49 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,54 @@
1-
<h1>Flags SDK</h1>
1+
<div class="p-4 prose lg:prose-lg mb-32 dark:prose-invert">
2+
<h1>Flags SDK</h1>
23

3-
<p>This page contains example snippets for the Flags SDK using SvelteKit</p>
4+
<p>This page contains example snippets for the Flags SDK using SvelteKit.</p>
45

5-
<p>
6-
See <a href="https://flags-sdk.dev">flags-sdk.dev</a> for the full documentation, or
7-
<a href="https://github.com/vercel/flags/tree/main/examples/sveltekit-example">GitHub</a> for the source
8-
code.
9-
</p>
6+
<p>
7+
See <a href="https://flags-sdk.dev">flags-sdk.dev</a> for the full documentation, or
8+
<a href="https://github.com/vercel/flags/tree/main/examples/sveltekit-example">GitHub</a> for the
9+
source code.
10+
</p>
1011

11-
<a class="tile" href="/examples/dashboard-pages">
12-
<h3>Dashboard Pages</h3>
13-
<p>Using feature flags on dynamic pages</p>
14-
</a>
12+
<div class="flex flex-col gap-4">
13+
<a class="no-underline" href="/examples/dashboard-pages">
14+
<div
15+
class="rounded-xl border border-neutral-200 bg-white text-neutral-950 shadow dark:border-neutral-800 dark:bg-neutral-950 dark:text-neutral-50"
16+
>
17+
<div class="flex flex-col space-y-1.5 p-6">
18+
<div class="font-semibold leading-none tracking-tight">Dashboard Pages</div>
19+
<div class="text-sm text-neutral-500 dark:text-neutral-400">
20+
Using feature flags on dynamic pages
21+
</div>
22+
</div>
23+
</div>
24+
</a>
1525

16-
<a class="tile" href="/examples/marketing-pages-manual-approach">
17-
<h3>Marketing Pages (manual approach)</h3>
18-
<p>Simple but not scalable approach to feature flags on static pages</p>
19-
</a>
26+
<a class="no-underline" href="/examples/marketing-pages-manual-approach">
27+
<div
28+
class="rounded-xl border border-neutral-200 bg-white text-neutral-950 shadow dark:border-neutral-800 dark:bg-neutral-950 dark:text-neutral-50"
29+
>
30+
<div class="flex flex-col space-y-1.5 p-6">
31+
<div class="font-semibold leading-none tracking-tight">
32+
Marketing Pages (manual approach)
33+
</div>
34+
<div class="text-sm text-neutral-500 dark:text-neutral-400">
35+
Simple but not scalable approach to feature flags on static pages
36+
</div>
37+
</div>
38+
</div>
39+
</a>
2040

21-
<a class="tile" href="/examples/marketing-pages">
22-
<h3>Marketing Pages</h3>
23-
<p>Using feature flags on static pages</p>
24-
</a>
25-
26-
<style>
27-
.tile {
28-
display: block;
29-
padding: 1rem;
30-
margin: 1rem 0;
31-
border: 1px solid #ccc;
32-
border-radius: 0.5rem;
33-
text-decoration: none;
34-
color: inherit;
35-
max-width: 30rem;
36-
}
37-
</style>
41+
<a class="no-underline" href="/examples/marketing-pages">
42+
<div
43+
class="rounded-xl border border-neutral-200 bg-white text-neutral-950 shadow dark:border-neutral-800 dark:bg-neutral-950 dark:text-neutral-50"
44+
>
45+
<div class="flex flex-col space-y-1.5 p-6">
46+
<div class="font-semibold leading-none tracking-tight">Marketing Pages</div>
47+
<div class="text-sm text-neutral-500 dark:text-neutral-400">
48+
Using feature flags on static pages
49+
</div>
50+
</div>
51+
</div>
52+
</a>
53+
</div>
54+
</div>
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
1-
<p>Marketing page (manual approach) variant A</p>
1+
<div class="rounded-md bg-green-100 dark:bg-green-800">
2+
<div class="p-4 text-sm font-medium text-green-800 dark:text-green-100">
3+
The feature flag <span class="font-semibold">marketingABTestManualApproach</span> evaluated to
4+
<span class="font-semibold">true</span>.
5+
</div>
6+
</div>
27

3-
<div>
8+
<div class="flex gap-2 pt-2">
49
<button
10+
class="inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-neutral-950 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 dark:focus-visible:ring-neutral-300 border border-neutral-200 bg-white shadow-sm hover:bg-neutral-100 hover:text-neutral-900 dark:border-neutral-800 dark:bg-neutral-950 dark:hover:bg-neutral-800 dark:hover:text-neutral-50 h-9 px-4 py-2"
511
onclick={() => {
612
document.cookie = 'marketingManual=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT';
713
window.location.reload();
8-
}}>Reset cookie</button
9-
>
10-
<span
11-
>(will automatically assign a new visitor id, which depending on the value will opt you into one
12-
of two variants)</span
14+
}}
1315
>
16+
Reset cookie
17+
</button>
1418
</div>
15-
16-
<style>
17-
div {
18-
max-width: 30rem;
19-
}
20-
</style>
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
1-
<p>Marketing page (manual approach) variant B</p>
1+
<div class="rounded-md bg-fuchsia-100 dark:bg-fuchsia-800">
2+
<div class="p-4 text-sm font-medium text-fuchsia-800 dark:text-fuchsia-100">
3+
The feature flag <span class="font-semibold">marketingABTestManualApproach</span> evaluated to
4+
<span class="font-semibold">false</span>.
5+
</div>
6+
</div>
27

3-
<div>
8+
<div class="flex gap-2 pt-2">
49
<button
10+
class="inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-neutral-950 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 dark:focus-visible:ring-neutral-300 border border-neutral-200 bg-white shadow-sm hover:bg-neutral-100 hover:text-neutral-900 dark:border-neutral-800 dark:bg-neutral-950 dark:hover:bg-neutral-800 dark:hover:text-neutral-50 h-9 px-4 py-2"
511
onclick={() => {
612
document.cookie = 'marketingManual=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT';
713
window.location.reload();
8-
}}>Reset cookie</button
9-
>
10-
<span
11-
>(will automatically assign a new visitor id, which depending on the value will opt you into one
12-
of two variants)</span
14+
}}
1315
>
16+
Reset cookie
17+
</button>
1418
</div>
15-
16-
<style>
17-
div {
18-
max-width: 30rem;
19-
}
20-
</style>

examples/sveltekit-example/src/routes/examples/dashboard-pages/+page.server.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,5 @@ import { showNewDashboard } from '$lib/flags';
44
export const load: PageServerLoad = async () => {
55
const dashboard = await showNewDashboard();
66

7-
return {
8-
title: dashboard ? 'New Dashboard' : `Old Dashboard`
9-
};
7+
return { dashboard };
108
};

examples/sveltekit-example/src/routes/examples/dashboard-pages/+page.svelte

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,48 @@
44
let { data }: PageProps = $props();
55
</script>
66

7-
<h1>{data.title}</h1>
7+
{#if data.dashboard}
8+
<div class="rounded-md bg-green-100 dark:bg-green-800">
9+
<div class="p-4 text-sm font-medium text-green-800 dark:text-green-100">
10+
The feature flag <span class="font-semibold">dashboard-flag</span> evaluated to
11+
<span class="font-semibold">true</span>.
12+
</div>
13+
</div>
14+
{:else}
15+
<div class="rounded-md bg-fuchsia-100 dark:bg-fuchsia-800">
16+
<div class="p-4 text-sm font-medium text-fuchsia-800 dark:text-fuchsia-100">
17+
The feature flag <span class="font-semibold">dashboard-flag</span> evaluated to
18+
<span class="font-semibold">false</span>.
19+
</div>
20+
</div>
21+
{/if}
822

9-
<button
10-
onclick={() => {
11-
document.cookie = 'showNewDashboard=true; Path=/';
12-
window.location.reload();
13-
}}>Act as flagged in user</button
14-
>
15-
<button
16-
onclick={() => {
17-
document.cookie = 'showNewDashboard=false; Path=/';
18-
window.location.reload();
19-
}}>Act as a regular user</button
20-
>
21-
<button
22-
onclick={() => {
23-
document.cookie = 'showNewDashboard=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT';
24-
window.location.reload();
25-
}}>Clear cookie</button
26-
>
23+
<div class="flex gap-2 pt-2">
24+
<button
25+
class="inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-neutral-950 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 dark:focus-visible:ring-neutral-300 border border-neutral-200 bg-white shadow-sm hover:bg-neutral-100 hover:text-neutral-900 dark:border-neutral-800 dark:bg-neutral-950 dark:hover:bg-neutral-800 dark:hover:text-neutral-50 h-9 px-4 py-2"
26+
onclick={() => {
27+
document.cookie = 'showNewDashboard=true; Path=/';
28+
window.location.reload();
29+
}}
30+
>
31+
Act as flagged in user
32+
</button>
33+
<button
34+
class="inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-neutral-950 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 dark:focus-visible:ring-neutral-300 border border-neutral-200 bg-white shadow-sm hover:bg-neutral-100 hover:text-neutral-900 dark:border-neutral-800 dark:bg-neutral-950 dark:hover:bg-neutral-800 dark:hover:text-neutral-50 h-9 px-4 py-2"
35+
onclick={() => {
36+
document.cookie = 'showNewDashboard=false; Path=/';
37+
window.location.reload();
38+
}}
39+
>
40+
Act as a regular user
41+
</button>
42+
<button
43+
class="inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-neutral-950 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 dark:focus-visible:ring-neutral-300 border border-neutral-200 bg-white shadow-sm hover:bg-neutral-100 hover:text-neutral-900 dark:border-neutral-800 dark:bg-neutral-950 dark:hover:bg-neutral-800 dark:hover:text-neutral-50 h-9 px-4 py-2"
44+
onclick={() => {
45+
document.cookie = 'showNewDashboard=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT';
46+
window.location.reload();
47+
}}
48+
>
49+
Clear cookie
50+
</button>
51+
</div>

examples/sveltekit-example/src/routes/examples/marketing-pages/[code]/+page.server.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { PageServerLoad } from './$types';
22
import { firstMarketingABTest, secondMarketingABTest } from '$lib/flags';
33
import { marketingFlags } from '$lib/precomputed-flags';
4-
import { generatePermutations } from 'flags/sveltekit';
4+
// import { generatePermutations } from 'flags/sveltekit';
55

66
// Use Vercel ISR:
77
export const config = {
@@ -22,8 +22,5 @@ export const load: PageServerLoad = async ({ params }) => {
2222
const flag1 = await firstMarketingABTest(params.code, marketingFlags);
2323
const flag2 = await secondMarketingABTest(params.code, marketingFlags);
2424

25-
return {
26-
first: `First flag evaluated to ${flag1}`,
27-
second: `Second flag evaluated to ${flag2}`
28-
};
25+
return { flag1, flag2 };
2926
};

examples/sveltekit-example/src/routes/examples/marketing-pages/[code]/+page.svelte

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,48 @@
44
let { data }: PageProps = $props();
55
</script>
66

7-
<p>{data.first}</p>
8-
<p>{data.second}</p>
7+
<div class="flex flex-col gap-2">
8+
{#if data.flag1}
9+
<div class="rounded-md bg-green-100 dark:bg-green-800">
10+
<div class="p-4 text-sm font-medium text-green-800 dark:text-green-100">
11+
The feature flag <span class="font-semibold">firstMarketingABTest</span> evaluated to
12+
<span class="font-semibold">true</span>.
13+
</div>
14+
</div>
15+
{:else}
16+
<div class="rounded-md bg-fuchsia-100 dark:bg-fuchsia-800">
17+
<div class="p-4 text-sm font-medium text-fuchsia-800 dark:text-fuchsia-100">
18+
The feature flag <span class="font-semibold">firstMarketingABTest</span> evaluated to
19+
<span class="font-semibold">false</span>.
20+
</div>
21+
</div>
22+
{/if}
923

10-
<div>
24+
{#if data.flag2}
25+
<div class="rounded-md bg-green-100 dark:bg-green-800">
26+
<div class="p-4 text-sm font-medium text-green-800 dark:text-green-100">
27+
The feature flag <span class="font-semibold">secondMarketingABTest</span> evaluated to
28+
<span class="font-semibold">true</span>.
29+
</div>
30+
</div>
31+
{:else}
32+
<div class="rounded-md bg-fuchsia-100 dark:bg-fuchsia-800">
33+
<div class="p-4 text-sm font-medium text-fuchsia-800 dark:text-fuchsia-100">
34+
The feature flag <span class="font-semibold">secondMarketingABTest</span> evaluated to
35+
<span class="font-semibold">false</span>.
36+
</div>
37+
</div>
38+
{/if}
39+
</div>
40+
41+
<div class="flex gap-2 pt-2">
1142
<button
43+
class="inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-neutral-950 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 dark:focus-visible:ring-neutral-300 border border-neutral-200 bg-white shadow-sm hover:bg-neutral-100 hover:text-neutral-900 dark:border-neutral-800 dark:bg-neutral-950 dark:hover:bg-neutral-800 dark:hover:text-neutral-50 h-9 px-4 py-2"
1244
onclick={() => {
1345
document.cookie = 'visitorId=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT';
1446
window.location.reload();
15-
}}>Reset cookie</button
16-
>
17-
<span
18-
>(will automatically assign a new visitor id, which depending on the value will opt you into the
19-
new marketing page)</span
47+
}}
2048
>
49+
Reset cookie
50+
</button>
2151
</div>
22-
23-
<style>
24-
div {
25-
max-width: 30rem;
26-
}
27-
</style>
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { sveltekit } from '@sveltejs/kit/vite';
22
import { defineConfig } from 'vite';
33
import { vercelToolbar } from '@vercel/toolbar/plugins/vite';
4+
import tailwindcss from '@tailwindcss/vite';
45

56
export default defineConfig({
6-
plugins: [sveltekit(), vercelToolbar()]
7+
plugins: [sveltekit(), vercelToolbar(), tailwindcss()]
78
});

0 commit comments

Comments
 (0)