sprucing the app up a little

This commit is contained in:
Chris Kruining 2024-11-21 17:01:44 +01:00
parent 57ab2d9324
commit 13e5727497
No known key found for this signature in database
GPG key ID: EB894A3560CCCAD2
20 changed files with 537 additions and 111 deletions

View file

@ -1,4 +1,5 @@
import { defineConfig } from '@solidjs/start/config';
import solidSvg from 'vite-plugin-solid-svg'
// import { VitePWA } from 'vite-plugin-pwa'
export default defineConfig({
@ -7,6 +8,7 @@ export default defineConfig({
cspNonce: 'KAAS_IS_AWESOME',
},
plugins: [
solidSvg()
// VitePWA({
// strategies: 'injectManifest',
// registerType: 'autoUpdate',

BIN
bun.lockb

Binary file not shown.

View file

@ -32,6 +32,7 @@
"bun-types": "^1.1.34",
"jsdom": "^25.0.1",
"vite-plugin-pwa": "^0.21.0",
"vite-plugin-solid-svg": "^0.8.1",
"workbox-window": "^7.3.0"
}
}

View file

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="512px" height="512px" viewBox="0 0 512 512" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(93.333334%,93.333334%,93.333334%);fill-opacity:1;" d="M 145.441406 214.847656 L 131.519531 256 L 96 256 L 155.585938 96 L 196.671875 96 L 256 256 L 218.65625 256 L 204.734375 214.847656 Z M 197.726562 191.296875 L 176 126.59375 L 174.433594 126.59375 L 152.703125 191.296875 L 197.761719 191.296875 Z M 197.726562 191.296875 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(93.333334%,93.333334%,93.333334%);fill-opacity:1;" d="M 0 64 C 0 28.652344 28.652344 0 64 0 L 288 0 C 323.347656 0 352 28.652344 352 64 L 352 160 L 448 160 C 483.347656 160 512 188.652344 512 224 L 512 448 C 512 483.347656 483.347656 512 448 512 L 224 512 C 188.652344 512 160 483.347656 160 448 L 160 352 L 64 352 C 28.652344 352 0 323.347656 0 288 Z M 64 32 C 46.328125 32 32 46.328125 32 64 L 32 288 C 32 305.671875 46.328125 320 64 320 L 288 320 C 305.671875 320 320 305.671875 320 288 L 320 64 C 320 46.328125 305.671875 32 288 32 Z M 292.414062 351.839844 C 298.59375 361.472656 305.28125 370.496094 312.574219 378.910156 C 288.640625 397.3125 259.039062 410.945312 224 420.257812 C 229.695312 427.199219 238.433594 440.574219 241.761719 448 C 277.761719 436.511719 308.320312 420.992188 334.113281 400.191406 C 358.976562 421.472656 389.761719 437.472656 427.871094 447.296875 C 432.128906 439.167969 441.121094 425.761719 448 418.816406 C 412 410.71875 382.175781 396.609375 357.761719 377.726562 C 379.550781 353.824219 396.863281 324.894531 409.632812 289.503906 L 448 289.503906 L 448 256 L 352 256 L 352 289.503906 L 376.480469 289.503906 C 366.304688 316.511719 352.800781 338.976562 335.777344 357.664062 C 331.074219 352.65625 326.640625 347.398438 322.496094 341.921875 C 313.464844 347.710938 303.117188 351.121094 292.414062 351.839844 Z M 292.414062 351.839844 "/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2 KiB

View file

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="512px" height="512px" viewBox="0 0 512 512" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(13.333334%,13.333334%,13.333334%);fill-opacity:1;" d="M 145.441406 214.847656 L 131.519531 256 L 96 256 L 155.585938 96 L 196.671875 96 L 256 256 L 218.65625 256 L 204.734375 214.847656 Z M 197.726562 191.296875 L 176 126.59375 L 174.433594 126.59375 L 152.703125 191.296875 L 197.761719 191.296875 Z M 197.726562 191.296875 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(13.333334%,13.333334%,13.333334%);fill-opacity:1;" d="M 0 64 C 0 28.652344 28.652344 0 64 0 L 288 0 C 323.347656 0 352 28.652344 352 64 L 352 160 L 448 160 C 483.347656 160 512 188.652344 512 224 L 512 448 C 512 483.347656 483.347656 512 448 512 L 224 512 C 188.652344 512 160 483.347656 160 448 L 160 352 L 64 352 C 28.652344 352 0 323.347656 0 288 Z M 64 32 C 46.328125 32 32 46.328125 32 64 L 32 288 C 32 305.671875 46.328125 320 64 320 L 288 320 C 305.671875 320 320 305.671875 320 288 L 320 64 C 320 46.328125 305.671875 32 288 32 Z M 292.414062 351.839844 C 298.59375 361.472656 305.28125 370.496094 312.574219 378.910156 C 288.640625 397.3125 259.039062 410.945312 224 420.257812 C 229.695312 427.199219 238.433594 440.574219 241.761719 448 C 277.761719 436.511719 308.320312 420.992188 334.113281 400.191406 C 358.976562 421.472656 389.761719 437.472656 427.871094 447.296875 C 432.128906 439.167969 441.121094 425.761719 448 418.816406 C 412 410.71875 382.175781 396.609375 357.761719 377.726562 C 379.550781 353.824219 396.863281 324.894531 409.632812 289.503906 L 448 289.503906 L 448 256 L 352 256 L 352 289.503906 L 376.480469 289.503906 C 366.304688 316.511719 352.800781 338.976562 335.777344 357.664062 C 331.074219 352.65625 326.640625 347.398438 322.496094 341.921875 C 313.464844 347.710938 303.117188 351.121094 292.414062 351.839844 Z M 292.414062 351.839844 "/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2 KiB

View file

@ -1,16 +1,28 @@
@import url("https://fonts.googleapis.com/css2?family=Roboto+Flex:opsz,wght,GRAD@8..144,400,45;8..144,400,50;8..144,1000,0&family=Roboto+Serif:opsz,GRAD@8..144,71&display=swap");
:root {
--surface-1: light-dark(#ddd, #222);
--surface-2: light-dark(#e8e8e8, #282828);
--surface-3: light-dark(#eee, #333);
--surface-4: light-dark(#f8f8f8, #383838);
--surface-5: light-dark(#fff, #444);
--text-1: light-dark(#222, #eee);
--text-2: light-dark(#282828, #d8d8d8);
--hue: 182.77deg;
--primary: light-dark(oklch(.7503 0.117 181.6deg), oklch(.8549 0.1149 182.77deg));
--secondary: oklch(from var(--primary) l c calc(h - 180));
--primary-100: oklch(from var(--primary-500) .95 c h);
--primary-300: oklch(from var(--primary-500) .9 c h);
--primary-500: light-dark(oklch(.7503 0.117 var(--hue)), oklch(.8549 0.1149 var(--hue)));
--primary-700: oklch(from var(--primary-500) .7 c h);
--primary-900: oklch(from var(--primary-500) .6 c h);
--secondary-100: oklch(from var(--secondary-500) .95 c h);
--secondary-300: oklch(from var(--secondary-500) .9 c h);
--secondary-500: oklch(from var(--primary-500) l c calc(h - 180));
--secondary-700: oklch(from var(--secondary-500) .7 c h);
--secondary-900: oklch(from var(--secondary-500) .6 c h);
--surface-1: light-dark(oklch(from var(--secondary-500) .9 .02 h), oklch(from var(--secondary-500) .2 .02 h));
--surface-2: oklch(from var(--surface-1) calc(l + .025) c h);
--surface-3: oklch(from var(--surface-2) calc(l + .025) c h);
--surface-4: oklch(from var(--surface-3) calc(l + .025) c h);
--surface-5: oklch(from var(--surface-4) calc(l + .025) c h);
--text-1: light-dark(oklch(from var(--secondary-500) .2 .02 h), oklch(from var(--secondary-500) .9 .02 h));
--text-2: oklch(from var(--text-1) calc(l + .1) c h);
--info: light-dark(oklch(.71 .17 249), oklch(.71 .17 249));
--fail: light-dark(oklch(.64 .21 25.3), oklch(.64 .21 25.3));
@ -30,6 +42,7 @@
--padding-s: .25em;
--padding-m: .5em;
--padding-l: 1em;
--padding-xl: 1.5em;
}
html {
@ -49,7 +62,7 @@ body {
background-color: var(--surface-1);
color: var(--text-2);
accent-color: var(--primary);
accent-color: var(--primary-500);
margin: 0;
@ -65,7 +78,7 @@ body {
}
a {
color: var(--primary);
color: var(--primary-500);
}
h1 {
@ -86,4 +99,10 @@ code {
background-color: var(--surface-3);
border: 1px solid var(--surface-5);
border-radius: var(--radii-m);
}
@property --hue {
syntax: '<angle>';
inherits: false;
initial-value: 0deg;
}

View file

@ -3,13 +3,16 @@ import { Router } from "@solidjs/router";
import { FileRoutes } from "@solidjs/start/router";
import { Suspense } from "solid-js";
import "./app.css";
import { ThemeProvider } from "./components/colorschemepicker";
export default function App() {
return (
<Router
root={props => (
<MetaProvider>
<Suspense>{props.children}</Suspense>
<ThemeProvider>
<Suspense>{props.children}</Suspense>
</ThemeProvider>
</MetaProvider>
)}
>

104
src/assets/edit-blank.svg Normal file
View file

@ -0,0 +1,104 @@
<svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" width="20em" height="12.3109243697em"
viewBox="0 0 952 586" xmlns:xlink="http://www.w3.org/1999/xlink">
<path id="a163713d-a7fc-4807-a77b-111ad75719e9-799" data-name="Path 133"
d="M170.63353,697.233a158.3937,158.3937,0,0,0,7.4,43.785c.1.329.211.653.319.982h27.613c-.029-.295-.059-.624-.088-.982-1.841-21.166,8.677-148.453,21.369-170.483C226.13454,572.322,168.49254,629.979,170.63353,697.233Z"
transform="translate(-124 -157)" fill="var(--surface-4)" />
<path id="a1d5a274-7181-45f3-aae5-db776f20014a-800" data-name="Path 134"
d="M172.70558,741.018c.231.329.471.658.717.982h20.716c-.157-.28-.339-.609-.55-.982-3.422-6.176-13.551-24.642-22.953-43.785-10.1-20.572-19.374-41.924-18.593-49.652C151.80058,649.323,144.80861,702.457,172.70558,741.018Z"
transform="translate(-124 -157)" fill="var(--surface-4)" />
<path
d="M775.29126,277.577a14.42246,14.42246,0,0,0,21.04127,6.80778l39.97977,32.06957,2.47488-26.51836-38.34489-26.38825a14.50066,14.50066,0,0,0-25.151,14.02926Z"
transform="translate(-124 -157)" fill="#9f616a" />
<polygon
points="713.205 130.446 698.283 119.903 681.358 139.458 701.046 151.126 713.205 130.446"
fill="var(--primary-500)" />
<path
d="M833.93681,280.29582l50.28691,19.349L932.63291,267.947a24.62075,24.62075,0,0,1,31.79547,37.06016l-.433.48083-74.454,39.9183-81.32649-37.15291Z"
transform="translate(-124 -157)" fill="var(--text-2)" />
<polygon points="695.76 583 171.76 583 190.76 212 272.76 212 348.374 265 714.76 265 695.76 583"
fill="var(--surface-4)" />
<path
d="M691.4891,626.86286,388.6242,502.13469a4.32609,4.32609,0,0,1-2.35009-5.64107L523.508,163.26232a4.3261,4.3261,0,0,1,5.64107-2.35009L832.014,285.6404a4.32609,4.32609,0,0,1,2.35009,5.64107L697.13017,624.51277A4.32609,4.32609,0,0,1,691.4891,626.86286Z"
transform="translate(-124 -157)" fill="var(--surface-5)" />
<path
d="M691.4891,626.86286,388.6242,502.13469a4.32609,4.32609,0,0,1-2.35009-5.64107L523.508,163.26232a4.3261,4.3261,0,0,1,5.64107-2.35009L832.014,285.6404a4.32609,4.32609,0,0,1,2.35009,5.64107L697.13017,624.51277A4.32609,4.32609,0,0,1,691.4891,626.86286ZM528.49088,162.51046a2.59553,2.59553,0,0,0-3.38465,1.41006L387.87234,497.15182a2.59552,2.59552,0,0,0,1.41005,3.38464l302.8649,124.72817a2.59553,2.59553,0,0,0,3.38465-1.41L832.76583,290.62327a2.59552,2.59552,0,0,0-1.41005-3.38464Z"
transform="translate(-124 -157)" fill="var(--surface-3)" />
<path
d="M614.03119,325.86654,538.9143,294.93132a4.32609,4.32609,0,0,1-2.35009-5.64107l30.93522-75.11689a4.3261,4.3261,0,0,1,5.64107-2.35009l75.11689,30.93522a4.3261,4.3261,0,0,1,2.35009,5.64107l-30.93522,75.11689A4.3261,4.3261,0,0,1,614.03119,325.86654ZM572.4823,213.4215a2.59553,2.59553,0,0,0-3.38464,1.41006l-30.93522,75.11689a2.59553,2.59553,0,0,0,1.41006,3.38464l75.11688,30.93522a2.59553,2.59553,0,0,0,3.38465-1.41006l30.93521-75.11689a2.59551,2.59551,0,0,0-1.41-3.38464Z"
transform="translate(-124 -157)" fill="var(--text-2)" />
<path
d="M588.67043,326.17072,513.55354,295.2355a3.89342,3.89342,0,0,1-2.11508-5.077l30.93522-75.11689a3.89343,3.89343,0,0,1,5.077-2.11508l75.11688,30.93522a3.89341,3.89341,0,0,1,2.11508,5.077l-30.93522,75.11689A3.89341,3.89341,0,0,1,588.67043,326.17072Z"
transform="translate(-124 -157)" fill="var(--primary-500)" />
<path
d="M733.35509,428.74966,498.415,331.99483a3.889,3.889,0,1,1,2.96189-7.192L736.317,421.55762a3.889,3.889,0,0,1-2.96188,7.192Z"
transform="translate(-124 -157)" fill="var(--text-1)" />
<path
d="M666.41582,430.15629,488.213,356.76742a3.889,3.889,0,1,1,2.96188-7.192l178.20284,73.38887a3.889,3.889,0,1,1-2.96189,7.192Z"
transform="translate(-124 -157)" fill="var(--text-1)" />
<path
d="M770.07315,337.32136,666.18809,294.53861a3.889,3.889,0,1,1,2.96189-7.192l103.885,42.78275a3.889,3.889,0,0,1-2.96188,7.192Z"
transform="translate(-124 -157)" fill="var(--text-1)" />
<path
d="M733.94491,351.41683,655.98605,319.3112a3.889,3.889,0,1,1,2.96189-7.192l77.95886,32.10562a3.889,3.889,0,0,1-2.96189,7.192Z"
transform="translate(-124 -157)" fill="var(--text-1)" />
<path
d="M712.951,478.29485,478.011,381.54a3.889,3.889,0,1,1,2.96188-7.192L715.91289,471.1028a3.889,3.889,0,0,1-2.96188,7.192Z"
transform="translate(-124 -157)" fill="var(--text-1)" />
<path
d="M646.01174,479.70147,467.80891,406.3126a3.889,3.889,0,1,1,2.96188-7.192l178.20284,73.38887a3.889,3.889,0,1,1-2.96189,7.192Z"
transform="translate(-124 -157)" fill="var(--text-1)" />
<path
d="M692.54693,527.84,457.60687,431.0852a3.889,3.889,0,0,1,2.96188-7.192L695.50881,520.648a3.889,3.889,0,0,1-2.96188,7.192Z"
transform="translate(-124 -157)" fill="var(--text-1)" />
<path
d="M682.34489,552.61262,447.40483,455.85779a3.889,3.889,0,0,1,2.96188-7.192l234.94006,96.75484a3.889,3.889,0,0,1-2.96188,7.192Z"
transform="translate(-124 -157)" fill="var(--text-1)" />
<path
d="M567.73018,550.77248a84.70308,84.70308,0,0,0,14.09436-.43c4.21238-.49243,8.60066-1.17049,12.29309-3.38536a11.6831,11.6831,0,0,0,5.8212-8.83535,8.2218,8.2218,0,0,0-4.975-8.33661,9.80892,9.80892,0,0,0-9.95124,1.3943,12.959,12.959,0,0,0-4.44981,10.35166c.194,8.00444,6.52716,15.90938,13.55947,19.23894,7.92082,3.75025,18.73754.56318,20.76617-8.67189.42194-1.92082-2.19428-2.58835-3.288-1.35411a8.72086,8.72086,0,0,0,12.17216,12.44835l-2.94431-1.21255a20.9902,20.9902,0,0,0,14.43752,15.24852,19.46991,19.46991,0,0,0,5.37174.81856c2.2119.00621,4.48428,1.11646,6.59962,1.80561l15.24432,4.96639c2.24232.73052,3.665-2.67332,1.40427-3.40985l-13.80618-4.49787c-2.30073-.74955-4.59586-1.51967-6.90308-2.24893-1.64936-.52133-3.45545-.23905-5.176-.54579a17.28811,17.28811,0,0,1-13.5191-12.64511,1.86584,1.86584,0,0,0-2.9443-1.21254,5.04821,5.04821,0,0,1-7.02188-7.25421l-3.288-1.35411c-1.30866,5.95754-8.576,8.19323-13.81358,6.47055-5.85748-1.92656-10.892-7.53271-12.639-13.4049a10.8108,10.8108,0,0,1,.7867-8.60233,6.443,6.443,0,0,1,6.75034-3.30637,4.62264,4.62264,0,0,1,3.95027,5.07015,8.26891,8.26891,0,0,1-4.60472,6.264c-3.29662,1.7695-7.24432,2.21012-10.90575,2.61181a78.79791,78.79791,0,0,1-12.57356.3577c-2.35393-.11867-2.82641,3.54144-.44763,3.66136Z"
transform="translate(-124 -157)" fill="var(--primary-500)" />
<polygon points="695.76 290 695.76 583 171.76 583 171.76 237 253.76 237 329.37 290 695.76 290"
fill="var(--surface-5)" />
<rect x="203.75984" y="528" width="214" height="17" fill="var(--primary-500)" />
<rect x="203.75984" y="495" width="107" height="17" fill="var(--primary-500)" />
<path
d="M820.75984,741h-526V393h83.31555l75.61414,53H820.75984Zm-524-2h522V448H453.05843l-75.61414-53H296.75984Z"
transform="translate(-124 -157)" fill="var(--surface-3)" />
<polygon
points="909.144 548.636 891.414 554.972 858.535 489.598 884.704 480.246 909.144 548.636"
fill="#9f616a" />
<path
d="M986.63848,741.638l-.25872-.72291a23.659,23.659,0,0,1,14.30045-30.20571l34.91779-12.47929,8.21153,22.97656Z"
transform="translate(-124 -157)" fill="oklch(from var(--text-2) calc(l - .1) c h)" />
<polygon
points="793.848 566.172 775.019 566.172 766.062 493.546 793.851 493.547 793.848 566.172"
fill="#9f616a" />
<path
d="M922.64961,741.42424l-60.71214-.00225v-.76791A23.63085,23.63085,0,0,1,885.5687,717.0236h.0015l37.08053.0015Z"
transform="translate(-124 -157)" fill="oklch(from var(--text-2) calc(l - .1) c h)" />
<path d="M960.75907,259.18645l-8.18861-16.18053s-30.50532,7.64282-33.27853,25.32289Z"
transform="translate(-124 -157)" fill="var(--primary-500)" />
<polygon
points="870.547 287.198 848.278 411.467 907.407 516.036 872.083 529.858 812.186 428.494 804.507 400.849 799.899 545.216 768.042 544.249 753.435 409.445 776.862 284.127 870.547 287.198"
fill="oklch(from var(--text-2) calc(l - .1) c h)" />
<path
d="M989.9385,388.055l-.77018-72.87145c0-30.88384-20.32611-53.64707-23.14362-55.75276-1.32569-4.231-3.70431-7.15557-7.0678-8.68606-6.77553-3.07086-15.06191.61412-15.41273.77989L918.685,260.84434l-.11662.34118c-.26371.77988-25.3466,83.08812-31.64469,103.74554-.8968,2.96364-1.41327,4.6599-1.41327,4.6599s.09758,4.77688.27275,12.20538c.556,25.54152,1.87167,82.43492,2.39814,84.82336,0,0,45.91642,6.96052,64.09763,6.96052,32.70714,0,53.48166-6.25865,53.94958-6.36587l.75066-.156Z"
transform="translate(-124 -157)" fill="var(--text-2)" />
<circle cx="927.1367" cy="204.30312" r="33.60816"
transform="translate(-108.38042 312.74381) rotate(-28.66301)" fill="#9f616a" />
<path
d="M930.86135,372.63255l-45.07817,9.16379c-.17517-7.4285-.27275-12.20538-.27275-12.20538s.51647-1.69626,1.41327-4.6599Z"
transform="translate(-124 -157)" opacity="0.2" />
<path
d="M797.36935,363.02694a14.4225,14.4225,0,0,0,21.81522-3.63l50.24885,10.09416-9.99619-24.68652-46.18464-5.80088a14.50066,14.50066,0,0,0-15.88324,24.02326Z"
transform="translate(-124 -157)" fill="#9f616a" />
<polygon points="732.887 186.321 714.788 183.82 708.751 208.968 731.599 210.276 732.887 186.321"
fill="var(--primary-500)" />
<path
d="M850.69724,338.47437l53.55238-5.94132,28.41215-50.40785a24.62075,24.62075,0,0,1,45.27595,18.28923l-.16338.62608-47.76016,69.68386-89.30252,4.40419Z"
transform="translate(-124 -157)" fill="var(--text-2)" />
<path
d="M955.76343,233.48271l-27.895,1.00127c-1.70035.061-6.31513-18.28939-6.91921-22.09617a10.3896,10.3896,0,0,0-10.838-8.40483c-2.08811.19724-7.35359-3.70388-12.78705-8.32323-10.31547-8.76987-9.77883-25.241,1.55269-32.65157q.46458-.30381.91188-.55481c7.14855-4.00112,15.511-5.34475,23.70251-5.44721,7.42579-.09288,15.06209.84177,21.60406,4.35653,11.72836,6.30122,17.97016,20.07116,18.51843,33.37376s-3.71631,26.31011-8.55563,38.71336"
transform="translate(-124 -157)" fill="var(--secondary-500)" />
<path d="M1075,743H125a1,1,0,0,1,0-2h950a1,1,0,0,1,0,2Z" transform="translate(-124 -157)"
fill="var(--text-2)" />
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

150
src/assets/landing.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 27 KiB

View file

@ -19,4 +19,10 @@
&:has(:focus-visible) {
border-color: var(--info);
}
}
.hue {
display: flex;
flex-flow: row;
align-items: center;
}

View file

@ -1,69 +1,115 @@
import { Component, createEffect, createMemo, createResource, For, Setter } from "solid-js";
import { Accessor, Component, createContext, createEffect, createMemo, createResource, For, ParentComponent, Setter, Show, Suspense, useContext } from "solid-js";
import css from './colorschemepicker.module.css';
import { CgDarkMode } from "solid-icons/cg";
import { action, cache, useAction } from "@solidjs/router";
import { action, createAsyncStore, query, useAction } from "@solidjs/router";
import { useSession } from "vinxi/http";
import { createStore, reconcile, ReconcileOptions, SetStoreFunction } from "solid-js/store";
export enum ColorScheme {
Auto = 'light dark',
Light = 'light',
Dark = 'dark',
}
type ColorSchemeKey = keyof typeof ColorScheme;
const colorSchemeKeys: readonly ColorSchemeKey[] = ['Auto', 'Light', 'Dark'] as const;
const colorSchemes = Object.entries(ColorScheme) as readonly [keyof typeof ColorScheme, ColorScheme][];
interface ColorSchemePickerProps {
value?: Setter<ColorScheme>;
export interface State {
colorScheme: ColorScheme;
hue: number;
}
const getSession = async () => {
'use server';
console.log('what? why? how???', process.env.SESSION_SECRET);
return useSession<{ colorScheme: ColorSchemeKey }>({
return useSession<State>({
password: process.env.SESSION_SECRET!,
});
};
export const getColorScheme = cache(async () => {
export const getState = query(async () => {
'use server';
const session = await getSession();
return session.data.colorScheme;
return session.data;
}, 'color-scheme');
const setColorScheme = action(async (colorScheme: ColorSchemeKey) => {
const setState = action(async (state: State) => {
'use server';
const session = await getSession();
await session.update({ colorScheme });
await session.update(state);
}, 'color-scheme');
export const ColorSchemePicker: Component<ColorSchemePickerProps> = (props) => {
const [value, { mutate }] = createResource<ColorSchemeKey>(() => getColorScheme(), { initialValue: 'Auto' });
const updateStore = useAction(setColorScheme);
interface ThemeContextType {
readonly theme: State;
setColorScheme(colorScheme: ColorScheme): void;
setHue(hue: number): void;
}
createEffect(() => {
props.value?.(ColorScheme[value()]);
});
const ThemeContext = createContext<ThemeContextType>();
return <label class={css.picker} aria-label="Color scheme picker">
<CgDarkMode />
const useStore = () => useContext(ThemeContext)!;
<select name="color-scheme-picker" onInput={(e) => {
if (e.target.value !== value()) {
const nextValue = (e.target.value ?? 'Auto') as ColorSchemeKey;
export const useTheme = () => {
const { theme } = useContext(ThemeContext) ?? {};
mutate(nextValue);
updateStore(nextValue);
}
}}>
<For each={colorSchemeKeys}>{
(v) => <option value={v} selected={v === value()}>{v}</option>
}</For>
</select>
</label>;
if (theme === undefined) {
throw new Error('useColorScheme is called outside a <ColorSchemeProvider />');
}
return theme;
};
export const ThemeProvider: ParentComponent = (props) => {
const [state, { mutate }] = createResource<State>(() => getState(), { deferStream: true, initialValue: { colorScheme: ColorScheme.Auto, hue: 0 } });
const updateState = useAction(setState);
return <Suspense>
<Show when={state()}>{state => {
const [store, setStore] = createStore(state());
createEffect(() => {
setStore(state());
});
createEffect(() => {
console.log({ ...store })
});
return <ThemeContext.Provider value={{
get theme() { return store; },
setColorScheme(colorScheme: ColorScheme) { updateState(mutate(prev => ({ ...prev, colorScheme }))) },
setHue(hue: number) { updateState(mutate(prev => ({ ...prev, hue }))) },
}}>
{props.children}
</ThemeContext.Provider>;
}}</Show>
</Suspense>;
};
export const ColorSchemePicker: Component = (props) => {
const { theme, setColorScheme, setHue } = useStore();
return <>
<label class={css.picker} aria-label="Color scheme picker">
<CgDarkMode />
<select name="color-scheme-picker" onInput={(e) => {
if (e.target.value !== theme.colorScheme) {
const nextValue = (e.target.value ?? ColorScheme.Auto) as ColorScheme;
setColorScheme(nextValue);
}
}}>
<For each={colorSchemes}>{
([label, value]) => <option value={value} selected={value === theme.colorScheme}>{label}</option>
}</For>
</select>
</label>
<label class={css.hue} aria-label="Hue slider">
<input type="range" min="0" max="360" value={theme.hue} onInput={e => setHue(e.target.valueAsNumber)} />
</label>
</>;
};

View file

@ -1,23 +1,26 @@
import { Link, Meta, Title } from "@solidjs/meta";
import { Component, createMemo, createSignal, ErrorBoundary, ParentProps, Show } from "solid-js";
import { BsTranslate } from "solid-icons/bs";
import { Link, Meta, Style, Title } from "@solidjs/meta";
import { Component, createEffect, createMemo, createSignal, ErrorBoundary, ParentProps, Show } from "solid-js";
import { FilesProvider } from "~/features/file";
import { CommandPalette, CommandPaletteApi, Menu, MenuProvider } from "~/features/menu";
import { A, createAsync, useBeforeLeave } from "@solidjs/router";
import { A, RouteDefinition, useBeforeLeave } from "@solidjs/router";
import { createCommand, Modifier } from "~/features/command";
import { ColorScheme, ColorSchemePicker, getColorScheme } from "~/components/colorschemepicker";
import { ColorScheme, ColorSchemePicker, getState, useTheme } from "~/components/colorschemepicker";
import css from "./editor.module.css";
export const route: RouteDefinition = {
preload: () => getState(),
};
export default function Editor(props: ParentProps) {
const storedColorScheme = createAsync<keyof typeof ColorScheme>(() => getColorScheme(), { initialValue: 'Auto' });
const theme = useTheme();
const [commandPalette, setCommandPalette] = createSignal<CommandPaletteApi>();
const colorScheme = createMemo(() => ColorScheme[storedColorScheme()]);
const color = createMemo(() => ({
[ColorScheme.Auto]: undefined,
[ColorScheme.Light]: '#eee',
[ColorScheme.Dark]: '#333',
}[ColorScheme[storedColorScheme()]]));
}[theme.colorScheme]));
const commands = [
createCommand('open command palette', () => {
@ -32,7 +35,7 @@ export default function Editor(props: ParentProps) {
}
useBeforeLeave((e) => {
e.preventDefault()
e.preventDefault();
transition(() => { e.retry(true) })
});
@ -40,14 +43,18 @@ export default function Editor(props: ParentProps) {
return <MenuProvider commands={commands}>
<Title>Calque</Title>
<Meta id="theme-scheme" name="color-scheme" content={colorScheme()} />
<Meta id="theme-color" name="theme-color" content={color()} />
<Show when={color() === undefined}>
<Meta id="theme-scheme" name="color-scheme" content={theme.colorScheme} />
<Show when={color() === undefined} fallback={<Meta id="theme-color" name="theme-color" content={color()} />}>
<Meta id="theme-auto-light" name="theme-color" media="(prefers-color-scheme: light)" content="#eee" />
<Meta id="theme-auto-dark" name="theme-color" media="(prefers-color-scheme: dark)" content="#333" />
</Show>
<Style>{`
:root {
--hue: ${theme.hue}deg !important;
}
`}</Style>
<Link rel="icon" href="/images/favicon.dark.svg" media="screen and (prefers-color-scheme: dark)" />
<Link rel="icon" href="/images/favicon.light.svg" media="screen and (prefers-color-scheme: light)" />
<Link rel="manifest" href="/manifest.json" />
@ -66,6 +73,7 @@ export default function Editor(props: ParentProps) {
<section class={css.right}>
<ColorSchemePicker />
</section>
</nav>

View file

@ -27,9 +27,25 @@
.blank {
display: grid;
grid: 100% / 100%;
place-content: center;
place-items: center;
grid-auto-flow: column;
gap: var(--padding-l);
inline-size: 100%;
block-size: 100%;
place-items: center;
& > svg {
padding-inline-end: 3em;
margin-inline-end: 3em;
border-inline-end: 2px solid var(--surface-5);
}
& > button {
background-color: var(--surface-4);
color: var(--text-1);
padding: var(--padding-l) var(--padding-xl);
border: none;
border-radius: var(--radii-m);
cursor: pointer;
}
}

View file

@ -7,9 +7,10 @@ import { Grid, load, useFiles } from "~/features/file";
import { Command, CommandType, Context, createCommand, Modifier, noop, useCommands } from "~/features/command";
import { GridApi } from "~/features/file/grid";
import { Tab, Tabs } from "~/components/tabs";
import css from "./edit.module.css";
import { isServer } from "solid-js/web";
import { Prompt, PromptApi } from "~/components/prompt";
import EditBlankImage from '~/assets/edit-blank.svg'
import css from "./edit.module.css";
const isInstalledPWA = !isServer && window.matchMedia('(display-mode: standalone)').matches;
@ -269,6 +270,10 @@ const Editor: Component<{ root: FileSystemDirectoryHandle }> = (props) => {
<Menu.Item command={commands.open} />
<Menu.Item command={commands.save} />
<Menu.Separator />
<Menu.Item command={commands.close} />
</Menu.Item>
<Menu.Item label="edit">
@ -385,6 +390,8 @@ const Content: Component<{ directory: FileSystemDirectoryHandle, api?: Setter<Gr
const Blank: Component<{ open: CommandType }> = (props) => {
return <div class={css.blank}>
<EditBlankImage />
<button onpointerdown={() => props.open()}>open a folder</button>
</div>
};

View file

@ -3,6 +3,11 @@
place-content: center;
gap: var(--padding-m);
& > :is(.primary, .secondary) {
display: grid;
grid: 3em / repeat(5, 3em);
}
ul {
display: flex;
flex-flow: column;

View file

@ -1,46 +1,13 @@
import { Component, createEffect, createMemo, createResource, createSignal, For, onMount, Show } from "solid-js";
import { useFiles } from "~/features/file";
import { AiFillFile, AiFillFolder, AiFillFolderOpen } from "solid-icons/ai";
import { A } from "@solidjs/router";
import LandingImage from '../../assets/landing.svg'
import css from "./index.module.css";
interface FileEntry {
name: string;
kind: 'file';
meta: File;
}
interface FolderEntry {
name: string;
kind: 'folder';
entries: Entry[];
}
type Entry = FileEntry | FolderEntry;
async function* walk(directory: FileSystemDirectoryHandle, filters: RegExp[] = [], depth = 0): AsyncGenerator<Entry, void, never> {
if (depth === 10) {
return;
}
for await (const handle of directory.values()) {
if (filters.some(f => f.test(handle.name))) {
continue;
}
if (handle.kind === 'file') {
yield { name: handle.name, kind: 'file', meta: await handle.getFile() };
}
else {
yield { name: handle.name, kind: 'folder', entries: await Array.fromAsync(walk(handle, filters, depth + 1)) };
}
}
}
export default function Index() {
return (
<main class={css.main}>
<LandingImage />
<h1>Hi, welcome!</h1>
<b>Lets get started</b>

View file

@ -0,0 +1,66 @@
.main {
display: grid;
place-content: center;
gap: var(--padding-m);
& > svg {
inline-size: 100%;
}
& > :is(.primary, .secondary) {
display: grid;
grid: 3em / repeat(5, 3em);
}
& > .primary {
& > :nth-child(1) {
background-color: var(--primary-100);
}
& > :nth-child(2) {
background-color: var(--primary-300);
}
& > :nth-child(3) {
background-color: var(--primary-500);
}
& > :nth-child(4) {
background-color: var(--primary-700);
}
& > :nth-child(5) {
background-color: var(--primary-900);
}
}
& > .secondary {
& > :nth-child(1) {
background-color: var(--secondary-100);
}
& > :nth-child(2) {
background-color: var(--secondary-300);
}
& > :nth-child(3) {
background-color: var(--secondary-500);
}
& > :nth-child(4) {
background-color: var(--secondary-700);
}
& > :nth-child(5) {
background-color: var(--secondary-900);
}
}
ul {
display: flex;
flex-flow: column;
gap: var(--padding-s);
padding-inline-start: var(--padding-l);
margin: 0;
}
}

View file

@ -0,0 +1,38 @@
import { A } from "@solidjs/router";
import LandingImage from '../../assets/landing.svg'
import css from "./test.module.css";
export default function Index() {
return (
<main class={css.main}>
<LandingImage />
<h1>Hi, welcome!</h1>
<b>Lets get started</b>
<div class={css.primary}>
<span />
<span />
<span />
<span />
<span />
</div>
<div class={css.secondary}>
<span />
<span />
<span />
<span />
<span />
</div>
<ul>
<li><A href="/edit">Start editing</A></li>
{/* <li><A href="/experimental">Try new features</A></li> */}
<li><A href="/instructions">Read the instructions</A></li>
<li><A href="/about">About this app</A></li>
</ul>
</main>
);
}

View file

@ -50,6 +50,7 @@
& .right {
display: grid;
grid-auto-flow: column;
align-content: center;
}
}

View file

@ -15,6 +15,7 @@
"@testing-library/jest-dom",
"@types/wicg-file-system-access",
"vinxi/types/client",
"vite-plugin-solid-svg/types-component-solid",
"vite-plugin-pwa/solid",
"bun-types"
],