Add talk to resources, public-site nav, and homepage link

- Resources: 7th project card linking the 'Hacking Your Hackerspace' talk
  (hack.build), with a PlayIcon; bump the section count to 07.
- Sidebar: NavLink now supports external targets; add a 'Public Site' section
  linking the homepage and the public resources page.
- Login: a back-to-homepage link.
This commit is contained in:
Moheeb Zara
2026-07-28 23:18:50 -07:00
parent 62c1c5f4b7
commit b6e50c0950
4 changed files with 54 additions and 15 deletions
+12 -1
View File
@@ -8,6 +8,7 @@ import {
CubeIcon, CubeIcon,
KeyIcon, KeyIcon,
GridIcon, GridIcon,
PlayIcon,
} from '@/components/resources/icons' } from '@/components/resources/icons'
import { AtlasLogo } from '@/components/resources/atlas-logo' import { AtlasLogo } from '@/components/resources/atlas-logo'
@@ -55,7 +56,7 @@ export default function ResourcesLandingPage() {
<section> <section>
<div className="resources-section-header"> <div className="resources-section-header">
<span className="resources-section-label">Projects</span> <span className="resources-section-label">Projects</span>
<span className="resources-section-count">06 tools</span> <span className="resources-section-count">07 tools</span>
</div> </div>
<div className="resources-projects"> <div className="resources-projects">
@@ -115,6 +116,16 @@ export default function ResourcesLandingPage() {
featured featured
visual={<KeyIcon />} visual={<KeyIcon />}
/> />
<ProjectCard
href="https://hack.build/hacking-your-hackerspace.html"
external
num="07"
title="Hacking Your Hackerspace"
description="A talk on the patterns, pitfalls, and governance lessons behind keeping a hackerspace alive — the research from these projects, condensed into one interactive session."
type="Talk · Interactive"
visual={<PlayIcon />}
/>
</div> </div>
</section> </section>
+5
View File
@@ -176,6 +176,11 @@ export default function LoginPage() {
create or join a space → create or join a space →
</Link> </Link>
</p> </p>
<p className="text-center font-mono text-xs mt-4">
<Link href="/" className="text-zinc-500 hover:text-[#d4f53c] hover:underline transition">
← Back to homepage
</Link>
</p>
</div> </div>
</div> </div>
</div> </div>
+28 -14
View File
@@ -15,7 +15,7 @@ import {
MessageSquare, Users, CreditCard, BookUser, Download, LogOut, MessageSquare, Users, CreditCard, BookUser, Download, LogOut,
Vote, ShieldAlert, ScrollText, LineChart, UserSearch, Vote, ShieldAlert, ScrollText, LineChart, UserSearch,
MessagesSquare, SlidersHorizontal, ClipboardList, FileText, Award, BadgeCheck, GraduationCap, Hammer, MessagesSquare, SlidersHorizontal, ClipboardList, FileText, Award, BadgeCheck, GraduationCap, Hammer,
ChevronDown, DoorClosed, CalendarCheck, Zap, ChevronDown, DoorClosed, CalendarCheck, Zap, Home, Compass,
} from 'lucide-react' } from 'lucide-react'
interface NavLinkProps { interface NavLinkProps {
@@ -24,22 +24,19 @@ interface NavLinkProps {
icon: React.ElementType icon: React.ElementType
badge?: number badge?: number
active: boolean active: boolean
external?: boolean
onClick?: () => void onClick?: () => void
} }
function NavLink({ href, label, icon: Icon, badge, active, onClick }: NavLinkProps) { function NavLink({ href, label, icon: Icon, badge, active, external, onClick }: NavLinkProps) {
return ( const className = cn(
<Link 'flex items-center justify-between mx-2 px-3 py-2 rounded-md text-sm transition-colors',
href={href} active
onClick={onClick} ? 'bg-[var(--sidebar-primary)]/15 text-[var(--sidebar-primary)]'
aria-current={active ? 'page' : undefined} : 'text-[var(--sidebar-foreground)]/70 hover:bg-[var(--sidebar-accent)] hover:text-[var(--sidebar-foreground)]',
className={cn( )
'flex items-center justify-between mx-2 px-3 py-2 rounded-md text-sm transition-colors', const inner = (
active <>
? 'bg-[var(--sidebar-primary)]/15 text-[var(--sidebar-primary)]'
: 'text-[var(--sidebar-foreground)]/70 hover:bg-[var(--sidebar-accent)] hover:text-[var(--sidebar-foreground)]',
)}
>
<span className="flex items-center gap-2.5"> <span className="flex items-center gap-2.5">
<Icon className={cn('w-4 h-4', active ? 'text-[var(--sidebar-primary)]' : 'text-[var(--sidebar-foreground)]/50')} /> <Icon className={cn('w-4 h-4', active ? 'text-[var(--sidebar-primary)]' : 'text-[var(--sidebar-foreground)]/50')} />
{label} {label}
@@ -49,6 +46,18 @@ function NavLink({ href, label, icon: Icon, badge, active, onClick }: NavLinkPro
{badge} {badge}
</span> </span>
) : null} ) : null}
</>
)
if (external) {
return (
<a href={href} target="_blank" rel="noopener noreferrer" onClick={onClick} className={className}>
{inner}
</a>
)
}
return (
<Link href={href} onClick={onClick} aria-current={active ? 'page' : undefined} className={className}>
{inner}
</Link> </Link>
) )
} }
@@ -222,6 +231,11 @@ export function AppSidebar({ member, roleName, taskBadge = 0, commsBadge = 0, pa
<NavLink href="/me" label="My membership" icon={BadgeCheck} active={isActive('/me')} onClick={onNav} /> <NavLink href="/me" label="My membership" icon={BadgeCheck} active={isActive('/me')} onClick={onNav} />
</NavSection> </NavSection>
<NavSection id="public" title="Public Site">
<NavLink href="/" label="Homepage" icon={Home} external active={false} onClick={onNav} />
<NavLink href="/resources" label="Resources" icon={Compass} external active={false} onClick={onNav} />
</NavSection>
{showAdminSection && ( {showAdminSection && (
<NavSection id="admin" title="Admin"> <NavSection id="admin" title="Admin">
{isAdmin && <NavLink href="/customize" label="Customize" icon={SlidersHorizontal} active={isActive('/customize')} onClick={onNav} />} {isAdmin && <NavLink href="/customize" label="Customize" icon={SlidersHorizontal} active={isActive('/customize')} onClick={onNav} />}
+9
View File
@@ -114,3 +114,12 @@ export function PromptIcon(props: IconProps) {
</svg> </svg>
) )
} }
export function PlayIcon(props: IconProps) {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" fill="none" {...props}>
<rect x="4" y="8" width="40" height="32" rx="3" stroke="currentColor" strokeWidth={2.5} />
<path d="M20 18 L30 24 L20 30 Z" fill="#d4ff00" />
</svg>
)
}