Skip to content

Commit c5c951d

Browse files
authored
Explorer homepage, new subsection based sidebar, refined transitions (#4042)
- **feat(app2): add statistics explorer** - **fix(app2): delete clearFiber** - **fix(app2): refine stats page** - **docs(app2): note how to use existing components** - **fix(app2): polish** - **fix(app2): use datetime on the stats page** - **feat(app2): stat display names** - **feat(app2): render bar chart** - **fix(app2): refine bar chart** - **fix(app2): graph styling** - **fix(app2): bar chart** - **feat(app2): bar hover effect** - **feat(app2): better bar chart** - **fix(app2): barchart component** - **fix(app2): add explorer to the sidebar** - **feat(app2): sidebar subroutes** - **fix(app2): better sidebar** - **chore: fmt**
2 parents 46eabda + 5baa132 commit c5c951d

File tree

20 files changed

+516
-144
lines changed

20 files changed

+516
-144
lines changed

app/src/generated/graphql-env.d.ts

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app2/CONVENTIONS.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@
2929
- never use `mx-auto` to style. use flexbox instead.
3030
- If you want to apply a gap between components, use `flex gap-*`, rather than `space-x-*`
3131

32+
## Use of existing components
33+
34+
- Don't create your own cards, instead, use the `components/ui/Card.svelte`
35+
- When creating a label, use `components/ui/Label.svelte`
36+
- When creating skeletons, use `components/ui/Skeleton.svelte`
37+
- When displaying an error somewhere, use `components/model/ErrorComponent.svelte`
38+
- When displaying dates or times somewhere, use `components/ui/DateTimeComponent.svelte`
39+
3240
## UI Components
3341

3442
- All UI components must accept a `class` prop for styling customization

app2/app2.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ _: {
2020
{
2121
packages = {
2222
app2 = jsPkgs.buildNpmPackage {
23-
npmDepsHash = "sha256-R+7qoYHPuUmBKnvBwjsb4arZQikBckKndQlSYH2lQ5I=";
23+
npmDepsHash = "sha256-LlSGZhPStl8xGhbHfQ6uXskvnK6yjL9VTY7/iUK1/Hg=";
2424
src = ./.;
2525
sourceRoot = "app2";
2626
npmFlags = [ "--legacy-peer-deps" ];

app2/package-lock.json

Lines changed: 25 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app2/package.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@
2121
"@cosmjs/proto-signing": "^0.33.0",
2222
"@cosmjs/stargate": "0.33.0",
2323
"@cosmjs/tendermint-rpc": "^0.33.0",
24-
"patch-package": "^8.0.0",
2524
"@effect/platform": "^0.77.2",
2625
"@eslint/compat": "^1.2.6",
2726
"@eslint/js": "^9.20.0",
2827
"@keplr-wallet/types": "^0.12.190",
2928
"@leapwallet/types": "^0.0.5",
29+
"@scure/base": "^1.2.4",
3030
"@sveltejs/adapter-static": "^3.0.8",
3131
"@sveltejs/kit": "^2.17.2",
3232
"@sveltejs/vite-plugin-svelte": "^5.0.3",
@@ -46,6 +46,7 @@
4646
"graphql": "^16.10.0",
4747
"graphql-request": "^7.1.2",
4848
"jsdom": "^26.0.0",
49+
"patch-package": "^8.0.0",
4950
"svelte": "^5.20.1",
5051
"svelte-check": "^4.1.4",
5152
"tailwind-merge": "^3.0.2",
@@ -54,7 +55,9 @@
5455
"typescript-eslint": "^8.24.1",
5556
"viem": "^2.23.5",
5657
"vite": "^6.1.0",
57-
"vitest": "^3.0.5",
58-
"@scure/base": "^1.2.4"
58+
"vitest": "^3.0.5"
59+
},
60+
"dependencies": {
61+
"@number-flow/svelte": "^0.3.5"
5962
}
6063
}
Lines changed: 46 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
12
<script lang="ts">
23
import { page } from "$app/state"
34
import { navigation } from "../Sidebar/navigation.ts"
45
import { Option } from "effect"
6+
import { fade, fly, slide } from "svelte/transition"
7+
import { quintOut } from "svelte/easing"
8+
import { flip } from "svelte/animate"
59
610
const toTitleCase = (str: string): string => {
711
return str.charAt(0).toUpperCase() + str.slice(1)
@@ -10,60 +14,56 @@ const toTitleCase = (str: string): string => {
1014
type Crumb = {
1115
title: string
1216
path: string
17+
id: string
1318
}
1419
15-
// Get current page info
16-
const currentPageInfo = $derived(
17-
Option.fromNullable(
18-
navigation.find(section => section.items.find(s => s.path === page.url.pathname))
19-
).pipe(
20-
Option.flatMap(s => Option.fromNullable(s.items.find(i => i.path === page.url.pathname))),
21-
Option.getOrElse(() => ({ title: page.url.pathname, path: page.url.pathname }))
22-
)
23-
)
24-
25-
// Build breadcrumb path
26-
const breadcrumbs = $derived(
27-
((): Array<Crumb> => {
28-
const parts = page.url.pathname.split("/").filter(Boolean)
29-
const crumbs: Array<Crumb> = []
20+
// Store the current breadcrumbs
21+
let currentBreadcrumbs = $state<Array<Crumb>>([])
3022
31-
// Add home
32-
// crumbs.push({ title: "Home", path: "/" })
23+
// Update breadcrumbs when the page changes
24+
$effect(() => {
25+
const parts = page.url.pathname.split("/").filter(Boolean)
26+
const newCrumbs: Array<Crumb> = []
3327
34-
// Build path progressively
35-
let currentPath = ""
36-
for (const part of parts) {
37-
currentPath += `/${part}`
28+
// Build path progressively
29+
let currentPath = ""
30+
for (const part of parts) {
31+
currentPath += `/${part}`
3832
39-
// Try to find matching navigation item for nice labels
40-
const matchingItem = navigation
41-
.flatMap(section => section.items)
42-
.find(item => item.path === currentPath)
33+
// Try to find matching navigation item for nice labels
34+
const matchingItem = navigation
35+
.flatMap(section => section.items)
36+
.find(item => item.path === currentPath)
4337
44-
crumbs.push({
45-
title: matchingItem?.title || toTitleCase(part),
46-
path: currentPath
47-
})
48-
}
38+
newCrumbs.push({
39+
title: matchingItem?.title || toTitleCase(part),
40+
path: currentPath,
41+
id: currentPath // Unique ID for animation keying
42+
})
43+
}
4944
50-
return crumbs
51-
})()
52-
)
45+
// Replace the breadcrumbs array
46+
currentBreadcrumbs = newCrumbs
47+
})
5348
</script>
5449

55-
<nav class="flex items-center gap-2 text-zinc-400">
56-
{#each breadcrumbs as crumb, i}
57-
{#if i < breadcrumbs.length - 1}
58-
<a
59-
href={crumb.path}
60-
class="hover:text-zinc-100 transition-colors"
61-
>
62-
{crumb.title}
63-
</a>
64-
<span class="text-zinc-600">/</span>
65-
{:else}
66-
<span class="text-zinc-100">{crumb.title}</span>
67-
{/if}
50+
<nav class="flex items-center gap-2 text-zinc-400 h-8 overflow-hidden">
51+
{#each currentBreadcrumbs as crumb, i (crumb.id)}
52+
<div animate:flip={{ duration: 400 }} class="flex items-center last:text-white">
53+
<a
54+
href={crumb.path}
55+
class="hover:text-zinc-100 transition-colors transition-delay-100"
56+
in:fly={{ x: -30, duration: 200, delay: i * 100, easing: quintOut }}
57+
out:fly={{ x: 30, duration: 100 }}
58+
>
59+
{crumb.title}
60+
</a>
61+
<span
62+
class="text-zinc-600 ml-2"
63+
in:fade={{ duration: 200, delay: i * 200 }}
64+
out:fade={{ duration: 150 }}
65+
>/</span>
66+
</div>
6867
{/each}
6968
</nav>
69+

0 commit comments

Comments
 (0)