Skip to content

Commit fa7a233

Browse files
committed
feat: luxe footer, navbar, sidebar
1 parent a0d74b4 commit fa7a233

File tree

8 files changed

+622
-48
lines changed

8 files changed

+622
-48
lines changed

public/sidebar.piml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
(label) Home
88
(to) /
99
(icon) HouseIcon
10+
> (item)
11+
(label) Terminal
12+
(to) /terminal
13+
(icon) TerminalWindowIcon
1014
> (item)
1115
(label) About
1216
(to) /about

src/components/BrutalistSidebar.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
FlaskIcon,
2626
BookBookmarkIcon,
2727
FilePdfIcon,
28+
TerminalWindowIcon
2829
} from '@phosphor-icons/react';
2930

3031
import { version } from '../version';
@@ -58,6 +59,7 @@ const ICON_MAP = {
5859
FlaskIcon,
5960
BookBookmarkIcon,
6061
FilePdfIcon,
62+
TerminalWindowIcon,
6163
};
6264

6365
const BrutalistSidebar = ({

src/components/Layout.jsx

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ import Navbar from './Navbar';
33
import ClassicSidebar from './ClassicSidebar';
44
import BrutalistSidebar from './BrutalistSidebar';
55
import Footer from './Footer';
6+
import LuxeSidebar from './LuxeSidebar';
7+
import LuxeNavbar from './LuxeNavbar';
8+
import LuxeFooter from './LuxeFooter';
69
import { useLocation } from 'react-router-dom';
710
import Search from './Search';
811
import CommandPalette from './CommandPalette';
@@ -37,6 +40,7 @@ const Layout = ({
3740
isSidebarOpen,
3841
toggleSidebar,
3942
isAppFullscreen,
43+
fezcodexTheme,
4044
} = useVisualSettings();
4145
const location = useLocation();
4246
const { projects } = useProjects();
@@ -75,9 +79,16 @@ const Layout = ({
7579
const mainContent = location.pathname.startsWith('/stories') ? (
7680
<DndProvider>{children}</DndProvider>
7781
) : (
78-
<div className="bg-[#050505] min-h-screen font-sans flex">
82+
<div className={`${fezcodexTheme === 'luxe' ? 'bg-[#F5F5F0]' : 'bg-[#050505]'} min-h-screen font-sans flex`}>
7983
{!hideLayout &&
80-
(sidebarMode === 'classic' ? (
84+
(fezcodexTheme === 'luxe' ? (
85+
<LuxeSidebar
86+
isOpen={isSidebarOpen}
87+
toggleSidebar={toggleSidebar}
88+
toggleModal={toggleModal}
89+
setIsPaletteOpen={setIsPaletteOpen}
90+
/>
91+
) : sidebarMode === 'classic' ? (
8192
<ClassicSidebar
8293
isOpen={isSidebarOpen}
8394
toggleSidebar={toggleSidebar}
@@ -97,12 +108,21 @@ const Layout = ({
97108
className={`flex-1 flex flex-col transition-all duration-300 ${isSidebarOpen && !hideLayout ? (sidebarMode === 'classic' ? 'md:ml-64' : 'md:ml-72') : 'md:ml-0'}`}
98109
>
99110
{!hideLayout && (
100-
<Navbar
101-
toggleSidebar={toggleSidebar}
102-
isSidebarOpen={isSidebarOpen}
103-
isSearchVisible={isSearchVisible}
104-
toggleSearch={toggleSearch}
105-
/>
111+
fezcodexTheme === 'luxe' ? (
112+
<LuxeNavbar
113+
toggleSidebar={toggleSidebar}
114+
isSidebarOpen={isSidebarOpen}
115+
isSearchVisible={isSearchVisible}
116+
toggleSearch={toggleSearch}
117+
/>
118+
) : (
119+
<Navbar
120+
toggleSidebar={toggleSidebar}
121+
isSidebarOpen={isSidebarOpen}
122+
isSearchVisible={isSearchVisible}
123+
toggleSearch={toggleSearch}
124+
/>
125+
)
106126
)}
107127
{!hideLayout && isSearchVisible && (
108128
<Search isVisible={isSearchVisible} />
@@ -111,7 +131,9 @@ const Layout = ({
111131
{!hideLayout &&
112132
location.pathname !== '/projects' &&
113133
location.pathname !== '/blog' &&
114-
location.pathname !== '/commands' && <Footer />}
134+
location.pathname !== '/commands' &&
135+
(fezcodexTheme === 'luxe' ? <LuxeFooter /> : <Footer />)
136+
}
115137
</div>
116138
</div>
117139
);

src/components/LuxeFooter.jsx

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import React from 'react';
2+
import { Link } from 'react-router-dom';
3+
import { version } from '../version';
4+
import { useAboutData } from '../hooks/useAboutData';
5+
import { Command } from '@phosphor-icons/react';
6+
7+
const LuxeFooter = () => {
8+
const scrollToTop = () => window.scrollTo({ top: 0, behavior: 'smooth' });
9+
const aboutData = useAboutData();
10+
11+
return (
12+
<footer className="bg-[#F5F5F0] border-t border-[#1A1A1A]/5 mt-auto text-[#1A1A1A]">
13+
<div className="mx-auto max-w-[1800px] px-6 py-20 md:px-12">
14+
<div className="grid grid-cols-1 md:grid-cols-12 gap-12 md:gap-24">
15+
16+
{/* Brand Column */}
17+
<div className="md:col-span-4 space-y-8">
18+
<Link to="/" onClick={scrollToTop} className="inline-block">
19+
<span className="font-playfairDisplay text-4xl italic font-medium text-[#1A1A1A]">
20+
Fezcodex.
21+
</span>
22+
</Link>
23+
<p className="font-outfit text-sm text-[#1A1A1A]/60 leading-relaxed max-w-sm">
24+
{aboutData.profile.tagline || 'A digital garden of experimental code, architectural thoughts, and creative explorations.'}
25+
</p>
26+
27+
<div className="pt-8 flex flex-col gap-2 font-outfit text-xs text-[#1A1A1A]/40 uppercase tracking-widest">
28+
<span>v{version}{new Date().getFullYear()}</span>
29+
<span>Built with Precision</span>
30+
</div>
31+
</div>
32+
33+
{/* Navigation Column */}
34+
<div className="md:col-span-4">
35+
<h4 className="font-outfit text-xs font-bold uppercase tracking-widest text-[#1A1A1A]/40 mb-8">Directory</h4>
36+
<ul className="space-y-4">
37+
{[
38+
{ label: 'Journal', to: '/blog' },
39+
{ label: 'Projects', to: '/projects' },
40+
{ label: 'About', to: '/about' },
41+
{ label: 'Logbook', to: '/logs' },
42+
{ label: 'System', to: '/settings' },
43+
].map((link) => (
44+
<li key={link.to}>
45+
<Link to={link.to} onClick={scrollToTop} className="font-playfairDisplay text-xl text-[#1A1A1A]/80 hover:text-[#1A1A1A] hover:italic transition-all">
46+
{link.label}
47+
</Link>
48+
</li>
49+
))}
50+
</ul>
51+
</div>
52+
53+
{/* Connect Column */}
54+
<div className="md:col-span-4">
55+
<h4 className="font-outfit text-xs font-bold uppercase tracking-widest text-[#1A1A1A]/40 mb-8">Connect</h4>
56+
<div className="flex flex-wrap gap-4 mb-12">
57+
{aboutData.profile.links.filter(l => l.id !== 'email' && l.id !== 'website').map((link, i) => (
58+
<a
59+
key={i}
60+
href={link.url}
61+
target="_blank"
62+
rel="noreferrer"
63+
className="font-outfit text-sm text-[#1A1A1A] border-b border-[#1A1A1A]/20 hover:border-[#1A1A1A] pb-1 transition-colors"
64+
>
65+
{link.label}
66+
</a>
67+
))}
68+
</div>
69+
70+
<div className="p-6 border border-[#1A1A1A]/5 bg-white rounded-sm">
71+
<div className="flex items-center gap-3 mb-2 text-[#1A1A1A]/60">
72+
<Command size={16} />
73+
<span className="font-outfit text-[10px] uppercase tracking-widest">Quick Actions</span>
74+
</div>
75+
<p className="font-outfit text-xs text-[#1A1A1A]/40">
76+
Press <kbd className="font-mono bg-[#1A1A1A]/5 px-1 rounded">Cmd + K</kbd> to open command palette.
77+
</p>
78+
</div>
79+
</div>
80+
81+
</div>
82+
</div>
83+
</footer>
84+
);
85+
};
86+
87+
export default LuxeFooter;

src/components/LuxeNavbar.jsx

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import React, { useState, useEffect } from 'react';
2+
import { Link } from 'react-router-dom';
3+
import { List, MagnifyingGlass } from '@phosphor-icons/react';
4+
5+
const LuxeNavbar = ({
6+
toggleSidebar,
7+
isSidebarOpen,
8+
isSearchVisible,
9+
toggleSearch,
10+
}) => {
11+
const [isScrolled, setIsScrolled] = useState(false);
12+
13+
useEffect(() => {
14+
const handleScroll = () => {
15+
setIsScrolled(window.scrollY > 20);
16+
};
17+
window.addEventListener('scroll', handleScroll);
18+
return () => {
19+
window.removeEventListener('scroll', handleScroll);
20+
};
21+
}, []);
22+
23+
return (
24+
<header
25+
className={`sticky top-0 left-0 right-0 z-[60] transition-all duration-500 bg-[#FDFCFB]/80 backdrop-blur-md border-b ${
26+
isScrolled
27+
? 'py-4 border-[#1A1A1A]/5 shadow-sm'
28+
: 'py-6 border-transparent'
29+
}`}
30+
> <div className="mx-auto max-w-[1800px] px-6 md:px-12 flex justify-between items-center text-[#1A1A1A]">
31+
32+
{/* Left: Sidebar Toggle & Brand */}
33+
<div className="flex items-center gap-6">
34+
<button
35+
onClick={toggleSidebar}
36+
className="text-[#1A1A1A]/60 hover:text-[#1A1A1A] transition-colors focus:outline-none"
37+
aria-label="Toggle Sidebar"
38+
>
39+
<List size={24} weight="light" />
40+
</button>
41+
42+
<Link to="/" className="flex items-center gap-2 group">
43+
<span className="font-playfairDisplay text-xl font-bold tracking-tight text-[#1A1A1A]">
44+
Fezcodex
45+
</span>
46+
</Link>
47+
</div>
48+
49+
{/* Right: Actions */}
50+
<div className="flex items-center gap-6">
51+
<Link
52+
to="/about"
53+
className="hidden md:flex items-center gap-2 text-[#1A1A1A]/60 hover:text-[#1A1A1A] transition-colors"
54+
>
55+
<span className="font-outfit text-xs font-medium uppercase tracking-widest">
56+
About
57+
</span>
58+
</Link>
59+
60+
<button
61+
onClick={toggleSearch}
62+
className="flex items-center gap-2 text-[#1A1A1A]/60 hover:text-[#1A1A1A] transition-colors"
63+
aria-label="Toggle Search"
64+
>
65+
<MagnifyingGlass size={20} weight="light" />
66+
<span className="hidden md:inline font-outfit text-xs font-medium uppercase tracking-widest">
67+
Search
68+
</span>
69+
</button>
70+
</div>
71+
</div>
72+
</header>
73+
);
74+
};
75+
76+
export default LuxeNavbar;

0 commit comments

Comments
 (0)