aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/app.css107
-rw-r--r--src/lib/components/BestRef.svelte8
-rw-r--r--src/lib/components/GroceryRow.svelte71
-rw-r--r--src/lib/components/Row.svelte54
-rw-r--r--src/routes/+page.svelte9
-rw-r--r--src/routes/groceries/categories/+page.svelte6
-rw-r--r--src/routes/grocery/[id]/+page.svelte5
-rw-r--r--src/routes/projects/[id]/+page.svelte20
-rw-r--r--src/routes/projects/[projectId]/routine/[routineId]/+page.svelte10
9 files changed, 146 insertions, 144 deletions
diff --git a/src/app.css b/src/app.css
index 87817bd..daeffd7 100644
--- a/src/app.css
+++ b/src/app.css
@@ -15,113 +15,6 @@
gap: 0.5rem;
}
-/* Row containers */
-.item-row {
- display: flex;
- align-items: center;
- gap: 0.5rem;
-}
-
-.item-row--card {
- padding: 0.5rem 0.75rem;
- background: var(--surface);
- border-radius: 0.75rem;
- box-shadow: 0 1px 2px var(--shadow);
- transition: all 0.2s ease;
-}
-
-.item-row--card:hover {
- box-shadow: 0 2px 6px var(--shadow);
- transform: translateY(-1px);
-}
-
-.item-row--fixed {
- height: 2.75rem;
-}
-
-.item-row--ref {
- padding: 0.875rem 1rem;
- gap: 0.75rem;
- background: var(--surface);
- border-radius: 0.75rem;
- box-shadow: 0 1px 2px var(--shadow);
- transition: all 0.2s ease;
-}
-
-.item-row--ref:hover {
- box-shadow: 0 2px 6px var(--shadow);
- transform: translateY(-1px);
-}
-
-/* Buttons inside rows */
-.item-btn {
- width: 100%;
- text-align: left;
- padding: 0 0.875rem;
- height: 100%;
- border: none;
- border-radius: 0.75rem;
- background: var(--surface);
- font-size: 1rem;
- font-weight: 500;
- display: flex;
- align-items: center;
- transition: all 0.2s ease;
- box-shadow: 0 1px 2px var(--shadow);
-}
-
-.item-btn:hover {
- background: var(--surface-hover);
- box-shadow: 0 2px 6px var(--shadow-accent);
- transform: translateY(-1px);
-}
-
-.item-btn--grow {
- flex-grow: 1;
- width: auto;
-}
-
-/* Text */
-.item-text {
- display: flex;
- flex-direction: column;
- text-align: left;
- line-height: 1.2;
- gap: 0.0625rem;
- overflow: hidden;
-}
-
-.best-ref {
- font-size: 0.75rem;
- color: var(--text-secondary);
- font-weight: 400;
-}
-
-/* Links */
-.ref-link {
- width: 2.75rem;
- flex-shrink: 0;
- height: 2.75rem;
- aspect-ratio: 1;
- display: flex;
- align-items: center;
- justify-content: center;
- border-radius: 0.75rem;
- background: var(--surface);
- color: var(--text-secondary);
- text-decoration: none;
- font-size: 1rem;
- transition: all 0.2s ease;
- box-shadow: 0 1px 2px var(--shadow);
-}
-
-.ref-link:hover {
- background: var(--surface-hover);
- color: var(--accent);
- box-shadow: 0 2px 6px var(--shadow-accent);
- transform: translateY(-1px);
-}
-
/* Category heading */
.category-name {
font-size: 0.75rem;
diff --git a/src/lib/components/BestRef.svelte b/src/lib/components/BestRef.svelte
index e194876..baa04f8 100644
--- a/src/lib/components/BestRef.svelte
+++ b/src/lib/components/BestRef.svelte
@@ -14,3 +14,11 @@
 ({ref.qualityScore}/100)
{/if}
</span>
+
+<style>
+ .best-ref {
+ font-size: 0.75rem;
+ color: var(--text-secondary);
+ font-weight: 400;
+ }
+</style>
diff --git a/src/lib/components/GroceryRow.svelte b/src/lib/components/GroceryRow.svelte
index 3305afa..9a88e90 100644
--- a/src/lib/components/GroceryRow.svelte
+++ b/src/lib/components/GroceryRow.svelte
@@ -1,5 +1,6 @@
<script lang="ts">
import BestRef from '$lib/components/BestRef.svelte';
+ import Row from '$lib/components/Row.svelte';
import type { EnrichedGrocery } from '$lib/server/services/groceries';
let {
@@ -17,29 +18,29 @@
} = $props();
</script>
-<li class="item-row item-row--fixed">
+<Row variant="plain" style="height: 2.75rem;">
{#if selectable}
- <input type="checkbox" class="item-check" {checked} onchange={oncheck} />
+ <input type="checkbox" class="check" {checked} onchange={oncheck} />
{/if}
<button
- class="item-btn item-btn--grow"
+ class="toggle"
name="id"
value={item.id}
type="submit"
aria-pressed={item.checked}
>
- <span class="item-text">
+ <span class="label">
<span class:checked={item.checked}>{item.name}</span>
{#if item.bestRef}
<BestRef ref={item.bestRef} />
{/if}
</span>
</button>
- <a class="ref-link" href="/grocery/{item.id}?from={from}">&rarr;</a>
-</li>
+ <a class="open" href="/grocery/{item.id}?from={from}">&rarr;</a>
+</Row>
<style>
- .item-check {
+ .check {
width: 1.25rem;
height: 1.25rem;
accent-color: var(--accent);
@@ -52,4 +53,60 @@
color: var(--text-secondary);
font-weight: 400;
}
+
+ .toggle {
+ flex-grow: 1;
+ width: auto;
+ text-align: left;
+ padding: 0 0.875rem;
+ height: 100%;
+ border: none;
+ border-radius: 0.75rem;
+ background: var(--surface);
+ font-size: 1rem;
+ font-weight: 500;
+ display: flex;
+ align-items: center;
+ transition: all 0.2s ease;
+ box-shadow: 0 1px 2px var(--shadow);
+ }
+
+ .toggle:hover {
+ background: var(--surface-hover);
+ box-shadow: 0 2px 6px var(--shadow-accent);
+ transform: translateY(-1px);
+ }
+
+ .label {
+ display: flex;
+ flex-direction: column;
+ text-align: left;
+ line-height: 1.2;
+ gap: 0.0625rem;
+ overflow: hidden;
+ }
+
+ .open {
+ width: 2.75rem;
+ flex-shrink: 0;
+ height: 2.75rem;
+ aspect-ratio: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 0.75rem;
+ background: var(--surface);
+ color: var(--text-secondary);
+ text-decoration: none;
+ font-size: 1rem;
+ transition: all 0.2s ease;
+ box-shadow: 0 1px 2px var(--shadow);
+ }
+
+ .open:hover {
+ background: var(--surface-hover);
+ color: var(--accent);
+ box-shadow: 0 2px 6px var(--shadow-accent);
+ transform: translateY(-1px);
+ }
</style>
diff --git a/src/lib/components/Row.svelte b/src/lib/components/Row.svelte
new file mode 100644
index 0000000..e388392
--- /dev/null
+++ b/src/lib/components/Row.svelte
@@ -0,0 +1,54 @@
+<script lang="ts">
+ import type { Snippet } from 'svelte';
+ import type { HTMLLiAttributes } from 'svelte/elements';
+
+ let {
+ variant = 'card',
+ style,
+ children,
+ ...rest
+ }: {
+ variant?: 'card' | 'ref' | 'plain';
+ style?: string;
+ children: Snippet;
+ } & HTMLLiAttributes = $props();
+</script>
+
+<li class={variant} {style} {...rest}>
+ {@render children()}
+</li>
+
+<style>
+ li {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ }
+
+ .card {
+ padding: 0.5rem 0.75rem;
+ background: var(--surface);
+ border-radius: 0.75rem;
+ box-shadow: 0 1px 2px var(--shadow);
+ transition: all 0.2s ease;
+ }
+
+ .card:hover {
+ box-shadow: 0 2px 6px var(--shadow);
+ transform: translateY(-1px);
+ }
+
+ .ref {
+ padding: 0.875rem 1rem;
+ gap: 0.75rem;
+ background: var(--surface);
+ border-radius: 0.75rem;
+ box-shadow: 0 1px 2px var(--shadow);
+ transition: all 0.2s ease;
+ }
+
+ .ref:hover {
+ box-shadow: 0 2px 6px var(--shadow);
+ transform: translateY(-1px);
+ }
+</style>
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index 1adfb6b..66b3259 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -2,6 +2,7 @@
import { enhance } from '$app/forms';
import ScoreBadge from '$lib/components/ScoreBadge.svelte';
import Button from '$lib/components/Button.svelte';
+ import Row from '$lib/components/Row.svelte';
let { data, form } = $props();
@@ -32,12 +33,12 @@
<ul class="item-list">
{#each data.projects as entry (entry.project.id)}
- <li class="item-row item-row--card project-row">
+ <Row style="padding: 0.875rem 1rem;">
<a class="project-link" href="/projects/{entry.project.id}"
>{entry.project.name}</a
>
<ScoreBadge score={entry.healthScore} />
- </li>
+ </Row>
{/each}
</ul>
@@ -47,10 +48,6 @@
</main>
<style>
- .project-row {
- padding: 0.875rem 1rem;
- }
-
.project-link {
flex-grow: 1;
font-weight: 500;
diff --git a/src/routes/groceries/categories/+page.svelte b/src/routes/groceries/categories/+page.svelte
index 3d6d5b3..c2a3684 100644
--- a/src/routes/groceries/categories/+page.svelte
+++ b/src/routes/groceries/categories/+page.svelte
@@ -2,6 +2,7 @@
import { enhance } from '$app/forms';
import type { Category } from '$lib/server/services/types';
import Button from '$lib/components/Button.svelte';
+ import Row from '$lib/components/Row.svelte';
let { data, form } = $props();
let name = $state('');
@@ -72,8 +73,7 @@
<form method="POST" action="?/delete" use:enhance>
<ul class="item-list">
{#each localCategories as cat, index (cat.id)}
- <li
- class="item-row item-row--card"
+ <Row
draggable="true"
ondragstart={() => handleDragStart(index)}
ondragover={(e) => handleDragOver(e, index)}
@@ -85,7 +85,7 @@
<Button variant="ghost" name="id" value={cat.id} ariaLabel="Supprimer"
>&times;</Button
>
- </li>
+ </Row>
{/each}
</ul>
</form>
diff --git a/src/routes/grocery/[id]/+page.svelte b/src/routes/grocery/[id]/+page.svelte
index 8a0a479..54134f0 100644
--- a/src/routes/grocery/[id]/+page.svelte
+++ b/src/routes/grocery/[id]/+page.svelte
@@ -1,6 +1,7 @@
<script lang="ts">
import { enhance } from '$app/forms';
import Button from '$lib/components/Button.svelte';
+ import Row from '$lib/components/Row.svelte';
let { data, form } = $props();
let name = $state('');
@@ -143,7 +144,7 @@
<form method="POST" action="?/delete" use:enhance>
<ul class="item-list item-list--wide">
{#each data?.references ?? [] as ref (ref.id)}
- <li class="item-row item-row--ref">
+ <Row variant="ref">
<div class="ref-info">
<strong>{ref.reference}</strong>
{#if ref.price}
@@ -158,7 +159,7 @@
<Button variant="ghost" name="id" value={ref.id} ariaLabel="Supprimer"
>&times;</Button
>
- </li>
+ </Row>
{/each}
</ul>
</form>
diff --git a/src/routes/projects/[id]/+page.svelte b/src/routes/projects/[id]/+page.svelte
index 2efe05b..b48a331 100644
--- a/src/routes/projects/[id]/+page.svelte
+++ b/src/routes/projects/[id]/+page.svelte
@@ -5,6 +5,7 @@
import ScoreBadge from '$lib/components/ScoreBadge.svelte';
import StatusBadge from '$lib/components/StatusBadge.svelte';
import Button from '$lib/components/Button.svelte';
+ import Row from '$lib/components/Row.svelte';
import {
formatFrequency,
parseIntervalToDays,
@@ -102,7 +103,7 @@
<ul class="item-list">
{#each sorted(data.routines) as routine (routine.id)}
- <li class="item-row item-row--card routine-row">
+ <Row style="flex-wrap: wrap; padding: 0.75rem 1rem;">
<form method="POST" action="?/complete" use:enhance>
<input type="hidden" name="id" value={routine.id} />
<Button variant="ghost">
@@ -127,7 +128,7 @@
{/if}
</span>
</div>
- </li>
+ </Row>
{/each}
</ul>
@@ -158,9 +159,9 @@
/>
<ul class="item-list">
{#each filteredArchived as routine (routine.id)}
- <li class="item-row item-row--card archived-row">
+ <Row>
<a
- class="routine-name"
+ class="routine-name archived-name"
href="/projects/{data.project.id}/routine/{routine.id}"
>{routine.name}</a
>
@@ -168,7 +169,7 @@
{formatFrequency(routine.frequencyDays)} · archivée le
{formatDayMonth(routine.archivedAt)}
</span>
- </li>
+ </Row>
{/each}
</ul>
{#if filteredArchived.length === 0}
@@ -201,11 +202,6 @@
align-items: stretch;
}
- .routine-row {
- flex-wrap: wrap;
- padding: 0.75rem 1rem;
- }
-
.routine-info {
flex-grow: 1;
min-width: 0;
@@ -300,12 +296,12 @@
width: 100%;
}
- .archived-row .routine-name {
+ .archived-name {
flex-grow: 1;
color: var(--text-secondary);
}
- .archived-row .routine-name:hover {
+ .archived-name:hover {
color: var(--accent);
}
diff --git a/src/routes/projects/[projectId]/routine/[routineId]/+page.svelte b/src/routes/projects/[projectId]/routine/[routineId]/+page.svelte
index 867719a..55185cc 100644
--- a/src/routes/projects/[projectId]/routine/[routineId]/+page.svelte
+++ b/src/routes/projects/[projectId]/routine/[routineId]/+page.svelte
@@ -4,6 +4,7 @@
import ScoreBadge from '$lib/components/ScoreBadge.svelte';
import StatusBadge from '$lib/components/StatusBadge.svelte';
import Button from '$lib/components/Button.svelte';
+ import Row from '$lib/components/Row.svelte';
import {
formatFrequency,
parseIntervalToDays,
@@ -176,14 +177,14 @@
<ul class="item-list">
{#each data.completions as c (c.id)}
- <li class="item-row item-row--card completion-row">
+ <Row style="flex-wrap: wrap; gap: 0.25rem 0.75rem;">
<span class="completion-date">
{formatDayMonthYear(c.doneAt)}
</span>
{#if c.note}
<span class="completion-note">{c.note}</span>
{/if}
- </li>
+ </Row>
{/each}
</ul>
@@ -259,11 +260,6 @@
flex: 1;
}
- .completion-row {
- flex-wrap: wrap;
- gap: 0.25rem 0.75rem;
- }
-
.completion-date {
font-weight: 500;
}