From da8aab7de5071fe2f5501da1398bb1dc1f92e9c0 Mon Sep 17 00:00:00 2001
From: Jure <44338+hoornet@users.noreply.github.com>
Date: Thu, 21 May 2026 21:19:55 +0200
Subject: [PATCH] polish: replace sidebar Unicode glyphs with Lucide icons
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The Unicode/symbol icons (◈ ☰ ▶ ⌕ ⟐ ✦ …) rendered inconsistently across
platforms and sizes. Lucide is crisp and pixel-perfect at any zoom.
- Add lucide-react (pinned exact); tree-shakes to the 15 icons used.
- NAV_ITEMS is now NavItem[] with ReactNode icons (the as-const array
couldn't carry JSX). View type exported from the ui store for it.
- Icon spans switched from text-centred glyphs to flex-centred SVGs.
- Write-article ✦ -> PenLine.
---
package-lock.json | 10 ++++++
package.json | 1 +
src/components/sidebar/Sidebar.tsx | 52 ++++++++++++++++++------------
src/stores/ui.ts | 2 +-
4 files changed, 44 insertions(+), 21 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index bc25ea5..3c870e7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -23,6 +23,7 @@
"@types/dompurify": "^3.0.5",
"dompurify": "^3.4.0",
"highlight.js": "^11.11.1",
+ "lucide-react": "1.16.0",
"marked": "^17.0.4",
"marked-highlight": "^2.2.3",
"react": "^19.1.0",
@@ -3585,6 +3586,15 @@
"yallist": "^3.0.2"
}
},
+ "node_modules/lucide-react": {
+ "version": "1.16.0",
+ "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.16.0.tgz",
+ "integrity": "sha512-dYwyPzb4MEKpGUmNYk3WKWPnMrHs3FKM+q94kAnJrcDIqqn1hq2xY8scaS2ovsOCM5D51ey2gaRG3PBb1vgoYQ==",
+ "license": "ISC",
+ "peerDependencies": {
+ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
"node_modules/lz-string": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz",
diff --git a/package.json b/package.json
index a74cf02..608af37 100644
--- a/package.json
+++ b/package.json
@@ -27,6 +27,7 @@
"@types/dompurify": "^3.0.5",
"dompurify": "^3.4.0",
"highlight.js": "^11.11.1",
+ "lucide-react": "1.16.0",
"marked": "^17.0.4",
"marked-highlight": "^2.2.3",
"react": "^19.1.0",
diff --git a/src/components/sidebar/Sidebar.tsx b/src/components/sidebar/Sidebar.tsx
index 1d5297e..0b7b436 100644
--- a/src/components/sidebar/Sidebar.tsx
+++ b/src/components/sidebar/Sidebar.tsx
@@ -1,4 +1,9 @@
-import { useUIStore } from "../../stores/ui";
+import type { ReactNode } from "react";
+import {
+ Rss, BookOpen, Image as ImageIcon, Mic2, Search, Bookmark, Mail, Bell,
+ Users, Zap, Radio, Wifi, Settings, Heart, PenLine,
+} from "lucide-react";
+import { useUIStore, type View } from "../../stores/ui";
import { useCanSign } from "../../stores/user";
import { useNotificationsStore } from "../../stores/notifications";
import { useDraftStore } from "../../stores/drafts";
@@ -8,22 +13,29 @@ import pkg from "../../../package.json";
// Items marked `requiresSigner: true` are hidden in read-only mode
// because they're account-bound and have no useful content without a signer.
-const NAV_ITEMS = [
- { id: "feed" as const, label: "Feed", icon: "◈" },
- { id: "articles" as const, label: "Articles", icon: "☰" },
- { id: "media" as const, label: "Media", icon: "▶" },
- { id: "podcasts" as const, label: "Podcasts", icon: "🎙" },
- { id: "search" as const, label: "Search", icon: "⌕" },
- { id: "bookmarks" as const, label: "Bookmarks", icon: "★", requiresSigner: true },
- { id: "dm" as const, label: "Messages", icon: "✉", requiresSigner: true },
- { id: "notifications" as const, label: "Notifications", icon: "🔔", requiresSigner: true },
- { id: "follows" as const, label: "People", icon: "👥" },
- { id: "zaps" as const, label: "Zaps", icon: "⚡", requiresSigner: true },
- { id: "v4v" as const, label: "Value 4 Value", icon: "📡", requiresSigner: true },
- { id: "relays" as const, label: "Relays", icon: "⟐" },
- { id: "settings" as const, label: "Settings", icon: "⚙" },
- { id: "about" as const, label: "Support", icon: "♥" },
-] as const;
+interface NavItem {
+ id: View;
+ label: string;
+ icon: ReactNode;
+ requiresSigner?: boolean;
+}
+
+const NAV_ITEMS: NavItem[] = [
+ { id: "feed", label: "Feed", icon: },
+ { id: "articles", label: "Articles", icon: },
+ { id: "media", label: "Media", icon: },
+ { id: "podcasts", label: "Podcasts", icon: },
+ { id: "search", label: "Search", icon: },
+ { id: "bookmarks", label: "Bookmarks", icon: , requiresSigner: true },
+ { id: "dm", label: "Messages", icon: , requiresSigner: true },
+ { id: "notifications", label: "Notifications", icon: , requiresSigner: true },
+ { id: "follows", label: "People", icon: },
+ { id: "zaps", label: "Zaps", icon: , requiresSigner: true },
+ { id: "v4v", label: "Value 4 Value", icon: , requiresSigner: true },
+ { id: "relays", label: "Relays", icon: },
+ { id: "settings", label: "Settings", icon: },
+ { id: "about", label: "Support", icon: },
+];
export function Sidebar() {
const { currentView, setView, sidebarCollapsed, toggleSidebar } = useUIStore();
@@ -85,8 +97,8 @@ export function Sidebar() {
: "text-text-muted hover:text-text hover:bg-bg-hover"
}`}
>
-
- ✦
+
+
{c && draftCount > 0 && (
)}
@@ -111,7 +123,7 @@ export function Sidebar() {
: "text-text-muted hover:text-text hover:bg-bg-hover"
}`}
>
-
+
{item.icon}
{badge > 0 && c && (
diff --git a/src/stores/ui.ts b/src/stores/ui.ts
index abc7b14..61c1d8a 100644
--- a/src/stores/ui.ts
+++ b/src/stores/ui.ts
@@ -2,7 +2,7 @@ import { create } from "zustand";
import { NDKEvent } from "@nostr-dev-kit/ndk";
-type View = "feed" | "search" | "relays" | "settings" | "profile" | "thread" | "article-editor" | "article" | "articles" | "media" | "podcasts" | "about" | "zaps" | "dm" | "notifications" | "bookmarks" | "hashtag" | "follows" | "v4v";
+export type View = "feed" | "search" | "relays" | "settings" | "profile" | "thread" | "article-editor" | "article" | "articles" | "media" | "podcasts" | "about" | "zaps" | "dm" | "notifications" | "bookmarks" | "hashtag" | "follows" | "v4v";
type FeedTab = "global" | "following" | "trending";
interface ViewStackEntry {