File size: 3,390 Bytes
f264e07
 
 
 
 
 
 
 
 
 
 
 
 
41a6d75
f264e07
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41a6d75
f264e07
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41a6d75
 
 
f264e07
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
<!-- frontend/shared/TopBarPanel.svelte -->

<script lang="ts">
	import { createEventDispatcher, onMount } from "svelte";
	const dispatch = createEventDispatcher<{
		expand: void;
		collapse: void;
	}>();

	export let open = true;
	export let height: number | string;
	export let width: number | string;
	export let bring_to_front = false;
	export let rounded_borders = false;

	let mounted = false;
	let _open = false;

	let width_css = typeof width === "number" ? `${width}px` : width;
	let height_css = typeof height === "number" ? `${height}px` : height;
	let prefersReducedMotion: boolean;

	onMount(() => {
		mounted = true;
		const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
		prefersReducedMotion = mediaQuery.matches;

		const updateMotionPreference = (e: MediaQueryListEvent): void => {
			prefersReducedMotion = e.matches;
		};
		mediaQuery.addEventListener("change", updateMotionPreference);
		return () => {
			mediaQuery.removeEventListener("change", updateMotionPreference);
		};
	});

	$: if (mounted) _open = open;
</script>

<div
	class="top-bar"
	class:open={_open}
	class:reduce-motion={prefersReducedMotion}
	class:on-top={bring_to_front}
	class:rounded={rounded_borders}
	style="height: {height_css}; width: {width_css};"
>
	<button
		on:click={() => {
			_open = !_open;
			open = _open;
			if (_open) {
				dispatch("expand");
			} else {
				dispatch("collapse");
			}
		}}
		class="toggle-top-button"
		aria-label="Toggle Top Bar"
	>
		<div class="chevron">
			<span class="chevron-arrow"></span>
		</div>
	</button>
	<div class="bar-content">
		<slot />
	</div>
</div>

<style>
	.top-bar {
		display: flex;
		flex-direction: column;
		position: fixed;
		top: 0;
		left: 50%;
		background-color: var(--background-fill-secondary);
		transform: translateX(-50%) translateY(-100%);
		z-index: 1000;
		border-bottom: 1px solid var(--border-color-primary);
		box-shadow: 0 2px 5px rgba(0,0,0,0.05);
	}
	.top-bar.rounded {		
		border-radius: 0 0 var(--radius-sm) var(--radius-sm);
	}
	.top-bar.on-top {
		z-index: 2000;
	}

	.top-bar:not(.reduce-motion) {
		transition: transform 0.3s ease-in-out;
	}

	.top-bar.open {
		transform: translateX(-50%) translateY(0);
	}

	.toggle-top-button {
		position: absolute;
		bottom: 0;
		left: 50%;
		transform: translate(-50%, 100%);
		background: var(--background-fill-secondary);
		border: 1px solid var(--border-color-primary);
		border-top: none;
		cursor: pointer;
		padding: var(--size-2);
		display: flex;
		align-items: center;
		justify-content: center;
		width: var(--size-10);
		height: var(--size-6);
		z-index: inherit;
		border-radius: 0 0 var(--radius-lg) var(--radius-lg);
	}

	.toggle-top-button:not(.reduce-motion) {
		transition: all 0.3s ease-in-out;
	}

	.chevron {
		position: relative;
		display: block;
		width: var(--size-3);
		height: var(--size-3);
	}

	.chevron-arrow {
		position: absolute;
		box-sizing: border-box;
		top: 10%;
		left: 18%;
		width: 80%;
		height: 80%;
		border-bottom: var(--size-0-5) solid var(--body-text-color);
		border-right: var(--size-0-5) solid var(--body-text-color);
		transform: rotate(45deg);
	}

	.top-bar:not(.reduce-motion) .chevron-arrow {
		transition: transform 0.3s ease-in-out;
	}

	.top-bar.open .chevron-arrow {
		transform: rotate(-135deg);
	}

	.bar-content {
		padding: var(--size-4);
		overflow-y: auto;
		flex-grow: 1;
	}
</style>