Skip to content

Commit 1242d8c

Browse files
committed
refactor: commands page
1 parent dabc8c4 commit 1242d8c

File tree

8 files changed

+186
-115
lines changed

8 files changed

+186
-115
lines changed

src/components/BrutalistSidebar.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import {
2121
Rss,
2222
} from '@phosphor-icons/react';
2323

24-
import Fez from './Fez';
2524
import { version } from '../version';
2625
import usePersistentState from '../hooks/usePersistentState';
2726
import { KEY_SIDEBAR_STATE } from '../utils/LocalStorageManager';

src/components/Layout.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,13 @@ const Layout = ({
102102
/>
103103
{isSearchVisible && <Search isVisible={isSearchVisible} />}
104104
<main className="flex-grow">{children}</main>
105-
{location.pathname !== '/projects' && <Footer />}
105+
{location.pathname !== '/projects' &&
106+
location.pathname !== '/blog' &&
107+
location.pathname !== '/commands' && <Footer />}
106108
</div>
107109
</div>
108110
</>
109111
);
110112
};
111113

112-
export default Layout;
114+
export default Layout;

src/components/PostItem.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ const PostItem = ({
1212
series,
1313
seriesIndex,
1414
isSeries,
15+
description,
16+
tags,
17+
authors,
18+
image,
1519
isActive,
1620
onHover = () => {},
1721
}) => {
@@ -38,7 +42,7 @@ const PostItem = ({
3842
<motion.div
3943
initial={{ opacity: 0, x: -10 }}
4044
animate={{ opacity: 1, x: 0 }}
41-
onMouseEnter={() => onHover({ slug, title, date, updatedDate, category, series, seriesIndex, isSeries })}
45+
onMouseEnter={() => onHover({ slug, title, date, updatedDate, category, series, seriesIndex, isSeries, description, tags, authors, image })}
4246
className="relative mr-4 md:mr-12"
4347
>
4448
<Link

src/pages/CommandsPage.js

Lines changed: 172 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
import React from 'react';
1+
import React, { useState } from 'react';
22
import { Link } from 'react-router-dom';
3-
import { ArrowLeftIcon, TerminalWindowIcon } from '@phosphor-icons/react';
3+
import { motion, AnimatePresence } from 'framer-motion';
44
import useSeo from '../hooks/useSeo';
55
import { useCommandPalette } from '../context/CommandPaletteContext';
6+
import { ArrowLeftIcon, TerminalWindowIcon, CommandIcon } from '@phosphor-icons/react';
7+
import GenerativeArt from '../components/GenerativeArt';
68

79
const commandsData = [
810
{
@@ -342,6 +344,45 @@ const colorClasses = {
342344
},
343345
};
344346

347+
const CommandListItem = ({ cmd, isActive, onHover }) => {
348+
return (
349+
<motion.div
350+
initial={{ opacity: 0, x: -10 }}
351+
whileInView={{ opacity: 1, x: 0 }}
352+
viewport={{ once: true }}
353+
onMouseEnter={() => onHover(cmd)}
354+
className="relative pl-6 md:pl-8 py-3 group cursor-pointer"
355+
>
356+
{/* Active Indicator */}
357+
<div
358+
className={`absolute left-0 top-0 bottom-0 w-0.5 transition-all duration-300 ${
359+
isActive ? 'bg-emerald-400 h-full' : 'bg-transparent h-0 group-hover:h-full group-hover:bg-white/20'
360+
}`}
361+
/>
362+
363+
<div className="flex items-baseline justify-between pr-4">
364+
<h3
365+
className={`text-lg font-playfairDisplay transition-all duration-300 ${
366+
isActive ? 'text-white translate-x-2' : 'text-gray-500 group-hover:text-gray-300'
367+
}`}
368+
>
369+
{cmd.title}
370+
</h3>
371+
372+
{isActive && (
373+
<motion.div
374+
initial={{ opacity: 0, x: -10 }}
375+
animate={{ opacity: 1, x: 0 }}
376+
className="hidden md:block text-emerald-400"
377+
>
378+
<ArrowLeftIcon className="rotate-180"/>
379+
</motion.div>
380+
)}
381+
</div>
382+
</motion.div>
383+
);
384+
};
385+
345386
function CommandsPage() {
346387
useSeo({
347388
title: 'All Commands | Fezcodex',
@@ -357,108 +398,146 @@ function CommandsPage() {
357398
});
358399

359400
const { togglePalette } = useCommandPalette();
401+
const [activeCommand, setActiveCommand] = useState(null);
402+
403+
// Flattened list for random selection if needed, but not used currently
404+
// const allCommands = commandsData.flatMap(c => c.items);
360405

361406
return (
362-
<div className="py-16 sm:py-24">
363-
<div className="mx-auto max-w-7xl px-6 lg:px-8">
364-
<Link
365-
to="/"
366-
className="group text-primary-400 hover:underline flex items-center justify-center gap-2 text-lg mb-4"
367-
>
368-
<ArrowLeftIcon className="text-xl transition-transform group-hover:-translate-x-1" />{' '}
369-
Back to Home
370-
</Link>
371-
<div className="mx-auto max-w-2xl text-center">
372-
<h1 className="text-4xl font-semibold tracking-tight text-white sm:text-6xl flex items-center justify-center">
373-
<TerminalWindowIcon
374-
size={48}
375-
weight="fill"
376-
className="mr-4 mt-1 text-gray-100 "
377-
/>
378-
<span className="text-orange-300">Command</span>&nbsp;Palette
407+
<div className="flex min-h-screen bg-[#050505] text-white overflow-hidden relative selection:bg-emerald-500/30">
408+
409+
{/* Mobile Background */}
410+
<div className="absolute inset-0 lg:hidden opacity-20 pointer-events-none z-0">
411+
<GenerativeArt seed="Commands" className="w-full h-full filter blur-3xl" />
412+
</div>
413+
414+
{/* LEFT PANEL: The Index */}
415+
<div className="w-full lg:w-1/2 lg:max-w-[50vw] relative z-10 flex flex-col min-h-screen py-24 px-6 md:px-20 overflow-y-auto overflow-x-hidden no-scrollbar">
416+
<header className="mb-20">
417+
<Link
418+
to="/"
419+
className="mb-8 inline-flex items-center gap-2 text-xs font-mono text-gray-500 hover:text-white transition-colors uppercase tracking-widest"
420+
>
421+
<ArrowLeftIcon weight="bold" />
422+
<span>Back to Home</span>
423+
</Link>
424+
<h1 className="text-6xl md:text-8xl font-black tracking-tighter text-white mb-4 leading-none">
425+
CMDS
379426
</h1>
380-
<p className="mt-6 text-lg leading-8 text-gray-300">
381-
See all available commands in Command Palette.
427+
<p className="text-gray-400 font-mono text-sm max-w-sm">
428+
{'//'} AVAILABLE INSTRUCTIONS
382429
</p>
383-
</div>
384-
<div className="flex justify-center items-center mt-16">
385-
<div
386-
className="group bg-[#1A2E1A50] rounded-[0.25rem] border border-neutral-700 shadow-2xl p-6 flex flex-col justify-between relative transform overflow-hidden h-full w-full max-w-4xl"
387-
>
388-
<div
389-
className="absolute top-0 left-0 w-full h-full opacity-10"
390-
style={{
391-
backgroundImage:
392-
'radial-gradient(circle, white 1px, transparent 1px)',
393-
backgroundSize: '10px 10px',
394-
}}
395-
></div>
396-
<div className="relative z-10 p-1 font-mono">
397-
<h1 className="text-3xl font-playfairDisplay font-normal mb-4 text-lime-200">
398-
Command Palette
399-
</h1>
400-
<hr className="border-gray-700 mb-4" />
430+
</header>
401431

402-
<div className="mb-6 ml-4 mr-4">
403-
<p className="text-gray-200 mb-4">
404-
Press <kbd className="kbd kbd-sm text-black border rounded-lg px-1 bg-gray-200">Alt/Ctrl</kbd> + <kbd className="kbd kbd-sm text-black border rounded-lg px-1 bg-gray-200">K</kbd> to open
405-
Commands Palette. It lists all available
406-
<code className="text-red-400"> PAGE</code>,
407-
<code className="text-red-400"> POST</code>,
408-
<code className="text-red-400"> PROJECT</code>,
409-
<code className="text-red-400"> LOG</code>,
410-
<code className="text-red-400"> APP</code> and
411-
<code className="text-red-400"> COMMAND</code> that can be
412-
used/consumed in Fezcodex.
413-
<br />
414-
<br />
415-
You can type{' '}
416-
<code className="text-emerald-300"> COMMAND </code> to see all
417-
available commands.
418-
</p>
419-
<button
420-
onClick={togglePalette}
421-
className="border border-gray-200 bg-black/50 hover:bg-gray-50 text-white hover:text-black font-mono py-3 px-4 rounded w-full transition-colors duration-300 flex items-center justify-center gap-2"
422-
>
423-
<TerminalWindowIcon size={24} />
424-
Open Command Palette
425-
</button>
432+
<div className="flex flex-col pb-32 gap-12">
433+
{commandsData.map((category, catIndex) => (
434+
<div key={catIndex}>
435+
<h2 className="font-mono text-xs text-emerald-500 uppercase tracking-widest mb-6 border-b border-white/10 pb-2">
436+
{category.category}
437+
</h2>
438+
<div className="flex flex-col">
439+
{category.items.map((cmd, cmdIndex) => (
440+
<CommandListItem
441+
key={cmd.title}
442+
cmd={cmd}
443+
isActive={activeCommand?.title === cmd.title}
444+
onHover={setActiveCommand}
445+
/>
446+
))}
426447
</div>
448+
</div>
449+
))}
450+
</div>
451+
</div>
427452

428-
<h1 className="text-3xl font-playfairDisplay font-normal mb-4 text-app">
429-
Available Commands
430-
</h1>
431-
<hr className="border-gray-700 mb-6" />
453+
{/* RIGHT PANEL: The Stage (Desktop Only) */}
454+
<div className="hidden lg:flex fixed right-0 top-0 h-screen w-1/2 bg-neutral-900 overflow-hidden border-l border-white/10 z-20 flex-col">
432455

433-
{commandsData.map((category, catIndex) => (
434-
<div key={catIndex} className="mb-8">
435-
<h2 className="text-2xl font-playfairDisplay font-semibold text-gray-200 mb-4 border-b border-gray-700 pb-2 inline-block">
436-
{category.category}
437-
</h2>
438-
<div className="grid grid-cols-1 gap-4">
439-
{category.items.map((cmd, cmdIndex) => {
440-
const classes =
441-
colorClasses[cmd.color] || colorClasses.gray;
442-
return (
443-
<div
444-
key={cmdIndex}
445-
className={`${classes.bg} bg-opacity-30 border ${classes.border} ${classes.text} px-4 py-3 rounded relative`}
446-
role="alert"
447-
>
448-
<strong className="font-bold">{cmd.title}:</strong>
449-
<span className="block sm:inline ml-2">
450-
{cmd.description}
456+
{/* Main Content Area (Grows) */}
457+
<div className="flex-1 relative overflow-hidden">
458+
<AnimatePresence mode="wait">
459+
{activeCommand ? (
460+
<motion.div
461+
key={activeCommand.title}
462+
initial={{ opacity: 0 }}
463+
animate={{ opacity: 1 }}
464+
exit={{ opacity: 0 }}
465+
transition={{ duration: 0.4 }}
466+
className="absolute inset-0 flex flex-col justify-end p-20 pb-8"
467+
>
468+
{/* Background */}
469+
<div className="absolute inset-0 z-0">
470+
<GenerativeArt seed={activeCommand.title} className="w-full h-full opacity-60" />
471+
<div className="absolute inset-0 bg-gradient-to-t from-[#050505] via-[#050505]/80 to-transparent" />
472+
<div className="absolute inset-0 bg-noise opacity-10 mix-blend-overlay" />
473+
</div>
474+
475+
<div className="relative z-10">
476+
<div className="mb-6">
477+
<span className={`inline-block px-3 py-1 text-xs font-mono uppercase tracking-wider rounded-full border bg-opacity-20 backdrop-blur-md mb-4 ${
478+
colorClasses[activeCommand.color]?.text || 'text-white'
479+
} ${colorClasses[activeCommand.color]?.border || 'border-white'} ${colorClasses[activeCommand.color]?.bg || 'bg-gray-800'}`}>
480+
{activeCommand.color}
451481
</span>
452482
</div>
453-
);
454-
})}
455-
</div>
456-
</div>
457-
))}
483+
484+
<h2 className="text-5xl font-playfairDisplay text-white mb-6 leading-tight">
485+
{activeCommand.title}
486+
</h2>
487+
488+
<p className="text-xl text-gray-300 font-light max-w-xl leading-relaxed">
489+
{activeCommand.description}
490+
</p>
491+
</div>
492+
</motion.div>
493+
) : (
494+
<motion.div
495+
key="default-state"
496+
initial={{ opacity: 0 }}
497+
animate={{ opacity: 1 }}
498+
exit={{ opacity: 0 }}
499+
className="absolute inset-0 flex items-center justify-center p-12 text-center"
500+
>
501+
<div className="absolute inset-0 z-0 opacity-20">
502+
<div className="w-full h-full bg-[radial-gradient(circle_at_center,_var(--tw-gradient-stops))] from-gray-800 via-black to-black" />
503+
</div>
504+
505+
<div className="relative z-10 max-w-lg">
506+
<TerminalWindowIcon size={64} className="mx-auto mb-8 text-emerald-500/50" />
507+
<h2 className="text-4xl font-playfairDisplay text-white mb-6">
508+
Command Palette
509+
</h2>
510+
<p className="text-gray-400 mb-8 leading-relaxed">
511+
Access all features and navigations quickly.
512+
<br/>
513+
Hover over the list to see details.
514+
</p>
515+
</div>
516+
</motion.div>
517+
)}
518+
</AnimatePresence>
519+
</div>
520+
521+
{/* Persistent Footer (Always Visible) */}
522+
<div className="p-8 border-t border-white/10 bg-neutral-900/80 backdrop-blur-md z-30 flex items-center justify-between gap-6">
523+
<div className="hidden xl:flex items-center gap-4 text-sm font-mono text-gray-400">
524+
<div className="flex gap-1">
525+
<kbd className="px-2 py-1 bg-white/10 rounded border border-white/20 text-white">Ctrl</kbd>
526+
<span className="self-center">+</span>
527+
<kbd className="px-2 py-1 bg-white/10 rounded border border-white/20 text-white">K</kbd>
528+
</div>
529+
<span>to open anywhere</span>
530+
</div>
531+
532+
<button
533+
onClick={togglePalette}
534+
className="flex-1 xl:flex-none group relative inline-flex items-center justify-center gap-3 px-6 py-4 bg-white text-black hover:bg-emerald-400 transition-colors duration-300 font-mono uppercase tracking-widest text-sm"
535+
>
536+
<CommandIcon size={20} />
537+
<span>Open Palette</span>
538+
</button>
539+
</div>
458540
</div>
459-
</div>
460-
</div>
461-
</div>
462541
</div>
463542
);
464543
}

src/pages/HomePage.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ const Hero = () => {
6565
<ArrowRight weight="bold" className="group-hover:translate-x-1 transition-transform" />
6666
</Link>
6767
<Link to="/about" className="group flex items-center gap-3 border border-white/20 px-6 py-3 rounded-sm font-bold uppercase tracking-widest text-xs text-white transition-all hover:bg-white/5">
68-
System Info
68+
About Me
6969
</Link>
7070
</div>
7171
</div>

src/pages/StandardBlogPostPage.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ const StandardBlogPostPage = () => {
168168
</ReactMarkdown>
169169
</div>
170170

171-
{/* Series Nav */}
171+
{/* {prevPost || nextPost} Series Nav */}
172172
{(prevPost || nextPost) && (
173173
<div className="mt-24 grid grid-cols-1 md:grid-cols-2 gap-4 border-t border-white/10 pt-12">
174174
{prevPost ? (

0 commit comments

Comments
 (0)