Compare commits

...

3 Commits

Author SHA1 Message Date
2f362a7e56 Add titles to menu
Some checks failed
Build and Deploy / build-and-push (push) Failing after 1m15s
2026-04-21 22:44:08 +02:00
e914f93781 Liquid glass - continuation 2026-04-21 22:28:19 +02:00
5499476a17 Liquid glass - first try 2026-04-21 22:01:07 +02:00
6 changed files with 184 additions and 43 deletions

View File

@@ -476,6 +476,90 @@
inset 0 2px 7px rgba(var(--overlay-rgb), 0.18),
inset 0 -1px 2px rgba(255, 255, 255, 0.03) !important;
}
#planner-view #planner-cal-bar {
position: absolute !important;
top: 0;
left: 0;
right: 0;
margin-top: 0 !important;
z-index: 20;
background: rgba(255, 255, 255, 0.5) !important;
border-bottom: 1px solid rgba(var(--line-rgb), 0.08) !important;
backdrop-filter: blur(28px) saturate(180%);
-webkit-backdrop-filter: blur(28px) saturate(180%);
}
.dark #planner-view #planner-cal-bar {
background: rgba(35, 34, 32, 0.5) !important;
border-bottom: 1px solid rgba(255, 255, 255, 0.06) !important;
}
#planner-view #calendar-swipe-zone,
#planner-view #calendar-week-wrap,
#planner-view #calendar-month-wrap {
background: transparent !important;
}
#planner-view #planner-scroll {
padding-top: 10rem !important;
}
#planner-meal-slots .planner-add-meal {
background: rgba(var(--overlay-rgb), 0.05) !important;
border: 1px solid rgba(255, 255, 255, 0.28) !important;
color: rgb(var(--text-body-soft-rgb)) !important;
backdrop-filter: blur(18px) saturate(180%);
-webkit-backdrop-filter: blur(18px) saturate(180%);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.4),
inset 0 -1px 0 rgba(var(--overlay-rgb), 0.06),
0 1px 3px rgba(var(--overlay-rgb), 0.08);
transition: background-color 160ms ease, transform 160ms ease;
}
#planner-meal-slots .planner-add-meal:hover {
background: rgba(var(--overlay-rgb), 0.1) !important;
transform: translateY(-1px);
}
#planner-meal-slots .planner-add-meal:active {
transform: scale(0.96);
}
.dark #planner-meal-slots .planner-add-meal {
background: rgba(255, 255, 255, 0.06) !important;
border: 1px solid rgba(255, 255, 255, 0.12) !important;
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.12),
inset 0 -1px 0 rgba(0, 0, 0, 0.22),
0 1px 3px rgba(0, 0, 0, 0.2);
}
.dark #planner-meal-slots .planner-add-meal:hover {
background: rgba(255, 255, 255, 0.1) !important;
}
#planner-meal-slots > div[data-slot-id] {
box-shadow:
0 2px 4px rgba(var(--overlay-rgb), 0.08),
0 14px 32px rgba(var(--overlay-rgb), 0.18) !important;
}
#planner-meal-slots > div[data-slot-id] > div:first-child {
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.55);
}
.dark #planner-meal-slots > div[data-slot-id] {
box-shadow:
0 2px 4px rgba(0, 0, 0, 0.22),
0 14px 32px rgba(0, 0, 0, 0.4) !important;
}
.dark #planner-meal-slots > div[data-slot-id] > div:first-child {
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
}
#planner-meal-slots .planner-kcal-pill {
background: rgba(var(--overlay-rgb), 0.05);
border: 1px solid rgba(255, 255, 255, 0.28);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.4),
inset 0 -1px 0 rgba(var(--overlay-rgb), 0.06);
}
.dark #planner-meal-slots .planner-kcal-pill {
background: rgba(255, 255, 255, 0.06);
border: 1px solid rgba(255, 255, 255, 0.12);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.12),
inset 0 -1px 0 rgba(0, 0, 0, 0.22);
}
#planner-picker-search {
appearance: none;
-webkit-appearance: none;
@@ -545,20 +629,33 @@
position: relative;
box-sizing: border-box;
width: min(calc(100% - 2.4rem), 24.5rem);
height: 3.34rem;
height: 3.72rem;
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
align-items: stretch;
gap: 0.06rem;
padding: 0.22rem;
padding: 0.42rem;
border-radius: 1.68rem;
background: rgb(var(--card-rgb));
border: 1px solid rgb(var(--border-card-rgb));
background: rgba(255, 255, 255, 0.2);
border: 1px solid rgba(255, 255, 255, 0.32);
backdrop-filter: blur(28px) saturate(180%);
-webkit-backdrop-filter: blur(28px) saturate(180%);
box-shadow:
inset 0 1px 8px rgba(var(--overlay-rgb), 0.15),
var(--shadow-shell);
inset 0 1px 0 rgba(255, 255, 255, 0.6),
inset 0 -1px 0 rgba(var(--overlay-rgb), 0.06),
0 8px 20px rgba(var(--overlay-rgb), 0.16),
0 22px 52px rgba(var(--overlay-rgb), 0.24);
pointer-events: auto;
}
.dark #app-bottom-nav .bottom-dock {
background: rgba(255, 255, 255, 0.04);
border: 1px solid rgba(255, 255, 255, 0.12);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.24),
inset 0 -1px 0 rgba(0, 0, 0, 0.22),
0 10px 24px rgba(0, 0, 0, 0.36),
0 26px 60px rgba(0, 0, 0, 0.46);
}
#app-bottom-nav .nav-slot {
min-width: 0;
height: 100%;
@@ -581,6 +678,8 @@
display: inline-flex;
align-items: center;
justify-content: center;
flex-direction: column;
gap: 0.24rem;
flex: 0 0 auto;
color: rgba(var(--text-primary-rgb), 0.94);
cursor: pointer;
@@ -595,6 +694,31 @@
font-size: 0.95rem;
line-height: 1;
}
#app-bottom-nav .nav-label {
display: none;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 0.62rem;
font-weight: 500;
line-height: 1.18;
}
#app-bottom-nav .nav-tab.is-active::after {
display: block;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 0.62rem;
font-weight: 500;
line-height: 1.18;
content: "";
}
#app-bottom-nav #nav-planner.is-active::after { content: "Planer"; }
#app-bottom-nav #nav-recipes.is-active::after { content: "Katalog"; }
#app-bottom-nav #nav-pantry.is-active::after { content: "Spiżarnia"; }
#app-bottom-nav #nav-shopping.is-active::after { content: "Zakupy"; }
#app-bottom-nav .nav-tab:hover,
#app-bottom-nav .nav-action:hover {
transform: translateY(-1px);
@@ -602,12 +726,28 @@
background: var(--hover-overlay) !important;
}
#app-bottom-nav .nav-tab.is-active {
width: 100%;
height: 100%;
width: min(100%, 5.2rem);
height: 2.82rem;
padding: 0.34rem 0.28rem 0.3rem;
color: rgb(var(--text-primary-rgb));
background: rgb(var(--app-bg-rgb)) !important;
border-radius: 1.46rem;
box-shadow: none !important;
background: rgba(var(--overlay-rgb), 0.38) !important;
border-radius: 1.05rem;
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.08),
inset 0 -1px 0 rgba(var(--overlay-rgb), 0.18) !important;
}
#app-bottom-nav .nav-tab.is-active .nav-label {
display: none;
}
#app-bottom-nav .nav-tab.is-active i {
font-size: 0.8rem;
}
.dark #app-bottom-nav .nav-tab.is-active {
color: #fff;
background: rgba(0, 0, 0, 0.42) !important;
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.06),
inset 0 -1px 0 rgba(0, 0, 0, 0.4) !important;
}
#app-bottom-nav .nav-tab:active,
#app-bottom-nav .nav-action:active {
@@ -625,9 +765,9 @@
}
#app-bottom-nav .bottom-dock {
width: min(calc(100% - 1.6rem), 22.5rem);
height: 3.12rem;
height: 3.48rem;
gap: 0.05rem;
padding: 0.2rem;
padding: 0.38rem;
border-radius: 1.56rem;
}
#app-bottom-nav .nav-tab,
@@ -637,9 +777,16 @@
border-radius: 1.28rem;
}
#app-bottom-nav .nav-tab.is-active {
height: 100%;
width: 100%;
border-radius: 1.36rem;
width: min(100%, 4.4rem);
height: 2.65rem;
padding: 0.3rem 0.22rem 0.27rem;
border-radius: 0.96rem;
}
#app-bottom-nav .nav-label {
font-size: 0.56rem;
}
#app-bottom-nav .nav-tab.is-active::after {
font-size: 0.56rem;
}
}
@@ -686,7 +833,7 @@
</div>
<script>
const APP_ASSET_VERSION = '20260417-svg7';
const APP_ASSET_VERSION = '20260421-nav-labels';
const APP_VERSION_STORAGE_KEY = 'recipe-app-asset-version';
const APP_VERSION_QUERY_KEY = 'appv';

View File

@@ -5,21 +5,25 @@ export function getBottomNavHTML() {
<div class="nav-slot">
<button type="button" data-tab="planner" id="nav-planner" class="nav-tab is-active" aria-label="Planer" aria-current="page">
<i class="far fa-calendar-alt" aria-hidden="true"></i>
<span class="nav-label">Planer</span>
</button>
</div>
<div class="nav-slot">
<button type="button" data-tab="recipes" id="nav-recipes" class="nav-tab" aria-label="Przepisy">
<button type="button" data-tab="recipes" id="nav-recipes" class="nav-tab" aria-label="Katalog">
<i class="fas fa-search" aria-hidden="true"></i>
<span class="nav-label">Katalog</span>
</button>
</div>
<div class="nav-slot">
<button type="button" data-tab="pantry" id="nav-pantry" class="nav-tab" aria-label="Spiżarnia">
<i class="fas fa-warehouse" aria-hidden="true"></i>
<span class="nav-label">Spiżarnia</span>
</button>
</div>
<div class="nav-slot" style="position:relative;">
<button type="button" data-tab="shopping" id="nav-shopping" class="nav-tab" aria-label="Zakupy">
<i class="fas fa-cart-shopping" aria-hidden="true"></i>
<span class="nav-label">Zakupy</span>
</button>
</div>
</div>

View File

@@ -74,8 +74,7 @@ export function getMealPlannerHTML() {
return `
<div id="planner-view" class="hidden flex flex-col h-full absolute inset-0 overflow-hidden bg-[rgb(var(--app-bg-rgb))] z-10">
<div id="planner-cal-bar" class="shrink-0 bg-[rgb(var(--app-bg-rgb))] border-b border-[rgb(var(--card-strong-rgb))] mt-3 relative z-10">
<div class="min-h-12 px-4 pt-4 pb-3 flex items-center justify-between gap-3 min-w-0">
<h1 class="min-w-0 flex-1 truncate" style="margin:0;padding:0;color:rgb(var(--text-emphasis-rgb));font-family:var(--app-font);font-size:18px;font-weight:700;line-height:1.2;letter-spacing:-0.02em;">Plan posiłków</h1>
<div class="min-h-12 px-4 pt-4 pb-3 flex items-center justify-end gap-3 min-w-0">
${createCalendarTopbarHTML({
todayId: 'cal-go-today',
wrapperClass: 'flex shrink-0 items-center justify-end',
@@ -440,8 +439,8 @@ function renderDayContent(state, onMealRemoved = null) {
<i class="fas fa-rotate-left text-[10px]" aria-hidden="true"></i>
</span>
</button>`
: `<button type="button" class="planner-edit-meal w-6 h-6 rounded-full border border-[rgb(var(--card-strong-rgb))] text-[rgb(var(--text-dim-rgb))] hover:text-[rgb(var(--text-body-rgb))] hover:border-[rgb(var(--text-subdued-rgb))] hover:bg-[rgb(var(--card-raised-rgb))] flex items-center justify-center transition-colors" data-slot-id="${slot.id}" data-entry-id="${eid}" aria-label="Edytuj ten przepis">
<i class="fas fa-pencil text-[9px]" aria-hidden="true"></i>
: `<button type="button" class="planner-edit-meal w-7 h-7 rounded-full border border-[rgb(var(--card-strong-rgb))] text-[rgb(var(--text-dim-rgb))] hover:text-[rgb(var(--text-body-rgb))] hover:border-[rgb(var(--text-subdued-rgb))] hover:bg-[rgb(var(--card-raised-rgb))] flex items-center justify-center transition-colors" data-slot-id="${slot.id}" data-entry-id="${eid}" aria-label="Edytuj ten przepis">
<i class="fas fa-pencil text-[10px]" aria-hidden="true"></i>
</button>`;
return `
<div class="relative overflow-hidden rounded-lg ${isPendingDelete ? 'ring-1 ring-white/5' : ''}" data-planner-swipe-row style="${rowStyle}" data-slot-id="${slot.id}" data-entry-id="${eid}" ${rowAttrs}>
@@ -476,32 +475,32 @@ function renderDayContent(state, onMealRemoved = null) {
const addBtn = `<button type="button" class="planner-add-meal w-7 h-7 rounded-full border border-[rgb(var(--card-strong-rgb))] text-[rgb(var(--text-dim-rgb))] flex items-center justify-center shrink-0" data-slot-id="${slot.id}" aria-label="Dodaj przepis"><i class="fas fa-plus text-[10px]"></i></button>`;
const kcalPill = slotKcal > 0
? `<span class="text-[10px] font-semibold tabular-nums shrink-0 px-2 py-0.5 rounded-full" style="background:rgb(var(--app-bg-rgb)); color:rgb(var(--text-body-soft-rgb));">${slotKcal} kcal</span>`
? `<span class="planner-kcal-pill text-[10px] font-semibold tabular-nums shrink-0 px-2 py-0.5 rounded-full" style="color:rgb(var(--text-body-soft-rgb));">${slotKcal} kcal</span>`
: '';
const filledCard = `
<div class="rounded-xl bg-[rgb(var(--card-rgb))] overflow-hidden" style="background:rgb(var(--card-rgb)) !important; box-shadow:var(--shadow-card);" data-slot-id="${slot.id}">
<div class="flex items-center gap-2 px-3 py-2.5 bg-[rgb(var(--card-rgb))]" style="background:rgb(var(--card-rgb)) !important;">
<div class="rounded-2xl bg-[rgb(var(--card-rgb))] overflow-hidden" style="background:rgb(var(--card-rgb)) !important; box-shadow:var(--shadow-card);" data-slot-id="${slot.id}">
<div class="flex items-center gap-2 px-4 py-3 bg-[rgb(var(--card-rgb))]" style="background:rgb(var(--card-rgb)) !important;">
<i class="fas ${slot.icon} w-7 text-center text-[13px] text-[rgb(var(--text-dim-rgb))] shrink-0" aria-hidden="true"></i>
<span class="text-[13px] font-semibold text-[rgb(var(--text-body-rgb))] truncate min-w-0">${slot.label}</span>
<span class="ml-auto"></span>
${kcalPill}
${addBtn}
</div>
${entries.length > 0 ? `<div class="px-2.5 pb-2.5 space-y-2 border-t border-[rgb(var(--card-strong-rgb))]" style="padding-top:0.625rem;">${entryCards}</div>` : ''}
${entries.length > 0 ? `<div class="px-3 pb-3 space-y-2 border-t border-[rgb(var(--card-strong-rgb))]" style="padding-top:0.75rem;">${entryCards}</div>` : ''}
</div>`;
if (entries.length > 0) return filledCard;
return `
<div class="rounded-xl bg-[rgb(var(--card-rgb))] overflow-hidden" style="background:rgb(var(--card-rgb)) !important; box-shadow:var(--shadow-card);" data-slot-id="${slot.id}">
<div class="flex items-center gap-2 px-3 py-2.5">
<div class="rounded-2xl bg-[rgb(var(--card-rgb))] overflow-hidden" style="background:rgb(var(--card-rgb)) !important; box-shadow:var(--shadow-card);" data-slot-id="${slot.id}">
<div class="flex items-center gap-2 px-4 py-3">
<i class="fas ${slot.icon} w-7 text-center text-[13px] text-[rgb(var(--text-dim-rgb))] shrink-0" aria-hidden="true"></i>
<span class="text-[13px] font-semibold text-[rgb(var(--text-body-rgb))] truncate min-w-0">${slot.label}</span>
<span class="ml-auto"></span>
${addBtn}
</div>
<div class="px-3 pb-2.5 -mt-0.5">
<div class="px-4 pb-3 -mt-0.5">
<p class="text-[11px] text-[rgb(var(--text-faint-rgb))] italic pl-9">Zaplanuj posiłek</p>
</div>
</div>`;
@@ -1096,15 +1095,11 @@ export function setupMealPlanner() {
};
/* ── calendar scroll shadow ─────────────────── */
const plannerScroll = document.getElementById('planner-scroll');
const calBar = document.getElementById('planner-cal-bar');
if (plannerScroll && calBar) {
if (calBar) {
const shadow = document.createElement('div');
shadow.style.cssText = 'position:absolute;left:0;right:0;bottom:-8px;height:8px;background:linear-gradient(to bottom,rgba(var(--overlay-rgb),0.25),transparent);opacity:0;transition:opacity 0.2s;pointer-events:none;';
shadow.style.cssText = 'position:absolute;left:0;right:0;bottom:-8px;height:8px;background:linear-gradient(to bottom,rgba(var(--overlay-rgb),0.25),transparent);pointer-events:none;';
calBar.appendChild(shadow);
plannerScroll.addEventListener('scroll', () => {
shadow.style.opacity = plannerScroll.scrollTop > 2 ? '1' : '0';
});
}
bindCalendarDayClicks(weekGrid, (date) => {

View File

@@ -174,9 +174,7 @@ export function getPantryHTML() {
<div id="pantry-topbar-outer" class="pointer-events-none absolute inset-x-0 top-0 z-[12] px-4 pt-4 pb-4" style="background:rgb(var(--app-bg-rgb)) !important; border:none !important;">
<div class="pointer-events-auto relative z-[1] w-full">
<div id="pantry-topbar" class="relative min-h-12">
<div id="pantry-default-row" class="flex min-h-12 items-center gap-2 transition-all duration-200" style="opacity:1; transform:translateY(0) scale(1);">
<h1 class="flex-1 min-w-0 truncate" style="margin:0;padding:0;color:rgb(var(--text-emphasis-rgb));font-family:var(--app-font);font-size:18px;font-weight:700;line-height:1.2;letter-spacing:-0.02em;">Zapasy</h1>
<div id="pantry-default-row" class="flex min-h-12 items-center justify-end gap-2 transition-all duration-200" style="opacity:1; transform:translateY(0) scale(1);">
<div id="pantry-horizon-wrap" class="relative shrink">
<button type="button" id="pantry-horizon-compact" class="min-w-0 max-w-[12rem] h-10 rounded-full flex items-center gap-1.5 px-2.5 transition-all" style="background:rgb(var(--card-rgb)) !important; border:1px solid rgb(var(--border-card-rgb)) !important; box-shadow:var(--shadow-shell) !important;">
<span id="pantry-horizon-compact-label" class="min-w-0 flex-1 text-left text-[13px] font-normal truncate" style="color:rgb(var(--text-body-rgb));"></span>

View File

@@ -115,9 +115,7 @@ export function getRecipeListHTML() {
<div class="pointer-events-auto relative z-[1] w-full">
<div id="recipe-topbar" class="relative min-h-12">
<div id="recipe-default-row" class="flex min-h-12 items-center gap-2 transition-all duration-200" style="opacity:1; transform:translateY(0) scale(1);">
<h1 class="min-w-0 flex-1 truncate" style="margin:0;padding:0;color:rgb(var(--text-emphasis-rgb));font-family:var(--app-font);font-size:18px;font-weight:700;line-height:1.2;letter-spacing:-0.02em;">Katalog przepisów</h1>
<div id="recipe-default-row" class="flex min-h-12 items-center justify-end gap-2 transition-all duration-200" style="opacity:1; transform:translateY(0) scale(1);">
<div id="recipe-filter-wrap" class="relative shrink-0">
<button type="button" id="recipe-filter-btn" class="relative w-11 h-11 rounded-full shrink-0 flex items-center justify-center transition-all duration-200" style="background:rgb(var(--card-rgb)); border:1px solid rgb(var(--border-card-rgb)); box-shadow:var(--shadow-shell); color:rgb(var(--text-body-rgb));" aria-label="Otwórz filtry">
<i class="fas fa-sliders-h text-[12px]" aria-hidden="true"></i>

View File

@@ -123,8 +123,7 @@ export function getShoppingListHTML() {
<div class="shrink-0 px-4 pt-5 pb-0">
<!-- title row + pill + bought button (position:relative anchors the popups) -->
<div class="flex items-center gap-2 mb-4" style="position:relative;">
<h1 class="flex-1 text-[18px] font-bold" style="color:rgb(var(--text-emphasis-rgb));">Lista zakupów</h1>
<div class="flex items-center justify-end gap-2 mb-4" style="position:relative;">
<button type="button" id="sl-range-pill" class="min-w-0 max-w-[10rem] h-10 rounded-full flex items-center gap-1.5 px-2.5 transition-all shrink" style="background:rgb(var(--card-rgb)); border:1px solid rgb(var(--border-card-rgb)); box-shadow:var(--shadow-shell);">
<span id="sl-range-label" class="min-w-0 flex-1 text-left text-[13px] font-normal truncate" style="color:rgb(var(--text-body-rgb));"></span>
<i id="sl-range-chevron" class="fas fa-chevron-down text-[10px] shrink-0 transition-transform duration-200" style="color:rgb(var(--text-dim-rgb));"></i>