Skip to content

Commit f4d14f7

Browse files
committed
feat: Add MediaQueryPresets
1 parent 3c3ccc4 commit f4d14f7

6 files changed

Lines changed: 176 additions & 1 deletion

File tree

.changeset/fancy-poets-lead.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@layerstack/svelte-state': patch
3+
---
4+
5+
feat: Add `MediaQueryPresets`
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export { MediaQueryPresets } from './mediaQueryPresets.svelte.js';
12
export { SelectionState } from './selectionState.svelte.js';
23
export { TimerState } from './timerState.svelte.js';
34
export { UniqueState } from './uniqueState.svelte.js';
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { MediaQuery } from 'svelte/reactivity';
2+
3+
export class MediaQueryPresets {
4+
width(width: number) {
5+
return new MediaQuery(`(min-width: ${width}px)`);
6+
}
7+
8+
height(height: number) {
9+
return new MediaQuery(`(min-height: ${height}px)`);
10+
}
11+
12+
// Matches tailwind defaults (https://tailwindcss.com/docs/responsive-design)
13+
smScreen = this.width(640);
14+
mdScreen = this.width(768);
15+
lgScreen = this.width(1024);
16+
xlScreen = this.width(1280);
17+
xxlScreen = this.width(1536);
18+
19+
screen = new MediaQuery('screen');
20+
print = new MediaQuery('print');
21+
22+
dark = new MediaQuery('(prefers-color-scheme: dark)');
23+
light = new MediaQuery('(prefers-color-scheme: light)');
24+
25+
motion = new MediaQuery('(prefers-reduced-motion: no-preference)');
26+
motionReduce = new MediaQuery('(prefers-reduced-motion: reduce)');
27+
28+
landscape = new MediaQuery('(orientation: landscape)');
29+
portrait = new MediaQuery('(orientation: portrait)');
30+
}

sites/docs/src/routes/_NavMenu.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
'styles',
2020
];
2121
22-
const state = ['SelectionState', 'TimerState', 'UniqueState'];
22+
const state = ['MediaQueryPresets', 'SelectionState', 'TimerState', 'UniqueState'];
2323
2424
const stores = [
2525
'changeStore',
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
<script lang="ts">
2+
import { MediaQuery } from 'svelte/reactivity';
3+
4+
import { Icon } from 'svelte-ux';
5+
import { MediaQueryPresets } from '@layerstack/svelte-state';
6+
import { mdiCheckCircle, mdiCloseCircle } from '@mdi/js';
7+
8+
import Code from '$docs/Code.svelte';
9+
import Preview from '$docs/Preview.svelte';
10+
11+
const {
12+
smScreen,
13+
mdScreen,
14+
lgScreen,
15+
xlScreen,
16+
xxlScreen,
17+
screen,
18+
print,
19+
dark,
20+
motion,
21+
motionReduce,
22+
} = new MediaQueryPresets();
23+
24+
let innerWidth = 0;
25+
</script>
26+
27+
<h1>Usage</h1>
28+
29+
<Code
30+
source={`<script>
31+
import { MediaQueryPresets } from '@layerstack/svelte-state';
32+
const { mdScreen, print} = new MediaQueryPresets();
33+
</script>
34+
35+
{#if mdScreen.current}
36+
<div>Only visible on 768px+ screens</div>
37+
{/if}
38+
39+
{#if print.current}
40+
<div>Only visable when printing</div>
41+
{/if}`}
42+
`}
43+
language="svelte"
44+
/>
45+
46+
<h1>Examples</h1>
47+
48+
<Preview>
49+
<div class="grid grid-cols-[auto_1fr] items-center gap-2">
50+
{#if smScreen.current}
51+
<Icon data={mdiCheckCircle} size="1rem" class="text-success" />
52+
{:else}
53+
<Icon data={mdiCloseCircle} size="1rem" class="text-danger" />
54+
{/if}
55+
smScreen (640px)
56+
57+
{#if mdScreen.current}
58+
<Icon data={mdiCheckCircle} size="1rem" class="text-success" />
59+
{:else}
60+
<Icon data={mdiCloseCircle} size="1rem" class="text-danger" />
61+
{/if}
62+
mdScreen (768px)
63+
64+
{#if lgScreen.current}
65+
<Icon data={mdiCheckCircle} size="1rem" class="text-success" />
66+
{:else}
67+
<Icon data={mdiCloseCircle} size="1rem" class="text-danger" />
68+
{/if}
69+
lgScreen (1024px)
70+
71+
{#if xlScreen.current}
72+
<Icon data={mdiCheckCircle} size="1rem" class="text-success" />
73+
{:else}
74+
<Icon data={mdiCloseCircle} size="1rem" class="text-danger" />
75+
{/if}
76+
xlScreen (1280px)
77+
78+
{#if xxlScreen.current}
79+
<Icon data={mdiCheckCircle} size="1rem" class="text-success" />
80+
{:else}
81+
<Icon data={mdiCloseCircle} size="1rem" class="text-danger" />
82+
{/if}
83+
xxlScreen (1536px)
84+
85+
{#if screen.current}
86+
<Icon data={mdiCheckCircle} size="1rem" class="text-success" />
87+
{:else}
88+
<Icon data={mdiCloseCircle} size="1rem" class="text-danger" />
89+
{/if}
90+
screen
91+
92+
{#if print.current}
93+
<Icon data={mdiCheckCircle} size="1rem" class="text-success" />
94+
{:else}
95+
<Icon data={mdiCloseCircle} size="1rem" class="text-danger" />
96+
{/if}
97+
print
98+
99+
{#if dark.current}
100+
<Icon data={mdiCheckCircle} size="1rem" class="text-success" />
101+
{:else}
102+
<Icon data={mdiCloseCircle} size="1rem" class="text-danger" />
103+
{/if}
104+
dark
105+
106+
{#if motion.current}
107+
<Icon data={mdiCheckCircle} size="1rem" class="text-success" />
108+
{:else}
109+
<Icon data={mdiCloseCircle} size="1rem" class="text-danger" />
110+
{/if}
111+
motion
112+
113+
{#if motionReduce.current}
114+
<Icon data={mdiCheckCircle} size="1rem" class="text-success" />
115+
{:else}
116+
<Icon data={mdiCloseCircle} size="1rem" class="text-danger" />
117+
{/if}
118+
motionReduce
119+
</div>
120+
121+
<div class="ml-6 mt-3 text-surface-content/50 text-xs">
122+
current width: {innerWidth}px
123+
</div>
124+
</Preview>
125+
126+
<svelte:window bind:innerWidth />
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import source from '$svelte-state/mediaQueryPresets.svelte.ts?raw';
2+
import pageSource from './+page.svelte?raw';
3+
4+
export async function load() {
5+
return {
6+
meta: {
7+
source,
8+
pageSource,
9+
description:
10+
'Presets to monitor media query matching, including screen width/height, orientation, print media, prefers dark/light scheme, and prefers reduced motion',
11+
},
12+
};
13+
}

0 commit comments

Comments
 (0)