aboutsummaryrefslogtreecommitdiffstats
path: root/frontend/src/components
diff options
context:
space:
mode:
authorAdam Mathes <adam@adammathes.com>2026-02-14 16:05:56 -0800
committerAdam Mathes <adam@adammathes.com>2026-02-14 16:05:56 -0800
commitad6b8187e5a7ba6b36f330b181434e4582bf2d74 (patch)
tree650b09b7c85edeab9e2e2cc1ef907c63610be17d /frontend/src/components
parent701e0e8e919d2929ecc98b555e468bd29bf606cf (diff)
downloadneko-ad6b8187e5a7ba6b36f330b181434e4582bf2d74.tar.gz
neko-ad6b8187e5a7ba6b36f330b181434e4582bf2d74.tar.bz2
neko-ad6b8187e5a7ba6b36f330b181434e4582bf2d74.zip
UI: Add collapsible caret icons for Tags and Feeds in sidebar (NK-gjymiw)
Diffstat (limited to 'frontend/src/components')
-rw-r--r--frontend/src/components/FeedList.css17
-rw-r--r--frontend/src/components/FeedList.tsx51
2 files changed, 51 insertions, 17 deletions
diff --git a/frontend/src/components/FeedList.css b/frontend/src/components/FeedList.css
index 7c39901..35543b7 100644
--- a/frontend/src/components/FeedList.css
+++ b/frontend/src/components/FeedList.css
@@ -4,6 +4,9 @@
color: #777;
/* specific v1 color */
font-size: 0.8rem;
+ background: var(--sidebar-bg);
+ min-height: 100%;
+ flex: 1;
}
.feed-list h1.logo {
@@ -57,6 +60,20 @@
/* Darker than list items */
text-transform: lowercase;
font-variant: small-caps;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.caret {
+ display: inline-block;
+ font-size: 0.6rem;
+ transition: transform 0.2s ease;
+ color: #777;
+}
+
+.caret.expanded {
+ transform: rotate(90deg);
}
.filter-list,
diff --git a/frontend/src/components/FeedList.tsx b/frontend/src/components/FeedList.tsx
index 250ce7d..a4ecccf 100644
--- a/frontend/src/components/FeedList.tsx
+++ b/frontend/src/components/FeedList.tsx
@@ -2,6 +2,7 @@ import { useEffect, useState } from 'react';
import { Link, useNavigate, useSearchParams, useLocation, useParams } from 'react-router-dom';
import type { Feed, Category } from '../types';
import './FeedList.css';
+import './FeedListVariants.css';
import { apiFetch } from '../utils';
export default function FeedList({
@@ -20,12 +21,22 @@ export default function FeedList({
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
const [feedsExpanded, setFeedsExpanded] = useState(false);
+ const [tagsExpanded, setTagsExpanded] = useState(true);
const [searchQuery, setSearchQuery] = useState('');
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const location = useLocation();
const { feedId, tagName } = useParams();
+ const sidebarVariant = searchParams.get('sidebar') || localStorage.getItem('neko-sidebar-variant') || 'glass';
+
+ useEffect(() => {
+ const variant = searchParams.get('sidebar');
+ if (variant) {
+ localStorage.setItem('neko-sidebar-variant', variant);
+ }
+ }, [searchParams]);
+
const currentFilter =
searchParams.get('filter') ||
(location.pathname === '/' && !feedId && !tagName ? 'unread' : '');
@@ -41,6 +52,10 @@ export default function FeedList({
setFeedsExpanded(!feedsExpanded);
};
+ const toggleTags = () => {
+ setTagsExpanded(!tagsExpanded);
+ };
+
const handleLinkClick = () => {
if (isMobile) {
setSidebarVisible(false);
@@ -77,7 +92,7 @@ export default function FeedList({
};
return (
- <div className="feed-list">
+ <div className={`feed-list variant-${sidebarVariant}`}>
<h1 className="logo" onClick={() => setSidebarVisible(false)}>
🐱
</h1>
@@ -115,27 +130,29 @@ export default function FeedList({
</div>
<div className="tag-section">
- <h4 onClick={() => { }} className="section-header">
- Tags
+ <h4 onClick={toggleTags} className="section-header">
+ <span className={`caret ${tagsExpanded ? 'expanded' : ''}`}>▶</span> Tags
</h4>
- <ul className="tag-list-items">
- {tags.map((tag) => (
- <li key={tag.title} className="tag-item">
- <Link
- to={`/tag/${encodeURIComponent(tag.title)}`}
- className={`tag-link ${tagName === tag.title ? 'active' : ''}`}
- onClick={handleLinkClick}
- >
- {tag.title}
- </Link>
- </li>
- ))}
- </ul>
+ {tagsExpanded && (
+ <ul className="tag-list-items">
+ {tags.map((tag) => (
+ <li key={tag.title} className="tag-item">
+ <Link
+ to={`/tag/${encodeURIComponent(tag.title)}`}
+ className={`tag-link ${tagName === tag.title ? 'active' : ''}`}
+ onClick={handleLinkClick}
+ >
+ {tag.title}
+ </Link>
+ </li>
+ ))}
+ </ul>
+ )}
</div>
<div className="feed-section">
<h4 onClick={toggleFeeds} className="section-header">
- Feeds
+ <span className={`caret ${feedsExpanded ? 'expanded' : ''}`}>▶</span> Feeds
</h4>
{feedsExpanded &&
(feeds.length === 0 ? (