Compare commits

...

3 Commits

Author SHA1 Message Date
Ilia Mashkov
2b7f21711b feat(BreadcrumbHeader): add a logo and change the animation
All checks were successful
Workflow / build (push) Successful in 55s
2026-02-04 10:49:13 +03:00
Ilia Mashkov
69ae955131 feat(Page): move breadcrumb header to the layout and add a logo section 2026-02-04 10:48:40 +03:00
Ilia Mashkov
12844432ac feat(Section): add a snippet prop for description 2026-02-04 10:47:04 +03:00
4 changed files with 46 additions and 21 deletions

View File

@@ -10,6 +10,7 @@
*
* - Footer area (currently empty, reserved for future use)
*/
import { BreadcrumbHeader } from '$entities/Breadcrumb';
import favicon from '$shared/assets/favicon.svg';
import { ScrollArea } from '$shared/shadcn/ui/scroll-area';
import { Provider as TooltipProvider } from '$shared/shadcn/ui/tooltip';
@@ -35,10 +36,16 @@ let { children }: Props = $props();
href="https://fonts.googleapis.com/css2?family=Karla:ital,wght@0,200..800;1,200..800&display=swap"
rel="stylesheet"
>
<link
href="https://fonts.googleapis.com/css2?family=Barlow:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Karla:wght@300&display=swap"
rel="stylesheet"
>
</svelte:head>
<div id="app-root" class="min-h-screen flex flex-col bg-background">
<header></header>
<header>
<BreadcrumbHeader />
</header>
<!-- <ScrollArea class="h-screen w-screen"> -->
<main class="flex-1 h-full w-full max-w-6xl mx-auto px-4 pt-6 pb-10 md:px-8 lg:pt-10 lg:pb-20 relative">

View File

@@ -3,9 +3,11 @@
Fixed header for breadcrumbs navigation for sections in the page
-->
<script lang="ts">
import Icon from '@lucide/svelte/icons/align-vertical-justify-center';
import { flip } from 'svelte/animate';
import { slide } from 'svelte/transition';
import { cn } from '$shared/shadcn/utils/shadcn-utils';
import {
fly,
slide,
} from 'svelte/transition';
import { scrollBreadcrumbsStore } from '../../model';
</script>
@@ -21,20 +23,17 @@ import { scrollBreadcrumbsStore } from '../../model';
"
>
<div class="max-w-8xl mx-auto px-6 h-full flex items-center gap-4">
<div class="flex items-center gap-2.5 opacity-70">
<Icon class="size-4 stroke-gray-900 stroke-1" />
<div class="w-px h-2.5 bg-gray-400/50"></div>
<span class="font-mono text-[9px] uppercase tracking-[0.25em] text-gray-500 font-medium">
nav_trace
</span>
</div>
<h1 class={cn('font-[Barlow] font-extralight')}>
GLYPHDIFF
</h1>
<div class="h-4 w-px bg-gray-300/60"></div>
<nav class="flex items-center gap-3 overflow-x-auto scrollbar-hide flex-1">
{#each scrollBreadcrumbsStore.items as item, idx (item.index)}
<div
animate:flip={{ duration: 200 }}
in:fly={{ duration: 300, y: -10, x: 100, opacity: 0 }}
out:fly={{ duration: 300, y: 10, x: 100, opacity: 0 }}
class="flex items-center gap-3 whitespace-nowrap shrink-0"
>
<span class="font-mono text-[9px] text-gray-400 tracking-wider">
@@ -42,7 +41,7 @@ import { scrollBreadcrumbsStore } from '../../model';
</span>
{@render item.title({
className: 'font-mono text-[10px] font-bold uppercase tracking-tight leading-[0.95] text-gray-900',
className: 'text-[10px] md:text-[10px] font-bold uppercase tracking-tight leading-[0.95] text-gray-900',
})}
{#if idx < scrollBreadcrumbsStore.items.length - 1}

View File

@@ -3,12 +3,13 @@
Description: The main page component of the application.
-->
<script lang="ts">
import { BreadcrumbHeader } from '$entities/Breadcrumb';
import { scrollBreadcrumbsStore } from '$entities/Breadcrumb';
import { cn } from '$shared/shadcn/utils/shadcn-utils';
import { Section } from '$shared/ui';
import ComparisonSlider from '$widgets/ComparisonSlider/ui/ComparisonSlider/ComparisonSlider.svelte';
import { FontSearch } from '$widgets/FontSearch';
import { SampleList } from '$widgets/SampleList';
import CodeIcon from '@lucide/svelte/icons/code';
import LineSquiggleIcon from '@lucide/svelte/icons/line-squiggle';
import ScanEyeIcon from '@lucide/svelte/icons/scan-eye';
import ScanSearchIcon from '@lucide/svelte/icons/search';
@@ -40,11 +41,23 @@ function handleTitleStatusChanged(index: number, isPast: boolean, title?: Snippe
// });
</script>
<BreadcrumbHeader />
<!-- Font List -->
<div class="p-2 h-full flex flex-col gap-3">
<Section class="my-12 gap-8" index={0} onTitleStatusChange={handleTitleStatusChanged}>
<Section class="my-12 gap-8" onTitleStatusChange={handleTitleStatusChanged}>
{#snippet icon({ className })}
<CodeIcon class={className} />
{/snippet}
{#snippet description({ className })}
<span class={className}>
Project_Codename
</span>
{/snippet}
<h2 class={cn('font-[Barlow] font-thin text-7xl md:text-8xl text-justify [text-align-last:justify] [text-justify:inter-character]')}>
GLYPHDIFF
</h2>
</Section>
<Section class="my-12 gap-8" index={1} onTitleStatusChange={handleTitleStatusChanged}>
{#snippet icon({ className })}
<ScanEyeIcon class={className} />
{/snippet}
@@ -56,7 +69,7 @@ function handleTitleStatusChanged(index: number, isPast: boolean, title?: Snippe
<ComparisonSlider />
</Section>
<Section class="my-12 gap-8" index={1} onTitleStatusChange={handleTitleStatusChanged}>
<Section class="my-12 gap-8" index={2} onTitleStatusChange={handleTitleStatusChanged}>
{#snippet icon({ className })}
<ScanSearchIcon class={className} />
{/snippet}
@@ -68,7 +81,7 @@ function handleTitleStatusChanged(index: number, isPast: boolean, title?: Snippe
<FontSearch bind:showFilters={isExpanded} />
</Section>
<Section class="my-12 gap-8" index={2} onTitleStatusChange={handleTitleStatusChanged}>
<Section class="my-12 gap-8" index={3} onTitleStatusChange={handleTitleStatusChanged}>
{#snippet icon({ className })}
<LineSquiggleIcon class={className} />
{/snippet}

View File

@@ -25,6 +25,10 @@ interface Props extends Omit<HTMLAttributes<HTMLElement>, 'title'> {
* Snippet for a title icon
*/
icon?: Snippet<[{ className?: string }]>;
/**
* Snippet for a title description
*/
description?: Snippet<[{ className?: string }]>;
/**
* Index of the section
*/
@@ -44,7 +48,7 @@ interface Props extends Omit<HTMLAttributes<HTMLElement>, 'title'> {
children?: Snippet;
}
const { class: className, title, icon, index = 0, onTitleStatusChange, children }: Props = $props();
const { class: className, title, icon, description, index = 0, onTitleStatusChange, children }: Props = $props();
let titleContainer = $state<HTMLElement>();
const flyParams: FlyParams = { y: 0, x: -50, duration: 300, easing: cubicOut, opacity: 0.2 };
@@ -92,7 +96,9 @@ $effect(() => {
{@render icon({ className: 'size-4 stroke-gray-900 stroke-1' })}
<div class="w-px h-3 bg-gray-400/50"></div>
{/if}
{#if typeof index === 'number'}
{#if description}
{@render description({ className: 'font-mono text-[10px] uppercase tracking-[0.2em] text-gray-600' })}
{:else if typeof index === 'number'}
<span class="font-mono text-[10px] uppercase tracking-[0.2em] text-gray-600">
Component_{String(index).padStart(3, '0')}
</span>