UI Rework

This commit is contained in:
2026-01-24 21:30:08 +00:00
parent 4183d7f122
commit 1e8b7082a4
37 changed files with 4648 additions and 2754 deletions

View File

@@ -1,13 +1,16 @@
<script lang="ts">
import "../app.css";
import { onMount } from "svelte";
import { isTauri } from "@tauri-apps/api/core";
import CustomTabBar from "$lib/components/CustomTabBar.svelte";
import CameraScreen from "$lib/components/CameraScreen.svelte";
import { page } from "$app/stores";
import { goto } from "$app/navigation";
import Icon from "@iconify/svelte";
let { children } = $props();
let isApp = $state(false);
let isMobile = $state(false);
let isCameraActive = $state(false);
let recentItems = $state([
{
@@ -26,8 +29,20 @@
},
]);
function handleScanComplete(item: any) {
recentItems = [item, ...recentItems];
isCameraActive = false;
}
onMount(() => {
const checkMobile = () => {
isMobile = window.innerWidth < 768;
};
isApp = isTauri();
checkMobile();
window.addEventListener("resize", checkMobile);
if (isApp) {
document.body.classList.add("platform-native");
} else {
@@ -40,6 +55,7 @@
window.addEventListener("scan", handleScan);
return () => {
window.removeEventListener("scan", handleScan);
window.removeEventListener("resize", checkMobile);
};
});
@@ -55,25 +71,37 @@
];
</script>
{#if isApp}
<main class="app-container">
{@render children()}
</main>
<CustomTabBar currentRoute={$page.route.id || "/"} />
<svelte:head>
<title>Ethix - Truth in every scan</title>
<meta
name="description"
content="Scan products to reveal their true environmental impact. Join the community of eco-conscious shoppers making a difference."
/>
</svelte:head>
{#if isMobile}
<div class="mobile-container">
<main class="app-container">
<div class="content-wrapper">
{@render children()}
</div>
</main>
<CustomTabBar currentRoute={$page.route.id || "/"} />
</div>
{:else}
<nav class="desktop-nav">
<div class="nav-container">
<a href="/" class="nav-brand">
<div class="brand-icon">
<a href="/" class="logo-container">
<div class="logo-icon">
<img
src="/ethix-logo.png"
alt="Ethix Logo"
class="brand-logo-img"
class="logo-img"
/>
</div>
<div class="brand-content">
<h1 class="brand-title">Ethix</h1>
<p class="brand-tagline">Truth in every scan</p>
<div class="logo-text-wrapper">
<span class="logo-text">Ethix</span>
<span class="logo-subtitle">Truth in every scan</span>
</div>
</a>
<div class="nav-links">
@@ -83,51 +111,16 @@
class="nav-link"
class:active={$page.route.id === link.route}
>
<iconify-icon icon={link.icon} width="20"
></iconify-icon>
<Icon icon={link.icon} width="20" />
<span>{link.name}</span>
</a>
{/each}
<a href="/catalogue" class="catalogue-button">
<iconify-icon icon="ri:search-line" width="20"
></iconify-icon>
<Icon icon="ri:search-line" width="20" />
<span>Browse Catalogue</span>
</a>
</div>
</div>
<svg
class="cloud-bg cloud-far"
viewBox="0 0 2880 200"
preserveAspectRatio="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill="rgba(255,255,255,0.4)"
d="M0,0 L2880,0 L2880,150 Q2760,180 2640,155 Q2520,130 2400,160 Q2280,190 2160,165 Q2040,140 1920,170 Q1800,200 1680,170 Q1560,140 1440,165 Q1320,190 1200,160 Q1080,130 960,155 Q840,180 720,150 Q600,120 480,150 Q360,180 240,155 Q120,130 0,150 L0,0 Z"
/>
</svg>
<svg
class="cloud-bg cloud-back"
viewBox="0 0 2880 200"
preserveAspectRatio="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill="rgba(255,255,255,0.65)"
d="M0,0 L2880,0 L2880,130 Q2800,160 2720,140 Q2640,120 2560,145 Q2480,170 2400,150 Q2320,130 2240,155 Q2160,180 2080,160 Q2000,140 1920,165 Q1840,190 1760,165 Q1680,140 1600,160 Q1520,180 1440,155 Q1360,130 1280,150 Q1200,170 1120,145 Q1040,120 960,145 Q880,170 800,150 Q720,130 640,155 Q560,180 480,160 Q400,140 320,165 Q240,190 160,170 Q80,150 0,130 L0,0 Z"
/>
</svg>
<svg
class="cloud-bg cloud-front"
viewBox="0 0 2880 200"
preserveAspectRatio="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill="rgba(255,255,255,0.95)"
d="M0,0 L2880,0 L2880,100 Q2820,75 2760,95 Q2700,115 2640,90 Q2580,65 2520,90 Q2460,115 2400,95 Q2340,75 2280,100 Q2220,125 2160,105 Q2100,85 2040,110 Q1980,135 1920,110 Q1860,85 1800,105 Q1740,125 1680,100 Q1620,75 1560,95 Q1500,115 1440,90 Q1380,65 1320,90 Q1260,115 1200,95 Q1140,75 1080,100 Q1020,125 960,105 Q900,85 840,110 Q780,135 720,110 Q660,85 600,105 Q540,125 480,100 Q420,75 360,95 Q300,115 240,90 Q180,65 120,90 Q60,115 0,100 L0,0 Z"
/>
</svg>
</nav>
<main class="app-container">
@@ -137,6 +130,13 @@
</main>
{/if}
{#if isCameraActive}
<CameraScreen
onClose={() => (isCameraActive = false)}
onScanComplete={handleScanComplete}
/>
{/if}
<style>
:global(body) {
margin: 0;
@@ -146,15 +146,16 @@
-apple-system,
BlinkMacSystemFont,
sans-serif;
background-color: #000000;
background-color: #0c0c0c;
color: white;
overflow: hidden;
min-height: 100vh;
}
.web-container {
min-height: 80vh;
max-width: 1200px;
padding: 20px;
.mobile-container {
height: 100vh;
overflow-y: auto;
background-color: #051f18;
}
.app-container {
@@ -208,51 +209,47 @@
pointer-events: auto;
}
.nav-brand {
.logo-container {
display: flex;
align-items: center;
gap: 16px;
text-decoration: none;
transition: transform 0.2s;
}
.brand-icon {
background: white;
border-radius: 50%;
padding: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
width: 48px;
height: 48px;
.logo-container:hover {
transform: scale(1.02);
}
.logo-icon {
width: 56px;
height: 56px;
display: flex;
align-items: center;
justify-content: center;
}
.brand-logo-img {
width: 32px;
height: 32px;
object-fit: contain;
}
.brand-content {
.logo-text-wrapper {
display: flex;
flex-direction: column;
gap: 2px;
}
.brand-title {
.logo-text {
font-size: 24px;
font-weight: 900;
color: #1a1a1a;
margin: 0;
line-height: 1;
letter-spacing: -0.5px;
}
.brand-tagline {
font-size: 12px;
color: #555;
margin: 4px 0 0 0;
.logo-subtitle {
font-size: 11px;
font-weight: 600;
color: #4b5563;
text-transform: uppercase;
letter-spacing: 1px;
}
.nav-links {
display: flex;
align-items: center;
@@ -303,43 +300,9 @@
color: white;
}
.cloud-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 150px;
z-index: 1;
pointer-events: none;
overflow: hidden;
}
.cloud-far {
z-index: 1;
opacity: 0.8;
transform-origin: center;
animation: drift 60s ease-in-out infinite alternate;
}
.cloud-back {
z-index: 2;
opacity: 0.9;
transform-origin: center;
animation: drift 45s ease-in-out infinite alternate-reverse;
}
.cloud-front {
z-index: 3;
transform-origin: center;
animation: drift 30s ease-in-out infinite alternate;
}
@keyframes drift {
0% {
transform: scaleY(1) translateX(-20px);
}
100% {
transform: scaleY(1.05) translateX(20px);
}
.logo-img {
width: 48px;
height: 48px;
object-fit: contain;
}
</style>