Add discord shield to navbar (vibe-kanban) (#927)

*  Discord shield added to navbar with:

- **Desktop badge**: Discord shield visible on sm+ screens, positioned before the dropdown menu
- **Mobile fallback**: Discord link added to dropdown menu for small screens
- **Consistent styling**: Uses `h-5` height and proper spacing (`ml-2 mr-1`)
- **Accessibility**: Includes proper `aria-label` and `alt` text

The implementation follows the existing code patterns and maintains readability as requested.

*  Fixed both issues:

- **Vertical centering**: Changed from `block` to `flex items-center` to properly align with other navbar buttons
- **Theme adaptation**: Added `dark:brightness-90 dark:contrast-125` to subtly adjust the shield colors in dark mode for better visibility

The Discord shield now properly aligns with other navbar elements and adapts to both light and dark themes.

*  Updated Discord shield with theme colors and positioning:

- **Theme colors**: Custom badge using `bg-background`, `text-foreground` for left side and `bg-success`, `text-success-foreground` for right side
- **Position**: Moved to right of logo (left side of navbar) instead of right side
- **Design**: Clean two-part badge with "discord" label and "online" status that adapts to theme automatically

The Discord badge now uses your app's theme colors and is positioned next to the logo for better visual hierarchy.

*  Discord online count implemented with:

- **Live data**: Fetches real member count from Discord Widget API
- **Auto-refresh**: Updates every 60 seconds for live feel
- **Graceful fallback**: Shows "online" if API unavailable
- **Theme integration**: Maintains your custom success/background colors
- **Accessibility**: Includes `aria-live="polite"` for screen readers
- **Formatted display**: Shows count as "1,234 online" with proper locale formatting

The Discord badge now displays the actual number of online members from your server while maintaining the theme colors and positioning next to the logo.

* Cleanup script changes for task attempt 230fa5cc-96f7-4fdb-a549-c2ea46b9e88e

*  Fixed positioning - Added `flex items-center` to the container so the logo and Discord badge sit side by side horizontally instead of stacking vertically.

*  Added Discord logo from simple-icons:

- **Added simple-icons dependency** via pnpm
- **Imported Discord icon** from `simple-icons` package
- **Replaced "discord" text** with actual Discord SVG logo
- **Maintained theme colors** - icon uses `currentColor` so it adapts to theme automatically
- **Proper sizing** - `h-4 w-4` matches other navbar icons

The Discord badge now displays the official Discord logo instead of text, while maintaining the live member count and theme integration.

* Cleanup script changes for task attempt 230fa5cc-96f7-4fdb-a549-c2ea46b9e88e

* manual style improvement
This commit is contained in:
Louis Knight-Webb
2025-10-03 18:52:44 +01:00
committed by GitHub
parent 613caf91d6
commit c8e660c7da
2 changed files with 69 additions and 3 deletions

View File

@@ -1,5 +1,6 @@
import { Link, useLocation } from 'react-router-dom';
import { useCallback } from 'react';
import { useCallback, useEffect, useState } from 'react';
import { siDiscord } from 'simple-icons';
import { Button } from '@/components/ui/button';
import {
DropdownMenu,
@@ -13,6 +14,7 @@ import {
Settings,
BookOpen,
MessageCircleQuestion,
MessageCircle,
Menu,
Plus,
} from 'lucide-react';
@@ -24,6 +26,8 @@ import { useProject } from '@/contexts/project-context';
import { showProjectForm } from '@/lib/modals';
import { useOpenProjectInEditor } from '@/hooks/useOpenProjectInEditor';
const DISCORD_GUILD_ID = '1423630976524877857';
const INTERNAL_NAV = [
{ label: 'Projects', icon: FolderOpen, to: '/projects' },
{ label: 'Settings', icon: Settings, to: '/settings' },
@@ -40,6 +44,11 @@ const EXTERNAL_LINKS = [
icon: MessageCircleQuestion,
href: 'https://github.com/BloopAI/vibe-kanban/issues',
},
{
label: 'Discord',
icon: MessageCircle,
href: 'https://discord.gg/AC4nwVtJM3',
},
];
export function Navbar() {
@@ -47,6 +56,36 @@ export function Navbar() {
const { projectId, project } = useProject();
const { query, setQuery, active, clear, registerInputRef } = useSearch();
const handleOpenInEditor = useOpenProjectInEditor(project || null);
const [onlineCount, setOnlineCount] = useState<number | null>(null);
useEffect(() => {
let cancelled = false;
const fetchCount = async () => {
try {
const res = await fetch(
`https://discord.com/api/guilds/${DISCORD_GUILD_ID}/widget.json`,
{ cache: 'no-store' }
);
if (!res.ok) return; // Widget disabled or temporary error; keep previous value
const data = await res.json();
if (!cancelled && typeof data?.presence_count === 'number') {
setOnlineCount(data.presence_count);
}
} catch {
// Network error; ignore and keep previous value
}
};
// Initial fetch + refresh every 60s
fetchCount();
const interval = setInterval(fetchCount, 60_000);
return () => {
cancelled = true;
clearInterval(interval);
};
}, []);
const setSearchBarRef = useCallback(
(node: HTMLInputElement | null) => {
@@ -78,10 +117,36 @@ export function Navbar() {
<div className="border-b bg-background">
<div className="w-full px-3">
<div className="flex items-center h-12 py-2">
<div className="flex-1">
<div className="flex-1 flex items-center">
<Link to="/projects">
<Logo />
</Link>
<a
href="https://discord.gg/AC4nwVtJM3"
target="_blank"
rel="noopener noreferrer"
aria-label="Join our Discord"
className="hidden sm:inline-flex items-center ml-3 text-xs font-medium overflow-hidden border h-6"
>
<span className="bg-muted text-foreground flex items-center p-2 border-r">
<svg
className="h-4 w-4"
viewBox="0 0 24 24"
fill="currentColor"
aria-hidden="true"
>
<path d={siDiscord.path} />
</svg>
</span>
<span
className=" h-full items-center flex p-2"
aria-live="polite"
>
{onlineCount !== null
? `${onlineCount.toLocaleString()} online`
: 'online'}
</span>
</a>
</div>
<SearchBar