Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7770ba9844 | ||
|
|
55b8e438ad | ||
|
|
1607a22f0c | ||
|
|
8a5dfef41a | ||
|
|
1a610eaac4 | ||
|
|
c2d4ce0179 | ||
|
|
a1b8cc6ddc | ||
|
|
8a2c46f5ea | ||
|
|
8d42f34065 | ||
|
|
905ceebc06 | ||
|
|
87c557941a | ||
|
|
0e1e803486 | ||
|
|
1dc9751a33 | ||
|
|
b81f8f67cc |
|
Before Width: | Height: | Size: 248 KiB After Width: | Height: | Size: 248 KiB |
|
Before Width: | Height: | Size: 308 KiB After Width: | Height: | Size: 308 KiB |
|
Before Width: | Height: | Size: 228 KiB After Width: | Height: | Size: 228 KiB |
|
Before Width: | Height: | Size: 147 KiB After Width: | Height: | Size: 148 KiB |
|
Before Width: | Height: | Size: 333 KiB After Width: | Height: | Size: 334 KiB |
|
Before Width: | Height: | Size: 245 KiB After Width: | Height: | Size: 245 KiB |
|
Before Width: | Height: | Size: 282 KiB After Width: | Height: | Size: 284 KiB |
|
Before Width: | Height: | Size: 370 KiB After Width: | Height: | Size: 370 KiB |
|
Before Width: | Height: | Size: 356 KiB After Width: | Height: | Size: 355 KiB |
|
Before Width: | Height: | Size: 229 KiB After Width: | Height: | Size: 231 KiB |
|
Before Width: | Height: | Size: 253 KiB After Width: | Height: | Size: 253 KiB |
|
Before Width: | Height: | Size: 238 KiB After Width: | Height: | Size: 245 KiB |
|
Before Width: | Height: | Size: 243 KiB After Width: | Height: | Size: 246 KiB |
|
Before Width: | Height: | Size: 243 KiB After Width: | Height: | Size: 245 KiB |
|
Before Width: | Height: | Size: 218 KiB After Width: | Height: | Size: 217 KiB |
|
Before Width: | Height: | Size: 227 KiB After Width: | Height: | Size: 227 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
@@ -2030,7 +2030,12 @@ test('en passkey kan registreres og logges ind med', async ({ browser, browserNa
|
|||||||
// Now sign out and back in with it. No email typed: the device knows which
|
// Now sign out and back in with it. No email typed: the device knows which
|
||||||
// account its key belongs to, which is also why this page cannot be used to
|
// account its key belongs to, which is also why this page cannot be used to
|
||||||
// find out who has an account here.
|
// find out who has an account here.
|
||||||
await page.getByRole('navigation', { name: 'Hovedmenu' }).getByText('Log ud').click();
|
// Signing out asks first now: one click arms it, a second within a few seconds
|
||||||
|
// does it. The whole account row is the button; its label changes to the prompt.
|
||||||
|
const signOut = page.getByRole('navigation', { name: 'Hovedmenu' }).locator('.user');
|
||||||
|
await signOut.click();
|
||||||
|
await expect(signOut).toContainText('Tryk igen for at logge ud');
|
||||||
|
await signOut.click();
|
||||||
// `exact`, because "Log ind" is a substring of "Log ind med en passkey" and
|
// `exact`, because "Log ind" is a substring of "Log ind med en passkey" and
|
||||||
// Playwright matches an accessible name loosely unless told otherwise.
|
// Playwright matches an accessible name loosely unless told otherwise.
|
||||||
await expect(page.getByRole('button', { name: 'Log ind', exact: true })).toBeVisible();
|
await expect(page.getByRole('button', { name: 'Log ind', exact: true })).toBeVisible();
|
||||||
|
|||||||
@@ -210,6 +210,52 @@
|
|||||||
--shadow-lg: 0 8px 32px rgb(0 0 0 / 0.4);
|
--shadow-lg: 0 8px 32px rgb(0 0 0 / 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Kul — the greys of Apple Notes' dark mode, to Kristian's own sampled values.
|
||||||
|
Three panel greys, lightest sidebar to darkest editor — the reverse of the usual
|
||||||
|
sunken-is-darkest order, which is why the editor gets its own --editor-bg rather
|
||||||
|
than sharing --surface-raised with the list. The accent turns amber, and the
|
||||||
|
selected menu item, selected note and section headings each get a fallback token
|
||||||
|
so this theme can hit its colours without touching any other. */
|
||||||
|
[data-theme='charcoal'] {
|
||||||
|
--ground: #1e1e1e;
|
||||||
|
--surface: #2a3033;
|
||||||
|
--surface-raised: #242b2e; /* the note list */
|
||||||
|
--surface-sunken: #2d3133; /* the menu / sidebar — lightest here */
|
||||||
|
--line: #34393b;
|
||||||
|
--line-strong: #414749;
|
||||||
|
|
||||||
|
--ink: #ffffff;
|
||||||
|
--ink-muted: #dcdcdc;
|
||||||
|
--ink-faint: #9ba0a2;
|
||||||
|
|
||||||
|
/* Amber, Apple's Notes accent. The bright value is the selected menu item; the
|
||||||
|
dark text rides on top of it. */
|
||||||
|
--accent: #ffce35;
|
||||||
|
--accent-hover: #ffd75a;
|
||||||
|
--accent-sunken: #ffce35;
|
||||||
|
--accent-ink: #1e1e1e;
|
||||||
|
|
||||||
|
/* Per-element, and only here — every other theme falls back to the shared token
|
||||||
|
in the var() calls that read these. */
|
||||||
|
--editor-bg: #1e1e1e; /* the text field, a shade below the list */
|
||||||
|
--note-on-bg: #a78c26; /* a selected note in the list — gold */
|
||||||
|
--note-on-ink: #1e1e1e; /* dark text on the gold */
|
||||||
|
--nav-active-ink: #1e1e1e; /* dark text on the amber menu item */
|
||||||
|
--heading-ink: #8a8e90; /* PROJEKTER and the group names — quiet grey */
|
||||||
|
--note-group-bg: #2d3133; /* day separators take the menu's resting grey, not the darker ground */
|
||||||
|
|
||||||
|
--p1: #cf6b6b;
|
||||||
|
--p2: #d69f5c;
|
||||||
|
--p3: #6b9ecf;
|
||||||
|
--p4: var(--ink-faint);
|
||||||
|
|
||||||
|
--danger: #cf6b6b;
|
||||||
|
--danger-sunken: #33201f;
|
||||||
|
|
||||||
|
--shadow: 0 1px 2px rgb(0 0 0 / 0.25);
|
||||||
|
--shadow-lg: 0 8px 32px rgb(0 0 0 / 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
/* Papir — warm light, closer to paper than to a screen. */
|
/* Papir — warm light, closer to paper than to a screen. */
|
||||||
[data-theme='paper'] {
|
[data-theme='paper'] {
|
||||||
--ground: #f6f1e7;
|
--ground: #f6f1e7;
|
||||||
@@ -375,9 +421,13 @@ button {
|
|||||||
søgefelt. */
|
søgefelt. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* A translucent wash of the accent, not a solid block and not the old near-invisible
|
||||||
|
tint. --accent-sunken sat a hair off the editor's own surface in dark, so a
|
||||||
|
selection could not be seen; a solid accent could, but read as a heavy slab. Mixing
|
||||||
|
the accent part-way into transparent lays a clear green film over the text while it
|
||||||
|
keeps its own colour — visible on white and on the dark surfaces alike. */
|
||||||
::selection {
|
::selection {
|
||||||
background: var(--accent-sunken);
|
background: color-mix(in oklab, var(--accent) 42%, transparent);
|
||||||
color: var(--ink);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Scrollbars, made quiet. The default on Windows is a wide grey slab that
|
/* Scrollbars, made quiet. The default on Windows is a wide grey slab that
|
||||||
|
|||||||
@@ -34,6 +34,23 @@
|
|||||||
location.href = '/';
|
location.href = '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Signing out is one click from a button the pointer passes over on its way to
|
||||||
|
// everything below it, and it drops you at the login screen — so it asks first.
|
||||||
|
// A second click within a few seconds confirms; anything else lets it lapse. Not
|
||||||
|
// a dialog: a two-step button is lighter and stays where the eye already is.
|
||||||
|
let confirmSignOut = $state(false);
|
||||||
|
let signOutTimer;
|
||||||
|
function onSignOutClick() {
|
||||||
|
if (confirmSignOut) {
|
||||||
|
clearTimeout(signOutTimer);
|
||||||
|
signOut();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
confirmSignOut = true;
|
||||||
|
clearTimeout(signOutTimer);
|
||||||
|
signOutTimer = setTimeout(() => (confirmSignOut = false), 3500);
|
||||||
|
}
|
||||||
|
|
||||||
let filters = $state([]);
|
let filters = $state([]);
|
||||||
let labels = $state([]);
|
let labels = $state([]);
|
||||||
|
|
||||||
@@ -1050,12 +1067,12 @@
|
|||||||
{#if !app.connected}
|
{#if !app.connected}
|
||||||
<span class="offline" title={t('nav.offlineHint')}>{t('nav.offline')}</span>
|
<span class="offline" title={t('nav.offlineHint')}>{t('nav.offline')}</span>
|
||||||
{/if}
|
{/if}
|
||||||
<button class="user" onclick={signOut}>
|
<button class="user" class:confirming={confirmSignOut} onclick={onSignOutClick}>
|
||||||
<span class="avatar" style="background: {app.user?.avatar_color}">
|
<span class="avatar" style="background: {app.user?.avatar_color}">
|
||||||
{app.user?.name?.[0]?.toUpperCase() ?? '?'}
|
{app.user?.name?.[0]?.toUpperCase() ?? '?'}
|
||||||
</span>
|
</span>
|
||||||
<span class="user-name">{app.user?.name}</span>
|
<span class="user-name">{confirmSignOut ? t('nav.signOutConfirm') : app.user?.name}</span>
|
||||||
<span class="signout">{t('nav.signOut')}</span>
|
<span class="signout">{confirmSignOut ? '' : t('nav.signOut')}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1091,14 +1108,16 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--s5);
|
gap: var(--s5);
|
||||||
padding: var(--s4) var(--s3);
|
/* A few pixels more air down each side than the rows strictly need, so the
|
||||||
|
menu breathes rather than sitting flush against its own edges. */
|
||||||
|
padding: var(--s4) calc(var(--s3) + 3px);
|
||||||
background: var(--surface-sunken);
|
background: var(--surface-sunken);
|
||||||
border-right: 1px solid var(--line);
|
border-right: 1px solid var(--line);
|
||||||
/* Selve bjælken ruller ikke længere — .scroller gør. `hidden` frem for
|
/* Selve bjælken ruller ikke længere — .scroller gør. `hidden` frem for
|
||||||
ingenting, fordi den stadig er den yderste kant: løber en række over,
|
ingenting, fordi den stadig er den yderste kant: løber en række over,
|
||||||
skal den klippes her og ikke skubbe kolonnen bredere. */
|
skal den klippes her og ikke skubbe kolonnen bredere. */
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding-left: max(var(--s3), env(safe-area-inset-left));
|
padding-left: max(calc(var(--s3) + 3px), env(safe-area-inset-left));
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1317,7 +1336,9 @@
|
|||||||
h2 {
|
h2 {
|
||||||
font-size: var(--menu-size);
|
font-size: var(--menu-size);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: var(--ink);
|
/* Kul sets these headings to a quiet grey (--heading-ink); every other theme
|
||||||
|
falls back to the reading ink and keeps them bold and bright. */
|
||||||
|
color: var(--heading-ink, var(--ink));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The heading's mark, in the muted ink so the bold name still leads. Sized and
|
/* The heading's mark, in the muted ink so the bold name still leads. Sized and
|
||||||
@@ -1572,7 +1593,10 @@
|
|||||||
in both themes. */
|
in both themes. */
|
||||||
a.active {
|
a.active {
|
||||||
background: var(--accent-sunken);
|
background: var(--accent-sunken);
|
||||||
color: var(--ink);
|
/* On a solid accent (Kul's amber menu item) the label goes dark via
|
||||||
|
--nav-active-ink; on the tinted accent-sunken every other theme uses, it
|
||||||
|
falls back to the reading ink. */
|
||||||
|
color: var(--nav-active-ink, var(--ink));
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1695,6 +1719,16 @@
|
|||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Asking to confirm: the row goes to the danger tint and the name is replaced by
|
||||||
|
"click again", so the second click is plainly the one that signs out. */
|
||||||
|
.user.confirming {
|
||||||
|
background: var(--danger-sunken);
|
||||||
|
}
|
||||||
|
|
||||||
|
.user.confirming .user-name {
|
||||||
|
color: var(--danger);
|
||||||
|
}
|
||||||
|
|
||||||
.avatar {
|
.avatar {
|
||||||
width: 22px;
|
width: 22px;
|
||||||
height: 22px;
|
height: 22px;
|
||||||
|
|||||||
@@ -228,13 +228,21 @@
|
|||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
padding: var(--s3) var(--s2);
|
padding: var(--s3) var(--s2);
|
||||||
border-bottom: 1px solid var(--line);
|
border-bottom: 1px solid var(--line);
|
||||||
|
border-radius: var(--radius);
|
||||||
transition:
|
transition:
|
||||||
opacity var(--medium) var(--ease),
|
opacity var(--medium) var(--ease),
|
||||||
transform var(--medium) var(--ease);
|
transform var(--medium) var(--ease);
|
||||||
}
|
}
|
||||||
|
|
||||||
.row:hover {
|
/* Hover only where there is a real pointer. On a touch screen a :hover on the tap
|
||||||
background: var(--surface);
|
target makes iOS spend the first tap applying the hover and only open on the
|
||||||
|
second — the "double-tap" on iPhone. With no hover to apply, the first tap opens
|
||||||
|
the task. The rounded corners are on the row itself, so the highlight is a
|
||||||
|
rounded box like a note in the list. */
|
||||||
|
@media (hover: hover) {
|
||||||
|
.row:hover {
|
||||||
|
background: var(--surface);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The exit: a short lift and fade, so completing something reads as the task
|
/* The exit: a short lift and fade, so completing something reads as the task
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ export const da = {
|
|||||||
'nav.calendar': 'Kalender',
|
'nav.calendar': 'Kalender',
|
||||||
'nav.settings': 'Indstillinger',
|
'nav.settings': 'Indstillinger',
|
||||||
'nav.signOut': 'Log ud',
|
'nav.signOut': 'Log ud',
|
||||||
|
'nav.signOutConfirm': 'Tryk igen for at logge ud',
|
||||||
'nav.main': 'Hovedmenu',
|
'nav.main': 'Hovedmenu',
|
||||||
'nav.search': 'Søg',
|
'nav.search': 'Søg',
|
||||||
'nav.searchLong': 'Søg i opgaver og projekter',
|
'nav.searchLong': 'Søg i opgaver og projekter',
|
||||||
@@ -843,6 +844,8 @@ export const da = {
|
|||||||
// --- the themes -------------------------------------------------------------------
|
// --- the themes -------------------------------------------------------------------
|
||||||
'theme.dark': 'Nordlys',
|
'theme.dark': 'Nordlys',
|
||||||
'theme.darkNote': 'Mørk med grøn accent.',
|
'theme.darkNote': 'Mørk med grøn accent.',
|
||||||
|
'theme.charcoal': 'Kul',
|
||||||
|
'theme.charcoalNote': 'Neutral mørkegrå.',
|
||||||
'theme.dusk': 'Skumring',
|
'theme.dusk': 'Skumring',
|
||||||
'theme.duskNote': 'Mørk og varm, med rav.',
|
'theme.duskNote': 'Mørk og varm, med rav.',
|
||||||
'theme.light': 'Dagslys',
|
'theme.light': 'Dagslys',
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ export const en = {
|
|||||||
'nav.calendar': 'Calendar',
|
'nav.calendar': 'Calendar',
|
||||||
'nav.settings': 'Settings',
|
'nav.settings': 'Settings',
|
||||||
'nav.signOut': 'Sign out',
|
'nav.signOut': 'Sign out',
|
||||||
|
'nav.signOutConfirm': 'Click again to sign out',
|
||||||
'nav.main': 'Main menu',
|
'nav.main': 'Main menu',
|
||||||
'nav.search': 'Search',
|
'nav.search': 'Search',
|
||||||
'nav.searchLong': 'Search tasks and projects',
|
'nav.searchLong': 'Search tasks and projects',
|
||||||
@@ -836,6 +837,8 @@ export const en = {
|
|||||||
// --- the themes -------------------------------------------------------------------
|
// --- the themes -------------------------------------------------------------------
|
||||||
'theme.dark': 'Northern lights',
|
'theme.dark': 'Northern lights',
|
||||||
'theme.darkNote': 'Dark, with a green accent.',
|
'theme.darkNote': 'Dark, with a green accent.',
|
||||||
|
'theme.charcoal': 'Charcoal',
|
||||||
|
'theme.charcoalNote': 'Neutral dark grey.',
|
||||||
'theme.dusk': 'Dusk',
|
'theme.dusk': 'Dusk',
|
||||||
'theme.duskNote': 'Dark and warm, with amber.',
|
'theme.duskNote': 'Dark and warm, with amber.',
|
||||||
'theme.light': 'Daylight',
|
'theme.light': 'Daylight',
|
||||||
|
|||||||
@@ -1006,6 +1006,7 @@ export const completedView = new CompletedView();
|
|||||||
*/
|
*/
|
||||||
export const THEMES = [
|
export const THEMES = [
|
||||||
{ id: 'dark', name: 'theme.dark', note: 'theme.darkNote', dark: true },
|
{ id: 'dark', name: 'theme.dark', note: 'theme.darkNote', dark: true },
|
||||||
|
{ id: 'charcoal', name: 'theme.charcoal', note: 'theme.charcoalNote', dark: true },
|
||||||
{ id: 'dusk', name: 'theme.dusk', note: 'theme.duskNote', dark: true },
|
{ id: 'dusk', name: 'theme.dusk', note: 'theme.duskNote', dark: true },
|
||||||
{ id: 'light', name: 'theme.light', note: 'theme.lightNote', dark: false },
|
{ id: 'light', name: 'theme.light', note: 'theme.lightNote', dark: false },
|
||||||
{ id: 'paper', name: 'theme.paper', note: 'theme.paperNote', dark: false },
|
{ id: 'paper', name: 'theme.paper', note: 'theme.paperNote', dark: false },
|
||||||
|
|||||||
@@ -707,7 +707,10 @@
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="notes">
|
<!-- `has-note` drives the phone layout: one column, showing the list until a note
|
||||||
|
is opened and the editor once one is. On a wide screen both are always up and
|
||||||
|
the class does nothing. -->
|
||||||
|
<div class="notes" class:has-note={selectedId}>
|
||||||
<aside>
|
<aside>
|
||||||
<div class="head">
|
<div class="head">
|
||||||
<h1>{t('notes.title')}</h1>
|
<h1>{t('notes.title')}</h1>
|
||||||
@@ -916,7 +919,15 @@
|
|||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<section class="editor">
|
<section class="editor">
|
||||||
{#if selected}
|
{#if selectedId}
|
||||||
|
<!-- Keyed on the id, which is set the instant a row is tapped — not on the
|
||||||
|
loaded note, which arrives a moment later. On a phone that moment was the
|
||||||
|
whole bug: the pane did not switch until the body had loaded, so the first
|
||||||
|
tap looked like nothing and people tapped again. -->
|
||||||
|
<!-- Phone only (hidden on a wide screen by CSS): the way back to the list,
|
||||||
|
since there the editor fills the screen and the list is not beside it. -->
|
||||||
|
<button class="back" onclick={() => open(null)}>‹ {t('notes.title')}</button>
|
||||||
|
{#if selected}
|
||||||
<NoteEditor
|
<NoteEditor
|
||||||
note={selected}
|
note={selected}
|
||||||
notes={notes}
|
notes={notes}
|
||||||
@@ -1050,6 +1061,12 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
{:else}
|
||||||
|
<!-- Chosen, but its full text is still loading. Keep the pane (so the tap
|
||||||
|
felt like it landed) and stay quiet — the "pick a note" line is for
|
||||||
|
when nothing is chosen at all, not for this half-second. -->
|
||||||
|
<p class="empty" aria-busy="true"></p>
|
||||||
|
{/if}
|
||||||
{:else}
|
{:else}
|
||||||
<p class="empty">{t('notes.pickOne')}</p>
|
<p class="empty">{t('notes.pickOne')}</p>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -1068,8 +1085,9 @@
|
|||||||
against the sidebar's rule, which reads as a rendering fault rather than
|
against the sidebar's rule, which reads as a rendering fault rather than
|
||||||
as a layout. */
|
as a layout. */
|
||||||
/* Luft hele vejen rundt om arket. Højre og bund var nul, dengang editoren
|
/* Luft hele vejen rundt om arket. Højre og bund var nul, dengang editoren
|
||||||
ingen kant havde og ingenting kunne støde imod. */
|
ingen kant havde og ingenting kunne støde imod. Et par pixels mere om
|
||||||
padding: var(--s3) var(--s4) var(--s3) var(--s4);
|
notelisten, så kortet ikke ligger klods op ad menuen. */
|
||||||
|
padding: var(--s3) var(--s4) var(--s3) calc(var(--s4) + 3px);
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(220px, 300px) 1fr;
|
grid-template-columns: minmax(220px, 300px) 1fr;
|
||||||
gap: var(--s4);
|
gap: var(--s4);
|
||||||
@@ -1083,13 +1101,15 @@
|
|||||||
gap: var(--s2);
|
gap: var(--s2);
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
border-right: 1px solid var(--line);
|
/* A rounded card, the same corner and border as the editor beside it — the
|
||||||
padding-right: var(--s3);
|
list is its own sheet, not a column ruled off the page. */
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
border-radius: var(--radius);
|
||||||
/* White in light, a nuance lighter than the ground in dark — the note list
|
/* White in light, a nuance lighter than the ground in dark — the note list
|
||||||
is a surface you read down, so it lifts off the page like the editor does.
|
is a surface you read down, so it lifts off the page like the editor does.
|
||||||
--surface-raised is #fff in the light themes and one step up in the dark. */
|
--surface-raised is #fff in the light themes and one step up in the dark. */
|
||||||
background: var(--surface-raised);
|
background: var(--surface-raised);
|
||||||
padding-left: var(--s3);
|
padding: var(--s3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.head {
|
.head {
|
||||||
@@ -1386,7 +1406,10 @@
|
|||||||
top: 0;
|
top: 0;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
margin: 0 0 var(--s1);
|
margin: 0 0 var(--s1);
|
||||||
background: var(--ground);
|
/* --ground everywhere but Kul, where the ground is the darkest thing on screen
|
||||||
|
and a day separator on it reads as a dark bar. There it takes the menu's own
|
||||||
|
resting colour instead, via --note-group-bg. */
|
||||||
|
background: var(--note-group-bg, var(--ground));
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1472,13 +1495,38 @@
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.row:hover {
|
/* Pointer only. On a touch screen a :hover on the tap target costs a tap — iOS
|
||||||
background: var(--surface);
|
spends the first applying the hover and opens on the second. Gated, the first
|
||||||
|
tap opens the note. The row's buttons are shown outright on touch below, since
|
||||||
|
there is no hover to reveal them. */
|
||||||
|
@media (hover: hover) {
|
||||||
|
.row:hover {
|
||||||
|
background: var(--surface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (hover: none) {
|
||||||
|
.star,
|
||||||
|
.archive-one {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.row.on {
|
.row.on {
|
||||||
background: var(--surface-raised);
|
background: var(--note-on-bg, var(--surface-raised));
|
||||||
color: var(--ink);
|
color: var(--note-on-ink, var(--ink));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* On a themed selection colour (Kul's gold), the row's own quieter tiers go dark
|
||||||
|
too, or the date and the filed line vanish into it. Other themes have no
|
||||||
|
--note-on-ink, so these fall back to their normal muted inks. */
|
||||||
|
.row.on .when,
|
||||||
|
.row.on .filed {
|
||||||
|
color: var(--note-on-ink, var(--ink-muted));
|
||||||
|
}
|
||||||
|
|
||||||
|
.row.on .filed-icon {
|
||||||
|
color: var(--note-on-ink, var(--ink-faint));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Samme størrelse som en opgavetitel. En note og en opgave er to ting af samme
|
/* Samme størrelse som en opgavetitel. En note og en opgave er to ting af samme
|
||||||
@@ -1574,8 +1622,10 @@
|
|||||||
min-height: 0;
|
min-height: 0;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
/* A nuance lighter than the ground in dark, still white in light — matches
|
/* A nuance lighter than the ground in dark, still white in light — matches
|
||||||
the note list beside it so the two read as one writing surface. */
|
the note list beside it so the two read as one writing surface. Kul gives
|
||||||
background: var(--surface-raised);
|
the text field its own darker grey via --editor-bg; other themes fall back
|
||||||
|
to the shared surface so the list and the editor stay the same colour. */
|
||||||
|
background: var(--editor-bg, var(--surface-raised));
|
||||||
border: 1px solid var(--line);
|
border: 1px solid var(--line);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
/* Luft nok til at teksten ikke rører kanten.
|
/* Luft nok til at teksten ikke rører kanten.
|
||||||
@@ -1894,14 +1944,48 @@
|
|||||||
font-size: var(--text-sm);
|
font-size: var(--text-sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The way back to the list on a phone — an iOS-style "‹ Noter" at the top of the
|
||||||
|
editor. Hidden on a wide screen, where the list is always beside the editor. */
|
||||||
|
.back {
|
||||||
|
display: none;
|
||||||
|
align-self: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--s1);
|
||||||
|
margin-bottom: var(--s2);
|
||||||
|
padding: var(--s1) 0;
|
||||||
|
font-size: var(--text-base);
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 700px) {
|
@media (max-width: 700px) {
|
||||||
.notes {
|
.notes {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
|
padding: 0;
|
||||||
|
gap: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
aside {
|
/* One pane at a time. The two-column card layout has no room on a phone, so
|
||||||
border-right: 0;
|
the list shows until a note is opened and the editor takes over once one is
|
||||||
padding-right: 0;
|
— the back button is the way between them. Without this the editor stacked
|
||||||
|
below a full-height list, so a tapped note opened out of sight. */
|
||||||
|
.notes.has-note aside {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notes:not(.has-note) .editor {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Full-bleed: the card border and rounded corners are for sitting beside
|
||||||
|
another card, and on one column there is nothing beside it. */
|
||||||
|
aside,
|
||||||
|
.editor {
|
||||||
|
border: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back {
|
||||||
|
display: inline-flex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||