feat: "Heute" start page with one next step, clear task states and motion levels
Start page (AuDHD-oriented, per the agreed "Heute zuerst" layout): - One highlighted next step: started work first (easy re-entry after an interruption), then overdue, due today, then urgent undated tasks. Primary action "Erledigt", secondary "Beginnen", link to the related colony/apiary/queen. - "Außerdem heute": at most five further tasks with a large honey-cell checkbox; undated automatic suggestions are included so a queenless colony does not sit unseen in the full list. - Completing is the one authored motion moment: the cell fills, the tick draws, the row folds away and the next step arrives with a short focus pull. Every completion can be undone from the toast (10 s), restoring the previous status. - Status is shown as icon plus word (never colour alone); tasks created by automation carry a "Vorschlag" badge, recurring and inspection tasks their own - a suggestion never looks like work already done. - Friendly empty, loading and error states; key figures moved into a compact overview below; overdue tasks are no longer listed twice. Motion: per-device setting Voll / Dezent / Aus in the profile (default Voll); the OS reduce-motion setting always lowers Voll to Dezent. New 44 px "touch" button size for gloves at the apiary; themed text selection and caret. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
5c2ea7bf1e
commit
f9374a135a
14 files changed
+1104
-112
No files matched your search
@@ -198,4 +198,179 @@
|
||||
font-family: var(--font-heading);
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
::selection {
|
||||
background: color-mix(in oklch, var(--primary) 28%, transparent);
|
||||
color: var(--foreground);
|
||||
}
|
||||
input,
|
||||
textarea {
|
||||
caret-color: var(--primary);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
Motion levels (see lib/motion/motion-preference.ts)
|
||||
html[data-motion] = full | subtle | off, chosen per device in the profile.
|
||||
The OS "reduce motion" setting always wins over "full".
|
||||
`motion-full:` = spatial movement allowed (level full AND system allows).
|
||||
------------------------------------------------------------------------ */
|
||||
@custom-variant motion-full {
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
&:where(:root:not([data-motion="subtle"]):not([data-motion="off"]) *) {
|
||||
@slot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:root {
|
||||
--ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}
|
||||
|
||||
/* Off: every state change is instant. Colour and icon still carry the state. */
|
||||
:root[data-motion="off"] *,
|
||||
:root[data-motion="off"] *::before,
|
||||
:root[data-motion="off"] *::after {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
transition-delay: 0ms !important;
|
||||
}
|
||||
|
||||
/* Subtle / system reduce: keep fades, drop movement. */
|
||||
:root[data-motion="subtle"] .motion-safe\:animate-page-in {
|
||||
animation-name: fade-in;
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.motion-safe\:animate-page-in {
|
||||
animation: fade-in 160ms ease-out;
|
||||
}
|
||||
}
|
||||
:root[data-motion="subtle"] [data-slot="card"] {
|
||||
translate: none !important;
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* --- Task completion: the one authored moment ------------------------------
|
||||
The honey cell fills, the tick draws itself, then the row folds away. */
|
||||
.honey-check {
|
||||
position: relative;
|
||||
display: inline-grid;
|
||||
place-items: center;
|
||||
flex-shrink: 0;
|
||||
width: 2.75rem;
|
||||
height: 2.75rem;
|
||||
border-radius: 9999px;
|
||||
color: var(--primary-foreground);
|
||||
outline: none;
|
||||
}
|
||||
.honey-check::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0.375rem;
|
||||
border-radius: 0.6rem;
|
||||
border: 2px solid color-mix(in oklch, var(--primary) 65%, var(--border));
|
||||
background: var(--card);
|
||||
transition:
|
||||
border-color 150ms ease-out,
|
||||
background-color 150ms ease-out;
|
||||
}
|
||||
.honey-check::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0.375rem;
|
||||
border-radius: 0.6rem;
|
||||
background: var(--gradient-honey);
|
||||
clip-path: circle(0% at 50% 60%);
|
||||
transition: clip-path 420ms var(--ease-out-expo);
|
||||
}
|
||||
.honey-check:hover::before {
|
||||
border-color: var(--primary);
|
||||
background: color-mix(in oklch, var(--primary) 8%, var(--card));
|
||||
}
|
||||
.honey-check:focus-visible::before {
|
||||
box-shadow: 0 0 0 3px color-mix(in oklch, var(--ring) 45%, transparent);
|
||||
}
|
||||
.honey-check svg {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
width: 1.1rem;
|
||||
height: 1.1rem;
|
||||
stroke-dasharray: 24;
|
||||
stroke-dashoffset: 24;
|
||||
transition: stroke-dashoffset 260ms var(--ease-out-expo) 160ms;
|
||||
}
|
||||
.honey-check[aria-checked="true"]::after {
|
||||
clip-path: circle(75% at 50% 60%);
|
||||
}
|
||||
.honey-check[aria-checked="true"] svg {
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
|
||||
.today-row {
|
||||
display: grid;
|
||||
grid-template-rows: 1fr;
|
||||
opacity: 1;
|
||||
transition:
|
||||
grid-template-rows 320ms var(--ease-out-expo) 380ms,
|
||||
opacity 220ms ease-out 360ms;
|
||||
}
|
||||
.today-row > * {
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.today-row[data-leaving="true"] {
|
||||
grid-template-rows: 0fr;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/* The next step changes: bring the new one in with a short focus pull. */
|
||||
@keyframes next-step-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
filter: blur(6px);
|
||||
transform: translateY(8px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
filter: blur(0);
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
@keyframes next-step-fade {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.next-step-enter {
|
||||
animation: next-step-in 480ms var(--ease-out-expo);
|
||||
}
|
||||
:root[data-motion="subtle"] .next-step-enter {
|
||||
animation: next-step-fade 200ms ease-out;
|
||||
}
|
||||
:root[data-motion="subtle"] .today-row,
|
||||
:root[data-motion="subtle"] .honey-check::after {
|
||||
transition-duration: 120ms;
|
||||
transition-delay: 0ms;
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.next-step-enter {
|
||||
animation: next-step-fade 200ms ease-out;
|
||||
}
|
||||
.today-row,
|
||||
.honey-check::after,
|
||||
.honey-check svg {
|
||||
transition-duration: 120ms;
|
||||
transition-delay: 0ms;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user