Give the website the app's Material 3 look
The site's tokens now carry the app's --md-sys-* names, with shape, elevation, motion, state, type and spacing values copied from Livewire Material 2.1 and the colours from the indigo profile, including its high-contrast light and dark values for prefers-contrast: more. Cards are outlined, the gallery uses a connected button group instead of segmented buttons, buttons use M3 Expressive sizes, state layers and pressed shapes, and layouts follow the M3 window classes with logical properties. A Light/Dark/System toggle in the nav sets data-theme before the first paint, and no text is dimmed with opacity. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
1bcb868897
commit
7ffc1c1ead
@@ -6,4 +6,4 @@ paths:
|
||||
# Website
|
||||
|
||||
## website/ is the live site, uploaded by hand
|
||||
website/ is a faithful copy of sealshare.nonameweb.ch (METANET hosting), hand-written HTML/CSS with no build step, uploaded wholesale when it changes. Colours in css/theme.css are copied from the indigo profile in resources/css/material-scheme.json: the standard light and dark values (profiles.indigo.light/dark) and the high-contrast light and dark values (profiles.indigo.contrast.high) — copy them again if indigo is regenerated differently; the site does not follow the admin's colour profile. The comparison tables are dated and every competitor value has a source from the product's own site, docs or repo; an unsourced value is "—", never a guess. Never call SealShare's encryption end-to-end (files are encrypted in the browser with a key the server issues, and the server decrypts them for downloads). Nothing may load from another host except plausible.io. tests/Feature/WebsiteTest.php guards all of this.
|
||||
website/ is a faithful copy of sealshare.nonameweb.ch (METANET hosting), hand-written HTML/CSS with no build step, uploaded wholesale when it changes. Colours in css/theme.css are copied from the indigo profile in resources/css/material-scheme.json: the standard light and dark values (profiles.indigo.light/dark) and the high-contrast light and dark values (profiles.indigo.contrast.high) — copy them again if indigo is regenerated differently; the site does not follow the admin's colour profile. Light or dark is <html data-theme>, written before the first paint by each page's inline head script from the nav's Light/Dark/System toggle (localStorage sealshare-website-theme); the high-contrast values apply under prefers-contrast: more. The comparison tables are dated and every competitor value has a source from the product's own site, docs or repo; an unsourced value is "—", never a guess. Never call SealShare's encryption end-to-end (files are encrypted in the browser with a key the server issues, and the server decrypts them for downloads). Nothing may load from another host except plausible.io. tests/Feature/WebsiteTest.php guards all of this.
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
* Pro viewport). The screen keeps the capture's aspect ratio, so the frame holds its shape while an
|
||||
* image loads. The screenshots come from `composer screenshots` (tests/Screenshots/).
|
||||
*
|
||||
* The bezels and the deck are hardware, drawn in fixed tints of their own; what shows through the
|
||||
* screen before an image paints and the shadow under a device are colour roles from theme.css, which
|
||||
* must be loaded first. Dark follows <html data-theme>, and the system setting without JavaScript.
|
||||
*
|
||||
* <div class="device device--laptop">
|
||||
* <div class="device__screen"><picture>…<img …></picture></div>
|
||||
* </div>
|
||||
@@ -14,13 +18,21 @@
|
||||
--bezel-edge: #3a3355;
|
||||
--deck: #c9c2dd;
|
||||
--deck-shadow: #8f88a8;
|
||||
--device-shadow: color-mix(in srgb, var(--md-sys-color-shadow) 40%, transparent);
|
||||
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:root[data-theme="dark"] .device {
|
||||
--bezel: #05020f;
|
||||
--bezel-edge: #2a2244;
|
||||
--deck: #4b426a;
|
||||
--deck-shadow: #231649;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.device {
|
||||
:root:not([data-theme]) .device {
|
||||
--bezel: #05020f;
|
||||
--bezel-edge: #2a2244;
|
||||
--deck: #4b426a;
|
||||
@@ -31,7 +43,7 @@
|
||||
.device__screen {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background: var(--surface-container-high, #e8deff);
|
||||
background-color: var(--md-sys-color-surface-container-high);
|
||||
}
|
||||
|
||||
.device__screen img {
|
||||
@@ -54,7 +66,7 @@
|
||||
padding: 2.4% 2.4% 3%;
|
||||
border-radius: 3.2% 3.2% 0 0 / 4.8% 4.8% 0 0;
|
||||
background: var(--bezel);
|
||||
box-shadow: inset 0 0 0 1px var(--bezel-edge), 0 24px 48px -24px rgb(16 6 45 / 0.45);
|
||||
box-shadow: inset 0 0 0 1px var(--bezel-edge), 0 24px 48px -24px var(--device-shadow);
|
||||
}
|
||||
|
||||
.device--laptop .device__screen {
|
||||
@@ -79,8 +91,7 @@
|
||||
.device--laptop::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -4%;
|
||||
right: -4%;
|
||||
inset-inline: -4%;
|
||||
bottom: 0;
|
||||
height: 3.2%;
|
||||
border-radius: 0 0 40% 40% / 0 0 100% 100%;
|
||||
@@ -95,7 +106,7 @@
|
||||
z-index: 1;
|
||||
width: 14%;
|
||||
height: 1.4%;
|
||||
border-radius: 0 0 12px 12px;
|
||||
border-radius: 0 0 var(--md-sys-shape-corner-md) var(--md-sys-shape-corner-md);
|
||||
background: var(--deck-shadow);
|
||||
translate: -50% 0;
|
||||
}
|
||||
@@ -106,7 +117,7 @@
|
||||
padding: 3.4%;
|
||||
border-radius: 15% / 7%;
|
||||
background: var(--bezel);
|
||||
box-shadow: inset 0 0 0 2px var(--bezel-edge), 0 24px 48px -20px rgb(16 6 45 / 0.5);
|
||||
box-shadow: inset 0 0 0 2px var(--bezel-edge), 0 24px 48px -20px var(--device-shadow);
|
||||
}
|
||||
|
||||
.device--phone .device__screen {
|
||||
|
||||
+914
-621
File diff suppressed because it is too large
Load Diff
+147
-27
@@ -7,6 +7,83 @@
|
||||
<meta name="description" content="SealShare is self-hosted file sharing: your company's own upload platform to exchange files with customers, encrypted at rest, on your own server and domain. Open source, one Docker image.">
|
||||
<meta name="theme-color" content="#faf4ff" media="(prefers-color-scheme: light)">
|
||||
<meta name="theme-color" content="#10062d" media="(prefers-color-scheme: dark)">
|
||||
<script>
|
||||
// Light, Dark or System, decided before the first paint: the visitor's choice in the nav, kept in
|
||||
// localStorage, else the system's. css/theme.css keys on <html data-theme>.
|
||||
(function () {
|
||||
var root = document.documentElement;
|
||||
var key = 'sealshare-website-theme';
|
||||
var choices = ['light', 'dark', 'system'];
|
||||
var surfaces = { light: '#faf4ff', dark: '#10062d' };
|
||||
var system = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
var choice = 'system';
|
||||
|
||||
try {
|
||||
var stored = localStorage.getItem(key);
|
||||
|
||||
if (choices.indexOf(stored) !== -1) {
|
||||
choice = stored;
|
||||
}
|
||||
} catch (error) {
|
||||
// Storage is blocked: follow the system.
|
||||
}
|
||||
|
||||
// A <picture>'s dark source (data-theme-dark) follows the site's theme instead of the system's.
|
||||
var sources = function () {
|
||||
document.querySelectorAll('source[data-theme-dark]').forEach(function (source) {
|
||||
source.media = root.dataset.theme === 'dark' ? 'all' : 'not all';
|
||||
});
|
||||
};
|
||||
|
||||
var apply = function () {
|
||||
var theme = choice === 'system' ? (system.matches ? 'dark' : 'light') : choice;
|
||||
|
||||
root.dataset.themeChoice = choice;
|
||||
root.dataset.theme = theme;
|
||||
|
||||
document.querySelectorAll('meta[name="theme-color"]').forEach(function (meta) {
|
||||
meta.removeAttribute('media');
|
||||
meta.setAttribute('content', surfaces[theme]);
|
||||
});
|
||||
|
||||
sources();
|
||||
document.dispatchEvent(new CustomEvent('sealshare:theme', { detail: { choice: choice, theme: theme } }));
|
||||
};
|
||||
|
||||
window.sealshareTheme = {
|
||||
sources: sources,
|
||||
get choice() {
|
||||
return choice;
|
||||
},
|
||||
get theme() {
|
||||
return root.dataset.theme;
|
||||
},
|
||||
set: function (next) {
|
||||
if (choices.indexOf(next) === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
choice = next;
|
||||
|
||||
try {
|
||||
localStorage.setItem(key, next);
|
||||
} catch (error) {
|
||||
// Storage is blocked: the page still switches, it just will not remember.
|
||||
}
|
||||
|
||||
apply();
|
||||
},
|
||||
};
|
||||
|
||||
system.addEventListener('change', function () {
|
||||
if (choice === 'system') {
|
||||
apply();
|
||||
}
|
||||
});
|
||||
|
||||
apply();
|
||||
})();
|
||||
</script>
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="https://sealshare.nonameweb.ch/">
|
||||
<meta property="og:title" content="SealShare — your own secure upload platform">
|
||||
@@ -25,7 +102,7 @@
|
||||
<link rel="stylesheet" href="css/device-frame.css">
|
||||
</head>
|
||||
<body id="top">
|
||||
<a class="skip-link" href="#main">Skip to content</a>
|
||||
<a class="skip-link btn btn--filled" href="#main">Skip to content</a>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="sprite" aria-hidden="true">
|
||||
<symbol id="i-cloud-upload" viewBox="0 -960 960 960"><path d="m440-446-36 35q-11 11-27.5 11T348-412q-11-11-11-28t11-28l104-104q12-12 28-12t28 12l104 104q11 11 11.5 27.5T612-412q-11 11-27.5 11.5T556-411l-36-35v206h220q42 0 71-29t29-71q0-42-29-71t-71-29h-60v-80q0-83-58.5-141.5T480-720q-83 0-141.5 58.5T280-520h-20q-58 0-99 41t-41 99q0 58 41 99t99 41h60q17 0 28.5 11.5T360-200q0 17-11.5 28.5T320-160h-60q-91 0-155.5-63T40-377q0-78 47-139t123-78q25-92 100-149t170-57q117 0 198.5 81.5T760-520q69 8 114.5 59.5T920-340q0 75-52.5 127.5T740-160H520q-33 0-56.5-23.5T440-240v-206Zm40 6Z"/></symbol>
|
||||
@@ -64,12 +141,15 @@
|
||||
<symbol id="s-sunny" viewBox="0 0 100 100"><path d="M98 50C98 51.7 97.4 53.5 96.2 54.9C93.7 57.8 91.3 60.7 88.8 63.6C87.8 64.8 87.2 66.3 87 67.9C86.7 71.6 86.4 75.4 86.1 79.2C85.8 82.9 82.9 85.8 79.2 86.1C75.4 86.4 71.6 86.7 67.9 87C66.3 87.2 64.8 87.8 63.6 88.8C60.7 91.3 57.8 93.7 54.9 96.2C52.1 98.6 47.9 98.6 45.1 96.2C42.2 93.7 39.3 91.3 36.4 88.8C35.2 87.8 33.7 87.2 32.1 87C28.4 86.7 24.6 86.4 20.8 86.1C17.1 85.8 14.2 82.9 13.9 79.2C13.6 75.4 13.3 71.6 13 67.9C12.8 66.3 12.2 64.8 11.2 63.6C8.7 60.7 6.3 57.8 3.8 54.9C1.4 52.1 1.4 47.9 3.8 45.1C6.3 42.2 8.7 39.3 11.2 36.4C12.2 35.2 12.8 33.7 13 32.1C13.3 28.4 13.6 24.6 13.9 20.8C14.2 17.1 17.1 14.2 20.8 13.9C24.6 13.6 28.4 13.3 32.1 13C33.7 12.8 35.2 12.2 36.4 11.2C39.3 8.7 42.2 6.3 45.1 3.8C47.9 1.4 52.1 1.4 54.9 3.8C57.8 6.3 60.7 8.7 63.6 11.2C64.8 12.2 66.3 12.8 67.9 13C71.6 13.3 75.4 13.6 79.2 13.9C82.9 14.2 85.8 17.1 86.1 20.8C86.4 24.6 86.7 28.4 87 32.1C87.2 33.7 87.8 35.2 88.8 36.4C91.3 39.3 93.7 42.2 96.2 45.1C97.4 46.5 98 48.3 98 50Z"/></symbol>
|
||||
<symbol id="s-cookie-6" viewBox="0 0 100 100"><path d="M71.8 87.5C70.1 88.5 68.5 89.7 67.1 91C67 91.1 67 91.1 66.9 91.2C62.2 95.7 56.1 98 50 98C43.9 98 37.8 95.7 33.1 91.2C30.3 88.4 26.8 86.4 23 85.3C22.9 85.3 22.9 85.3 22.8 85.3C10.2 81.6 2.7 68.7 5.9 55.9C6.9 52.1 6.9 48.1 5.9 44.3C5.9 44.2 5.9 44.1 5.9 44.1C2.7 31.3 10.2 18.4 22.8 14.8C26.6 13.7 30.1 11.7 32.9 9C33 8.9 33 8.9 33.1 8.8C37.8 4.3 43.9 2 50 2C56.1 2 62.2 4.3 66.9 8.8C69.7 11.6 73.2 13.6 77 14.7C77.1 14.7 77.1 14.7 77.2 14.7C89.8 18.4 97.3 31.3 94.1 44.1C93.1 47.9 93.1 51.9 94.1 55.7C94.1 55.8 94.1 55.9 94.1 55.9C97.3 68.7 89.8 81.6 77.2 85.2C75.3 85.8 73.5 86.5 71.8 87.5Z"/></symbol>
|
||||
<symbol id="s-gem" viewBox="0 0 100 100"><path d="M49.9 98C49.2 98 48.4 98 47.6 97.9C43.8 97.5 40.2 95.8 32.9 92.5C26.9 89.8 21 87 15.1 84.3C7 80.6 2.4 72.1 3.7 63.3C5 54.2 6.3 45.1 7.7 36C8.5 30.1 11.7 24.8 16.6 21.4C23.8 16.2 31 11 38.3 5.8C41.7 3.3 45.9 2 50.1 2C54.4 2 58.5 3.4 61.9 5.8C69.2 11.1 76.4 16.3 83.6 21.5C88.4 25 91.6 30.3 92.5 36.2C93.8 45.3 95.1 54.4 96.3 63.5C97.6 72.2 92.9 80.8 84.8 84.5C78.9 87.2 73 89.8 67 92.5C59.7 95.9 56.1 97.5 52.3 97.9C51.5 98 50.7 98 49.9 98Z"/></symbol>
|
||||
<symbol id="i-light-mode" viewBox="0 -960 960 960"><path d="M480-360q50 0 85-35t35-85q0-50-35-85t-85-35q-50 0-85 35t-35 85q0 50 35 85t85 35Zm0 80q-83 0-141.5-58.5T280-480q0-83 58.5-141.5T480-680q83 0 141.5 58.5T680-480q0 83-58.5 141.5T480-280ZM80-440q-17 0-28.5-11.5T40-480q0-17 11.5-28.5T80-520h80q17 0 28.5 11.5T200-480q0 17-11.5 28.5T160-440H80Zm720 0q-17 0-28.5-11.5T760-480q0-17 11.5-28.5T800-520h80q17 0 28.5 11.5T920-480q0 17-11.5 28.5T880-440h-80ZM480-760q-17 0-28.5-11.5T440-800v-80q0-17 11.5-28.5T480-920q17 0 28.5 11.5T520-880v80q0 17-11.5 28.5T480-760Zm0 720q-17 0-28.5-11.5T440-80v-80q0-17 11.5-28.5T480-200q17 0 28.5 11.5T520-160v80q0 17-11.5 28.5T480-40ZM226-678l-43-42q-12-11-11.5-28t11.5-29q12-12 29-12t28 12l42 43q11 12 11 28t-11 28q-11 12-27.5 11.5T226-678Zm494 495-42-43q-11-12-11-28.5t11-27.5q11-12 27.5-11.5T734-282l43 42q12 11 11.5 28T777-183q-12 12-29 12t-28-12Zm-42-495q-12-11-11.5-27.5T678-734l42-43q11-12 28-11.5t29 11.5q12 12 12 29t-12 28l-43 42q-12 11-28 11t-28-11ZM183-183q-12-12-12-29t12-28l43-42q12-11 28.5-11t27.5 11q12 11 11.5 27.5T282-226l-42 43q-11 12-28 11.5T183-183Zm297-297Z"/></symbol>
|
||||
<symbol id="i-dark-mode" viewBox="0 -960 960 960"><path d="M480-120q-151 0-255.5-104.5T120-480q0-138 90-239.5T440-838q13-2 23 3.5t16 14.5q6 9 6.5 21t-7.5 23q-17 26-25.5 55t-8.5 61q0 90 63 153t153 63q31 0 61.5-9t54.5-25q11-7 22.5-6.5T819-479q10 5 15.5 15t3.5 24q-14 138-117.5 229T480-120Zm0-80q88 0 158-48.5T740-375q-20 5-40 8t-40 3q-123 0-209.5-86.5T364-660q0-20 3-40t8-40q-78 32-126.5 102T200-480q0 116 82 198t198 82Zm-10-270Z"/></symbol>
|
||||
<symbol id="i-brightness-auto" viewBox="0 -960 960 960"><path d="M408-412h146l25 73q3 8 10.5 13.5T606-320q15 0 23.5-12.5T633-359L519-661q-3-9-11-14t-17-5h-22q-9 0-17 5t-11 14L327-360q-5 14 3.5 27t24.5 13q10 0 17.5-5.5T383-340l25-72Zm18-52 52-150h4l52 150H426Zm-80 304H240q-33 0-56.5-23.5T160-240v-106l-77-78q-11-12-17-26.5T60-480q0-15 6-29.5T83-536l77-78v-106q0-33 23.5-56.5T240-800h106l78-77q12-11 26.5-17t29.5-6q15 0 29.5 6t26.5 17l78 77h106q33 0 56.5 23.5T800-720v106l77 78q11 12 17 26.5t6 29.5q0 15-6 29.5T877-424l-77 78v106q0 33-23.5 56.5T720-160H614l-78 77q-12 11-26.5 17T480-60q-15 0-29.5-6T424-83l-78-77Zm34-80 100 100 100-100h140v-140l100-100-100-100v-140H580L480-820 380-720H240v140L140-480l100 100v140h140Zm100-240Z"/></symbol>
|
||||
</svg>
|
||||
|
||||
<header class="nav">
|
||||
<div class="container nav__bar">
|
||||
<a class="brand" href="#top"><svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M6 2h8l6 6v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2Z" stroke="currentColor" stroke-width="1.5"/><path d="M14 2v5a1 1 0 0 0 1 1h5" stroke="currentColor" stroke-width="1.5"/><path d="M12 17v-6m0 0-2.5 2.5M12 11l2.5 2.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg><span>SealShare</span></a>
|
||||
<button class="nav__toggle" id="navToggle" type="button" aria-expanded="false" aria-controls="navLinks" aria-label="Menu">
|
||||
<button class="icon-btn nav__toggle" id="navToggle" type="button" aria-expanded="false" aria-controls="navLinks" aria-label="Menu">
|
||||
<svg class="icon icon-menu" aria-hidden="true"><use href="#i-menu"/></svg>
|
||||
<svg class="icon icon-close" aria-hidden="true"><use href="#i-close"/></svg>
|
||||
</button>
|
||||
@@ -84,6 +164,11 @@
|
||||
<li><a class="btn btn--filled" href="https://gitea.nonameweb.ch/noNameWEB/SealShare"><svg class="icon" aria-hidden="true"><use href="#i-open-in-new"/></svg>Gitea</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<button class="icon-btn theme-toggle" id="themeToggle" type="button" aria-label="Theme: System">
|
||||
<svg class="icon icon-light-mode" aria-hidden="true"><use href="#i-light-mode"/></svg>
|
||||
<svg class="icon icon-dark-mode" aria-hidden="true"><use href="#i-dark-mode"/></svg>
|
||||
<svg class="icon icon-brightness-auto" aria-hidden="true"><use href="#i-brightness-auto"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -112,8 +197,9 @@
|
||||
<div class="device__lid">
|
||||
<div class="device__screen">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="img/screenshots/desktop/dark/01-upload-1600.webp 1600w, img/screenshots/desktop/dark/01-upload-800.webp 800w" sizes="(max-width: 960px) 94vw, 58vw">
|
||||
<img src="img/screenshots/desktop/light/01-upload-800.webp" srcset="img/screenshots/desktop/light/01-upload-1600.webp 1600w, img/screenshots/desktop/light/01-upload-800.webp 800w" sizes="(max-width: 960px) 94vw, 58vw"
|
||||
<source data-theme-dark media="(prefers-color-scheme: dark)" srcset="img/screenshots/desktop/dark/01-upload-1600.webp 1600w, img/screenshots/desktop/dark/01-upload-800.webp 800w" sizes="(max-width: 839px) 94vw, 58vw">
|
||||
<script>sealshareTheme.sources()</script>
|
||||
<img src="img/screenshots/desktop/light/01-upload-800.webp" srcset="img/screenshots/desktop/light/01-upload-1600.webp 1600w, img/screenshots/desktop/light/01-upload-800.webp 800w" sizes="(max-width: 839px) 94vw, 58vw"
|
||||
width="1512" height="982" loading="eager" decoding="async"
|
||||
alt="SealShare's upload page with files selected and a generated password in the share options">
|
||||
</picture>
|
||||
@@ -123,8 +209,9 @@
|
||||
<div class="device device--phone">
|
||||
<div class="device__screen">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="img/screenshots/phone/dark/03-download-1080.webp 1080w, img/screenshots/phone/dark/03-download-540.webp 540w" sizes="(max-width: 960px) 24vw, 15vw">
|
||||
<img src="img/screenshots/phone/light/03-download-540.webp" srcset="img/screenshots/phone/light/03-download-1080.webp 1080w, img/screenshots/phone/light/03-download-540.webp 540w" sizes="(max-width: 960px) 24vw, 15vw"
|
||||
<source data-theme-dark media="(prefers-color-scheme: dark)" srcset="img/screenshots/phone/dark/03-download-1080.webp 1080w, img/screenshots/phone/dark/03-download-540.webp 540w" sizes="(max-width: 839px) 24vw, 15vw">
|
||||
<script>sealshareTheme.sources()</script>
|
||||
<img src="img/screenshots/phone/light/03-download-540.webp" srcset="img/screenshots/phone/light/03-download-1080.webp 1080w, img/screenshots/phone/light/03-download-540.webp 540w" sizes="(max-width: 839px) 24vw, 15vw"
|
||||
width="393" height="852" loading="eager" decoding="async"
|
||||
alt="The download page on a phone">
|
||||
</picture>
|
||||
@@ -286,13 +373,13 @@
|
||||
<p class="lede">The same interface on a laptop and a phone, in light or dark.</p>
|
||||
</div>
|
||||
<div class="gallery__controls">
|
||||
<div class="segmented" role="group" aria-label="Device">
|
||||
<button type="button" data-gallery-device="desktop" aria-pressed="true"><svg class="icon" aria-hidden="true"><use href="#i-check"/></svg>Desktop</button>
|
||||
<button type="button" data-gallery-device="phone" aria-pressed="false"><svg class="icon" aria-hidden="true"><use href="#i-check"/></svg>Phone</button>
|
||||
<div class="button-group" role="group" aria-label="Device">
|
||||
<button class="btn" type="button" data-gallery-device="desktop" aria-pressed="true"><svg class="icon" aria-hidden="true"><use href="#i-check"/></svg>Desktop</button>
|
||||
<button class="btn" type="button" data-gallery-device="phone" aria-pressed="false"><svg class="icon" aria-hidden="true"><use href="#i-check"/></svg>Phone</button>
|
||||
</div>
|
||||
<div class="segmented" role="group" aria-label="Theme">
|
||||
<button type="button" data-gallery-theme="light" aria-pressed="true"><svg class="icon" aria-hidden="true"><use href="#i-check"/></svg>Light</button>
|
||||
<button type="button" data-gallery-theme="dark" aria-pressed="false"><svg class="icon" aria-hidden="true"><use href="#i-check"/></svg>Dark</button>
|
||||
<div class="button-group" role="group" aria-label="Theme">
|
||||
<button class="btn" type="button" data-gallery-theme="light" aria-pressed="true"><svg class="icon" aria-hidden="true"><use href="#i-check"/></svg>Light</button>
|
||||
<button class="btn" type="button" data-gallery-theme="dark" aria-pressed="false"><svg class="icon" aria-hidden="true"><use href="#i-check"/></svg>Dark</button>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="gallery gallery--desktop" data-gallery="desktop">
|
||||
@@ -301,7 +388,7 @@
|
||||
<div class="device device--laptop">
|
||||
<div class="device__lid">
|
||||
<div class="device__screen">
|
||||
<img src="img/screenshots/desktop/light/01-upload-800.webp" srcset="img/screenshots/desktop/light/01-upload-1600.webp 1600w, img/screenshots/desktop/light/01-upload-800.webp 800w" sizes="(max-width: 840px) 94vw, 568px"
|
||||
<img src="img/screenshots/desktop/light/01-upload-800.webp" srcset="img/screenshots/desktop/light/01-upload-1600.webp 1600w, img/screenshots/desktop/light/01-upload-800.webp 800w" sizes="(max-width: 839px) 94vw, 568px"
|
||||
data-light-src="img/screenshots/desktop/light/01-upload-800.webp" data-light-srcset="img/screenshots/desktop/light/01-upload-1600.webp 1600w, img/screenshots/desktop/light/01-upload-800.webp 800w"
|
||||
data-dark-src="img/screenshots/desktop/dark/01-upload-800.webp" data-dark-srcset="img/screenshots/desktop/dark/01-upload-1600.webp 1600w, img/screenshots/desktop/dark/01-upload-800.webp 800w"
|
||||
width="1512" height="982" loading="lazy" decoding="async"
|
||||
@@ -317,7 +404,7 @@
|
||||
<div class="device device--laptop">
|
||||
<div class="device__lid">
|
||||
<div class="device__screen">
|
||||
<img src="img/screenshots/desktop/light/02-share-created-800.webp" srcset="img/screenshots/desktop/light/02-share-created-1600.webp 1600w, img/screenshots/desktop/light/02-share-created-800.webp 800w" sizes="(max-width: 840px) 94vw, 568px"
|
||||
<img src="img/screenshots/desktop/light/02-share-created-800.webp" srcset="img/screenshots/desktop/light/02-share-created-1600.webp 1600w, img/screenshots/desktop/light/02-share-created-800.webp 800w" sizes="(max-width: 839px) 94vw, 568px"
|
||||
data-light-src="img/screenshots/desktop/light/02-share-created-800.webp" data-light-srcset="img/screenshots/desktop/light/02-share-created-1600.webp 1600w, img/screenshots/desktop/light/02-share-created-800.webp 800w"
|
||||
data-dark-src="img/screenshots/desktop/dark/02-share-created-800.webp" data-dark-srcset="img/screenshots/desktop/dark/02-share-created-1600.webp 1600w, img/screenshots/desktop/dark/02-share-created-800.webp 800w"
|
||||
width="1512" height="982" loading="lazy" decoding="async"
|
||||
@@ -333,7 +420,7 @@
|
||||
<div class="device device--laptop">
|
||||
<div class="device__lid">
|
||||
<div class="device__screen">
|
||||
<img src="img/screenshots/desktop/light/03-qr-code-800.webp" srcset="img/screenshots/desktop/light/03-qr-code-1600.webp 1600w, img/screenshots/desktop/light/03-qr-code-800.webp 800w" sizes="(max-width: 840px) 94vw, 568px"
|
||||
<img src="img/screenshots/desktop/light/03-qr-code-800.webp" srcset="img/screenshots/desktop/light/03-qr-code-1600.webp 1600w, img/screenshots/desktop/light/03-qr-code-800.webp 800w" sizes="(max-width: 839px) 94vw, 568px"
|
||||
data-light-src="img/screenshots/desktop/light/03-qr-code-800.webp" data-light-srcset="img/screenshots/desktop/light/03-qr-code-1600.webp 1600w, img/screenshots/desktop/light/03-qr-code-800.webp 800w"
|
||||
data-dark-src="img/screenshots/desktop/dark/03-qr-code-800.webp" data-dark-srcset="img/screenshots/desktop/dark/03-qr-code-1600.webp 1600w, img/screenshots/desktop/dark/03-qr-code-800.webp 800w"
|
||||
width="1512" height="982" loading="lazy" decoding="async"
|
||||
@@ -349,7 +436,7 @@
|
||||
<div class="device device--laptop">
|
||||
<div class="device__lid">
|
||||
<div class="device__screen">
|
||||
<img src="img/screenshots/desktop/light/04-download-800.webp" srcset="img/screenshots/desktop/light/04-download-1600.webp 1600w, img/screenshots/desktop/light/04-download-800.webp 800w" sizes="(max-width: 840px) 94vw, 568px"
|
||||
<img src="img/screenshots/desktop/light/04-download-800.webp" srcset="img/screenshots/desktop/light/04-download-1600.webp 1600w, img/screenshots/desktop/light/04-download-800.webp 800w" sizes="(max-width: 839px) 94vw, 568px"
|
||||
data-light-src="img/screenshots/desktop/light/04-download-800.webp" data-light-srcset="img/screenshots/desktop/light/04-download-1600.webp 1600w, img/screenshots/desktop/light/04-download-800.webp 800w"
|
||||
data-dark-src="img/screenshots/desktop/dark/04-download-800.webp" data-dark-srcset="img/screenshots/desktop/dark/04-download-1600.webp 1600w, img/screenshots/desktop/dark/04-download-800.webp 800w"
|
||||
width="1512" height="982" loading="lazy" decoding="async"
|
||||
@@ -365,7 +452,7 @@
|
||||
<div class="device device--laptop">
|
||||
<div class="device__lid">
|
||||
<div class="device__screen">
|
||||
<img src="img/screenshots/desktop/light/05-admin-dashboard-800.webp" srcset="img/screenshots/desktop/light/05-admin-dashboard-1600.webp 1600w, img/screenshots/desktop/light/05-admin-dashboard-800.webp 800w" sizes="(max-width: 840px) 94vw, 568px"
|
||||
<img src="img/screenshots/desktop/light/05-admin-dashboard-800.webp" srcset="img/screenshots/desktop/light/05-admin-dashboard-1600.webp 1600w, img/screenshots/desktop/light/05-admin-dashboard-800.webp 800w" sizes="(max-width: 839px) 94vw, 568px"
|
||||
data-light-src="img/screenshots/desktop/light/05-admin-dashboard-800.webp" data-light-srcset="img/screenshots/desktop/light/05-admin-dashboard-1600.webp 1600w, img/screenshots/desktop/light/05-admin-dashboard-800.webp 800w"
|
||||
data-dark-src="img/screenshots/desktop/dark/05-admin-dashboard-800.webp" data-dark-srcset="img/screenshots/desktop/dark/05-admin-dashboard-1600.webp 1600w, img/screenshots/desktop/dark/05-admin-dashboard-800.webp 800w"
|
||||
width="1512" height="982" loading="lazy" decoding="async"
|
||||
@@ -381,7 +468,7 @@
|
||||
<div class="device device--laptop">
|
||||
<div class="device__lid">
|
||||
<div class="device__screen">
|
||||
<img src="img/screenshots/desktop/light/06-admin-settings-800.webp" srcset="img/screenshots/desktop/light/06-admin-settings-1600.webp 1600w, img/screenshots/desktop/light/06-admin-settings-800.webp 800w" sizes="(max-width: 840px) 94vw, 568px"
|
||||
<img src="img/screenshots/desktop/light/06-admin-settings-800.webp" srcset="img/screenshots/desktop/light/06-admin-settings-1600.webp 1600w, img/screenshots/desktop/light/06-admin-settings-800.webp 800w" sizes="(max-width: 839px) 94vw, 568px"
|
||||
data-light-src="img/screenshots/desktop/light/06-admin-settings-800.webp" data-light-srcset="img/screenshots/desktop/light/06-admin-settings-1600.webp 1600w, img/screenshots/desktop/light/06-admin-settings-800.webp 800w"
|
||||
data-dark-src="img/screenshots/desktop/dark/06-admin-settings-800.webp" data-dark-srcset="img/screenshots/desktop/dark/06-admin-settings-1600.webp 1600w, img/screenshots/desktop/dark/06-admin-settings-800.webp 800w"
|
||||
width="1512" height="982" loading="lazy" decoding="async"
|
||||
@@ -398,7 +485,7 @@
|
||||
<figure class="shot">
|
||||
<div class="device device--phone">
|
||||
<div class="device__screen">
|
||||
<img src="img/screenshots/phone/light/01-upload-540.webp" srcset="img/screenshots/phone/light/01-upload-1080.webp 1080w, img/screenshots/phone/light/01-upload-540.webp 540w" sizes="(max-width: 840px) 44vw, 232px"
|
||||
<img src="img/screenshots/phone/light/01-upload-540.webp" srcset="img/screenshots/phone/light/01-upload-1080.webp 1080w, img/screenshots/phone/light/01-upload-540.webp 540w" sizes="(max-width: 839px) 44vw, 232px"
|
||||
data-light-src="img/screenshots/phone/light/01-upload-540.webp" data-light-srcset="img/screenshots/phone/light/01-upload-1080.webp 1080w, img/screenshots/phone/light/01-upload-540.webp 540w"
|
||||
data-dark-src="img/screenshots/phone/dark/01-upload-540.webp" data-dark-srcset="img/screenshots/phone/dark/01-upload-1080.webp 1080w, img/screenshots/phone/dark/01-upload-540.webp 540w"
|
||||
width="393" height="852" loading="lazy" decoding="async"
|
||||
@@ -412,7 +499,7 @@
|
||||
<figure class="shot">
|
||||
<div class="device device--phone">
|
||||
<div class="device__screen">
|
||||
<img src="img/screenshots/phone/light/02-password-540.webp" srcset="img/screenshots/phone/light/02-password-1080.webp 1080w, img/screenshots/phone/light/02-password-540.webp 540w" sizes="(max-width: 840px) 44vw, 232px"
|
||||
<img src="img/screenshots/phone/light/02-password-540.webp" srcset="img/screenshots/phone/light/02-password-1080.webp 1080w, img/screenshots/phone/light/02-password-540.webp 540w" sizes="(max-width: 839px) 44vw, 232px"
|
||||
data-light-src="img/screenshots/phone/light/02-password-540.webp" data-light-srcset="img/screenshots/phone/light/02-password-1080.webp 1080w, img/screenshots/phone/light/02-password-540.webp 540w"
|
||||
data-dark-src="img/screenshots/phone/dark/02-password-540.webp" data-dark-srcset="img/screenshots/phone/dark/02-password-1080.webp 1080w, img/screenshots/phone/dark/02-password-540.webp 540w"
|
||||
width="393" height="852" loading="lazy" decoding="async"
|
||||
@@ -426,7 +513,7 @@
|
||||
<figure class="shot">
|
||||
<div class="device device--phone">
|
||||
<div class="device__screen">
|
||||
<img src="img/screenshots/phone/light/03-download-540.webp" srcset="img/screenshots/phone/light/03-download-1080.webp 1080w, img/screenshots/phone/light/03-download-540.webp 540w" sizes="(max-width: 840px) 44vw, 232px"
|
||||
<img src="img/screenshots/phone/light/03-download-540.webp" srcset="img/screenshots/phone/light/03-download-1080.webp 1080w, img/screenshots/phone/light/03-download-540.webp 540w" sizes="(max-width: 839px) 44vw, 232px"
|
||||
data-light-src="img/screenshots/phone/light/03-download-540.webp" data-light-srcset="img/screenshots/phone/light/03-download-1080.webp 1080w, img/screenshots/phone/light/03-download-540.webp 540w"
|
||||
data-dark-src="img/screenshots/phone/dark/03-download-540.webp" data-dark-srcset="img/screenshots/phone/dark/03-download-1080.webp 1080w, img/screenshots/phone/dark/03-download-540.webp 540w"
|
||||
width="393" height="852" loading="lazy" decoding="async"
|
||||
@@ -440,7 +527,7 @@
|
||||
<figure class="shot">
|
||||
<div class="device device--phone">
|
||||
<div class="device__screen">
|
||||
<img src="img/screenshots/phone/light/04-qr-code-540.webp" srcset="img/screenshots/phone/light/04-qr-code-1080.webp 1080w, img/screenshots/phone/light/04-qr-code-540.webp 540w" sizes="(max-width: 840px) 44vw, 232px"
|
||||
<img src="img/screenshots/phone/light/04-qr-code-540.webp" srcset="img/screenshots/phone/light/04-qr-code-1080.webp 1080w, img/screenshots/phone/light/04-qr-code-540.webp 540w" sizes="(max-width: 839px) 44vw, 232px"
|
||||
data-light-src="img/screenshots/phone/light/04-qr-code-540.webp" data-light-srcset="img/screenshots/phone/light/04-qr-code-1080.webp 1080w, img/screenshots/phone/light/04-qr-code-540.webp 540w"
|
||||
data-dark-src="img/screenshots/phone/dark/04-qr-code-540.webp" data-dark-srcset="img/screenshots/phone/dark/04-qr-code-1080.webp 1080w, img/screenshots/phone/dark/04-qr-code-540.webp 540w"
|
||||
width="393" height="852" loading="lazy" decoding="async"
|
||||
@@ -665,6 +752,23 @@ docker compose up -d</code></pre>
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
// The top app bar takes surface-container once the page scrolls under it.
|
||||
const nav = document.querySelector('.nav');
|
||||
const markScrolled = () => nav.toggleAttribute('data-scrolled', window.scrollY > 0);
|
||||
|
||||
window.addEventListener('scroll', markScrolled, { passive: true });
|
||||
markScrolled();
|
||||
|
||||
// Theme: Light, then Dark, then System (the <head> script applies and remembers it).
|
||||
const themeToggle = document.getElementById('themeToggle');
|
||||
const themeNames = { light: 'Light', dark: 'Dark', system: 'System' };
|
||||
const nextTheme = { light: 'dark', dark: 'system', system: 'light' };
|
||||
const nameThemeToggle = () => themeToggle.setAttribute('aria-label', 'Theme: ' + themeNames[sealshareTheme.choice]);
|
||||
|
||||
themeToggle.addEventListener('click', () => sealshareTheme.set(nextTheme[sealshareTheme.choice]));
|
||||
document.addEventListener('sealshare:theme', nameThemeToggle);
|
||||
nameThemeToggle();
|
||||
|
||||
// Phone menu.
|
||||
const navToggle = document.getElementById('navToggle');
|
||||
const navLinks = document.getElementById('navLinks');
|
||||
@@ -694,11 +798,14 @@ docker compose up -d</code></pre>
|
||||
}
|
||||
});
|
||||
|
||||
// Screenshot gallery: one device at a time, in the chosen theme (the visitor's, to begin with).
|
||||
// Screenshot gallery: one device at a time, in the site's theme to begin with and whenever it
|
||||
// changes, until the visitor picks Light or Dark here.
|
||||
const deviceButtons = document.querySelectorAll('[data-gallery-device]');
|
||||
const themeButtons = document.querySelectorAll('[data-gallery-theme]');
|
||||
const galleries = document.querySelectorAll('[data-gallery]');
|
||||
const shots = document.querySelectorAll('[data-gallery] img');
|
||||
let galleryTheme = 'light';
|
||||
let galleryThemeChosen = false;
|
||||
|
||||
const press = (buttons, pressed) => buttons.forEach((button) => button.setAttribute('aria-pressed', String(button === pressed)));
|
||||
|
||||
@@ -709,6 +816,12 @@ docker compose up -d</code></pre>
|
||||
|
||||
const showTheme = (theme) => {
|
||||
press(themeButtons, [...themeButtons].find((button) => button.dataset.galleryTheme === theme));
|
||||
|
||||
if (theme === galleryTheme) {
|
||||
return;
|
||||
}
|
||||
|
||||
galleryTheme = theme;
|
||||
shots.forEach((shot) => {
|
||||
shot.srcset = shot.dataset[theme + 'Srcset'];
|
||||
shot.src = shot.dataset[theme + 'Src'];
|
||||
@@ -716,11 +829,18 @@ docker compose up -d</code></pre>
|
||||
};
|
||||
|
||||
deviceButtons.forEach((button) => button.addEventListener('click', () => showDevice(button.dataset.galleryDevice)));
|
||||
themeButtons.forEach((button) => button.addEventListener('click', () => showTheme(button.dataset.galleryTheme)));
|
||||
themeButtons.forEach((button) => button.addEventListener('click', () => {
|
||||
galleryThemeChosen = true;
|
||||
showTheme(button.dataset.galleryTheme);
|
||||
}));
|
||||
|
||||
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
showTheme('dark');
|
||||
}
|
||||
document.addEventListener('sealshare:theme', (event) => {
|
||||
if (!galleryThemeChosen) {
|
||||
showTheme(event.detail.theme);
|
||||
}
|
||||
});
|
||||
|
||||
showTheme(sealshareTheme.theme === 'dark' ? 'dark' : 'light');
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
+105
-2
@@ -7,6 +7,83 @@
|
||||
<meta name="description" content="How the SealShare website handles visitor data: server logs at the host and Plausible analytics, nothing else.">
|
||||
<meta name="theme-color" content="#faf4ff" media="(prefers-color-scheme: light)">
|
||||
<meta name="theme-color" content="#10062d" media="(prefers-color-scheme: dark)">
|
||||
<script>
|
||||
// Light, Dark or System, decided before the first paint: the visitor's choice in the nav, kept in
|
||||
// localStorage, else the system's. css/theme.css keys on <html data-theme>.
|
||||
(function () {
|
||||
var root = document.documentElement;
|
||||
var key = 'sealshare-website-theme';
|
||||
var choices = ['light', 'dark', 'system'];
|
||||
var surfaces = { light: '#faf4ff', dark: '#10062d' };
|
||||
var system = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
var choice = 'system';
|
||||
|
||||
try {
|
||||
var stored = localStorage.getItem(key);
|
||||
|
||||
if (choices.indexOf(stored) !== -1) {
|
||||
choice = stored;
|
||||
}
|
||||
} catch (error) {
|
||||
// Storage is blocked: follow the system.
|
||||
}
|
||||
|
||||
// A <picture>'s dark source (data-theme-dark) follows the site's theme instead of the system's.
|
||||
var sources = function () {
|
||||
document.querySelectorAll('source[data-theme-dark]').forEach(function (source) {
|
||||
source.media = root.dataset.theme === 'dark' ? 'all' : 'not all';
|
||||
});
|
||||
};
|
||||
|
||||
var apply = function () {
|
||||
var theme = choice === 'system' ? (system.matches ? 'dark' : 'light') : choice;
|
||||
|
||||
root.dataset.themeChoice = choice;
|
||||
root.dataset.theme = theme;
|
||||
|
||||
document.querySelectorAll('meta[name="theme-color"]').forEach(function (meta) {
|
||||
meta.removeAttribute('media');
|
||||
meta.setAttribute('content', surfaces[theme]);
|
||||
});
|
||||
|
||||
sources();
|
||||
document.dispatchEvent(new CustomEvent('sealshare:theme', { detail: { choice: choice, theme: theme } }));
|
||||
};
|
||||
|
||||
window.sealshareTheme = {
|
||||
sources: sources,
|
||||
get choice() {
|
||||
return choice;
|
||||
},
|
||||
get theme() {
|
||||
return root.dataset.theme;
|
||||
},
|
||||
set: function (next) {
|
||||
if (choices.indexOf(next) === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
choice = next;
|
||||
|
||||
try {
|
||||
localStorage.setItem(key, next);
|
||||
} catch (error) {
|
||||
// Storage is blocked: the page still switches, it just will not remember.
|
||||
}
|
||||
|
||||
apply();
|
||||
},
|
||||
};
|
||||
|
||||
system.addEventListener('change', function () {
|
||||
if (choice === 'system') {
|
||||
apply();
|
||||
}
|
||||
});
|
||||
|
||||
apply();
|
||||
})();
|
||||
</script>
|
||||
<!-- Privacy-friendly analytics by Plausible -->
|
||||
<script async src="https://plausible.io/js/pa-zWB4R2-rrBeLfwms3uIBT.js"></script>
|
||||
<script>
|
||||
@@ -19,18 +96,21 @@
|
||||
<link rel="stylesheet" href="css/theme.css">
|
||||
</head>
|
||||
<body id="top">
|
||||
<a class="skip-link" href="#main">Skip to content</a>
|
||||
<a class="skip-link btn btn--filled" href="#main">Skip to content</a>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="sprite" aria-hidden="true">
|
||||
<symbol id="i-menu" viewBox="0 -960 960 960"><path d="M160-240q-17 0-28.5-11.5T120-280q0-17 11.5-28.5T160-320h640q17 0 28.5 11.5T840-280q0 17-11.5 28.5T800-240H160Zm0-200q-17 0-28.5-11.5T120-480q0-17 11.5-28.5T160-520h640q17 0 28.5 11.5T840-480q0 17-11.5 28.5T800-440H160Zm0-200q-17 0-28.5-11.5T120-680q0-17 11.5-28.5T160-720h640q17 0 28.5 11.5T840-680q0 17-11.5 28.5T800-640H160Z"/></symbol>
|
||||
<symbol id="i-close" viewBox="0 -960 960 960"><path d="M480-424 284-228q-11 11-28 11t-28-11q-11-11-11-28t11-28l196-196-196-196q-11-11-11-28t11-28q11-11 28-11t28 11l196 196 196-196q11-11 28-11t28 11q11 11 11 28t-11 28L536-480l196 196q11 11 11 28t-11 28q-11 11-28 11t-28-11L480-424Z"/></symbol>
|
||||
<symbol id="i-open-in-new" viewBox="0 -960 960 960"><path d="M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h240q17 0 28.5 11.5T480-800q0 17-11.5 28.5T440-760H200v560h560v-240q0-17 11.5-28.5T800-480q17 0 28.5 11.5T840-440v240q0 33-23.5 56.5T760-120H200Zm560-584L416-360q-11 11-28 11t-28-11q-11-11-11-28t11-28l344-344H600q-17 0-28.5-11.5T560-800q0-17 11.5-28.5T600-840h200q17 0 28.5 11.5T840-800v200q0 17-11.5 28.5T800-560q-17 0-28.5-11.5T760-600v-104Z"/></symbol>
|
||||
<symbol id="i-light-mode" viewBox="0 -960 960 960"><path d="M480-360q50 0 85-35t35-85q0-50-35-85t-85-35q-50 0-85 35t-35 85q0 50 35 85t85 35Zm0 80q-83 0-141.5-58.5T280-480q0-83 58.5-141.5T480-680q83 0 141.5 58.5T680-480q0 83-58.5 141.5T480-280ZM80-440q-17 0-28.5-11.5T40-480q0-17 11.5-28.5T80-520h80q17 0 28.5 11.5T200-480q0 17-11.5 28.5T160-440H80Zm720 0q-17 0-28.5-11.5T760-480q0-17 11.5-28.5T800-520h80q17 0 28.5 11.5T920-480q0 17-11.5 28.5T880-440h-80ZM480-760q-17 0-28.5-11.5T440-800v-80q0-17 11.5-28.5T480-920q17 0 28.5 11.5T520-880v80q0 17-11.5 28.5T480-760Zm0 720q-17 0-28.5-11.5T440-80v-80q0-17 11.5-28.5T480-200q17 0 28.5 11.5T520-160v80q0 17-11.5 28.5T480-40ZM226-678l-43-42q-12-11-11.5-28t11.5-29q12-12 29-12t28 12l42 43q11 12 11 28t-11 28q-11 12-27.5 11.5T226-678Zm494 495-42-43q-11-12-11-28.5t11-27.5q11-12 27.5-11.5T734-282l43 42q12 11 11.5 28T777-183q-12 12-29 12t-28-12Zm-42-495q-12-11-11.5-27.5T678-734l42-43q11-12 28-11.5t29 11.5q12 12 12 29t-12 28l-43 42q-12 11-28 11t-28-11ZM183-183q-12-12-12-29t12-28l43-42q12-11 28.5-11t27.5 11q12 11 11.5 27.5T282-226l-42 43q-11 12-28 11.5T183-183Zm297-297Z"/></symbol>
|
||||
<symbol id="i-dark-mode" viewBox="0 -960 960 960"><path d="M480-120q-151 0-255.5-104.5T120-480q0-138 90-239.5T440-838q13-2 23 3.5t16 14.5q6 9 6.5 21t-7.5 23q-17 26-25.5 55t-8.5 61q0 90 63 153t153 63q31 0 61.5-9t54.5-25q11-7 22.5-6.5T819-479q10 5 15.5 15t3.5 24q-14 138-117.5 229T480-120Zm0-80q88 0 158-48.5T740-375q-20 5-40 8t-40 3q-123 0-209.5-86.5T364-660q0-20 3-40t8-40q-78 32-126.5 102T200-480q0 116 82 198t198 82Zm-10-270Z"/></symbol>
|
||||
<symbol id="i-brightness-auto" viewBox="0 -960 960 960"><path d="M408-412h146l25 73q3 8 10.5 13.5T606-320q15 0 23.5-12.5T633-359L519-661q-3-9-11-14t-17-5h-22q-9 0-17 5t-11 14L327-360q-5 14 3.5 27t24.5 13q10 0 17.5-5.5T383-340l25-72Zm18-52 52-150h4l52 150H426Zm-80 304H240q-33 0-56.5-23.5T160-240v-106l-77-78q-11-12-17-26.5T60-480q0-15 6-29.5T83-536l77-78v-106q0-33 23.5-56.5T240-800h106l78-77q12-11 26.5-17t29.5-6q15 0 29.5 6t26.5 17l78 77h106q33 0 56.5 23.5T800-720v106l77 78q11 12 17 26.5t6 29.5q0 15-6 29.5T877-424l-77 78v106q0 33-23.5 56.5T720-160H614l-78 77q-12 11-26.5 17T480-60q-15 0-29.5-6T424-83l-78-77Zm34-80 100 100 100-100h140v-140l100-100-100-100v-140H580L480-820 380-720H240v140L140-480l100 100v140h140Zm100-240Z"/></symbol>
|
||||
</svg>
|
||||
|
||||
<header class="nav">
|
||||
<div class="container nav__bar">
|
||||
<a class="brand" href="index.html"><svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M6 2h8l6 6v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2Z" stroke="currentColor" stroke-width="1.5"/><path d="M14 2v5a1 1 0 0 0 1 1h5" stroke="currentColor" stroke-width="1.5"/><path d="M12 17v-6m0 0-2.5 2.5M12 11l2.5 2.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg><span>SealShare</span></a>
|
||||
<button class="nav__toggle" id="navToggle" type="button" aria-expanded="false" aria-controls="navLinks" aria-label="Menu">
|
||||
<button class="icon-btn nav__toggle" id="navToggle" type="button" aria-expanded="false" aria-controls="navLinks" aria-label="Menu">
|
||||
<svg class="icon icon-menu" aria-hidden="true"><use href="#i-menu"/></svg>
|
||||
<svg class="icon icon-close" aria-hidden="true"><use href="#i-close"/></svg>
|
||||
</button>
|
||||
@@ -45,6 +125,11 @@
|
||||
<li><a class="btn btn--filled" href="https://gitea.nonameweb.ch/noNameWEB/SealShare"><svg class="icon" aria-hidden="true"><use href="#i-open-in-new"/></svg>Gitea</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<button class="icon-btn theme-toggle" id="themeToggle" type="button" aria-label="Theme: System">
|
||||
<svg class="icon icon-light-mode" aria-hidden="true"><use href="#i-light-mode"/></svg>
|
||||
<svg class="icon icon-dark-mode" aria-hidden="true"><use href="#i-dark-mode"/></svg>
|
||||
<svg class="icon icon-brightness-auto" aria-hidden="true"><use href="#i-brightness-auto"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -118,6 +203,24 @@
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
// The top app bar takes surface-container once the page scrolls under it.
|
||||
const nav = document.querySelector('.nav');
|
||||
const markScrolled = () => nav.toggleAttribute('data-scrolled', window.scrollY > 0);
|
||||
|
||||
window.addEventListener('scroll', markScrolled, { passive: true });
|
||||
markScrolled();
|
||||
|
||||
// Theme: Light, then Dark, then System (the <head> script applies and remembers it).
|
||||
const themeToggle = document.getElementById('themeToggle');
|
||||
const themeNames = { light: 'Light', dark: 'Dark', system: 'System' };
|
||||
const nextTheme = { light: 'dark', dark: 'system', system: 'light' };
|
||||
const nameThemeToggle = () => themeToggle.setAttribute('aria-label', 'Theme: ' + themeNames[sealshareTheme.choice]);
|
||||
|
||||
themeToggle.addEventListener('click', () => sealshareTheme.set(nextTheme[sealshareTheme.choice]));
|
||||
document.addEventListener('sealshare:theme', nameThemeToggle);
|
||||
nameThemeToggle();
|
||||
|
||||
// Phone menu.
|
||||
const navToggle = document.getElementById('navToggle');
|
||||
const navLinks = document.getElementById('navLinks');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user