tabs always enabled

This commit is contained in:
2026-02-08 09:16:27 +00:00
parent 6b76673467
commit 72f6277c9f

View File

@@ -48,7 +48,6 @@ export default App;
function Home() { function Home() {
const isDevMode = import.meta.env.VITE_PUBLIC_DEV === "1"; const isDevMode = import.meta.env.VITE_PUBLIC_DEV === "1";
const isTabsEnabled = import.meta.env.VITE_TABS === "1";
const navigate = useNavigate(); const navigate = useNavigate();
const [asciiArt, setAsciiArt] = useState(""); const [asciiArt, setAsciiArt] = useState("");
const [activeHomeTab, setActiveHomeTab] = useState<HomeTab>("work"); const [activeHomeTab, setActiveHomeTab] = useState<HomeTab>("work");
@@ -123,7 +122,7 @@ function Home() {
if (event.defaultPrevented || event.isComposing) return; if (event.defaultPrevented || event.isComposing) return;
if (event.metaKey || event.ctrlKey || event.altKey) return; if (event.metaKey || event.ctrlKey || event.altKey) return;
if (isTabsEnabled && event.key === "Tab") { if (event.key === "Tab") {
event.preventDefault(); event.preventDefault();
setActiveHomeTab((prev) => { setActiveHomeTab((prev) => {
const currentIndex = homeTabs.indexOf(prev); const currentIndex = homeTabs.indexOf(prev);
@@ -428,201 +427,183 @@ function Home() {
Age: <TimeSince date={new Date(2004, 10, 4, 11, 47, 0)} /> Age: <TimeSince date={new Date(2004, 10, 4, 11, 47, 0)} />
</div> </div>
</div> </div>
{isTabsEnabled ? ( <Tabs
<Tabs value={activeHomeTab}
value={activeHomeTab} onValueChange={(value) => setActiveHomeTab(value as HomeTab)}
onValueChange={(value) => setActiveHomeTab(value as HomeTab)} className="w-full max-w-5xl gap-0"
className="w-full max-w-5xl gap-0" >
<TabsList
variant="line"
className="relative z-0 h-auto w-full gap-0 p-0"
> >
<TabsList <TabsTrigger
variant="line" value={homeTabs[0]}
className="relative z-0 h-auto w-full gap-0 p-0" className="border-border -mr-[1px] after:hidden data-[state=active]:text-accent"
> >
<TabsTrigger Work
value={homeTabs[0]} </TabsTrigger>
className="border-border -mr-[1px] after:hidden data-[state=active]:text-accent" <TabsTrigger
> value={homeTabs[1]}
Work className="border-border after:hidden data-[state=active]:text-accent"
</TabsTrigger> >
<TabsTrigger Travel
value={homeTabs[1]} </TabsTrigger>
className="border-border after:hidden data-[state=active]:text-accent" </TabsList>
> <TabsContent value={homeTabs[0]} className="relative z-10">
Travel <div className="-mt-[1.5px] border p-2 grid grid-cols-1 gap-2 md:grid-cols-2">
</TabsTrigger> {visibleProjects.map((project, index) => (
</TabsList> <ProjectListItem
<TabsContent value={homeTabs[0]} className="relative z-10"> key={project.metadata.slug}
<div className="-mt-[1.5px] border p-2 grid grid-cols-1 gap-2 md:grid-cols-2"> metadata={project.metadata}
{visibleProjects.map((project, index) => ( isDevMode={isDevMode}
<ProjectListItem isActive={
key={project.metadata.slug} activeProjectIndex !== null && index === activeProjectIndex
metadata={project.metadata} }
isDevMode={isDevMode} />
isActive={ ))}
activeProjectIndex !== null && index === activeProjectIndex </div>
} </TabsContent>
/> <TabsContent value={homeTabs[1]} className="relative z-10">
))} <div className="-mt-[1px] grid grid-cols-1">
</div> {locations.map((location, index) => (
</TabsContent> <div key={location.id}>
<TabsContent value={homeTabs[1]} className="relative z-10"> <Button
<div className="-mt-[1px] grid grid-cols-1"> className={cn(
{locations.map((location, index) => ( "text-sm border cursor-pointer hover:border-accent justify-start w-full",
<div key={location.id}> activeLocationIndex === index &&
<Button activeHomeTab === "travel" &&
className={cn( travelFocusLevel === "location" &&
"text-sm border cursor-pointer hover:border-accent justify-start", "border-accent",
activeLocationIndex === index && )}
activeHomeTab === "travel" && onClick={(_e) => {
travelFocusLevel === "location" && const isExpanded = expandedLocationIndex === index;
"border-accent", const photos = locationPhotos[location.id] ?? [];
)}
onClick={(_e) => {
const isExpanded = expandedLocationIndex === index;
const photos = locationPhotos[location.id] ?? [];
setActiveLocationIndex(index); setActiveLocationIndex(index);
if (isExpanded) { if (isExpanded) {
setExpandedLocationIndex(null); setExpandedLocationIndex(null);
setTravelFocusLevel("location"); setTravelFocusLevel("location");
setPreviewPhotoPath(null); setPreviewPhotoPath(null);
return; return;
} }
setExpandedLocationIndex(index); setExpandedLocationIndex(index);
if (photos.length === 0) { if (photos.length === 0) {
setTravelFocusLevel("location"); setTravelFocusLevel("location");
setPreviewPhotoPath(null); setPreviewPhotoPath(null);
return; return;
} }
const nextPhotoIndex = clampIndex( const nextPhotoIndex = clampIndex(
activePhotoIndexByLocation[location.id] ?? 0, activePhotoIndexByLocation[location.id] ?? 0,
photos.length, photos.length,
); );
const nextPhotoName = photos[nextPhotoIndex]; const nextPhotoName = photos[nextPhotoIndex];
if (!nextPhotoName) { if (!nextPhotoName) {
setTravelFocusLevel("location"); setTravelFocusLevel("location");
setPreviewPhotoPath(null); setPreviewPhotoPath(null);
return; return;
} }
setActivePhotoIndexByLocation((prev) => ({ setActivePhotoIndexByLocation((prev) => ({
...prev, ...prev,
[location.id]: nextPhotoIndex, [location.id]: nextPhotoIndex,
})); }));
setPreviewPhotoPath( setPreviewPhotoPath(
getTravelPhotoPath(location, nextPhotoName), getTravelPhotoPath(location, nextPhotoName),
); );
setTravelFocusLevel("photo"); setTravelFocusLevel("photo");
}} }}
variant="dummy" variant="dummy"
size="sm" size="sm"
> >
{location.city}, {location.country} - {location.date} {location.city}, {location.country} - {location.date}
</Button> </Button>
{expandedLocationIndex === index && {expandedLocationIndex === index &&
(locationPhotos[location.id].length === 0 ? ( (locationPhotos[location.id].length === 0 ? (
<div className="flex"> <div className="flex">
<div className="flex flex-col flex-1 ml-8"> <div className="flex flex-col flex-1 ml-8">
<Button <Button
disabled disabled
className={cn( className={cn(
"flex text-sm border cursor-pointer hover:border-accent items-center justify-start p-0 pl-2 ", "flex text-sm border cursor-pointer hover:border-accent items-center justify-start p-0 pl-2 w-full",
)}
variant="dummy"
size="sm"
>
<ImageDelete size={16} /> No photos available
</Button>
</div>
</div>
) : (
<div className="flex">
<div
id={getTravelPhotoListId(location.id)}
className="flex flex-col flex-1 ml-8 max-h-128 overflow-y-auto gap-1"
>
{locationPhotos[location.id].map(
(photo, photoIndex) => (
<Button
key={photo}
id={getTravelPhotoItemId(
location.id,
photoIndex,
)}
onClick={() => {
const path = getTravelPhotoPath(
location,
photo,
);
setActiveLocationIndex(index);
setExpandedLocationIndex(index);
setTravelFocusLevel("photo");
setActivePhotoIndexByLocation((prev) => ({
...prev,
[location.id]: photoIndex,
}));
setPreviewPhotoPath(path);
}}
className={cn(
"flex text-sm border cursor-pointer hover:border-accent items-center justify-start p-0 pl-2 ",
activeHomeTab === "travel" &&
travelFocusLevel === "photo" &&
activePhotoIndexByLocation[location.id] ===
photoIndex &&
"border-accent",
)}
variant="dummy"
size="sm"
>
<Image size={22} />
{photo}
</Button>
),
)} )}
</div> variant="dummy"
<div size="sm"
className={
"flex-1 max-w-sm border flex items-center h-128 justify-center text-sm gap-4"
}
> >
{previewPhotoPath ? ( <ImageDelete size={16} /> No photos available
<img </Button>
className={"flex-1 max-w-sm"}
src={previewPhotoPath}
alt={"active-photo"}
/>
) : (
<span>
<ImageDelete />
No photo selected
</span>
)}
</div>
</div> </div>
))} </div>
</div> ) : (
))} <div className="flex">
</div> <div
</TabsContent> id={getTravelPhotoListId(location.id)}
</Tabs> className="flex flex-col flex-1 ml-8 max-h-128 overflow-y-auto gap-1"
) : ( >
<div className="w-full max-w-5xl grid grid-cols-1 gap-2 md:grid-cols-2"> {locationPhotos[location.id].map(
{visibleProjects.map((project, index) => ( (photo, photoIndex) => (
<ProjectListItem <Button
key={project.metadata.slug} key={photo}
metadata={project.metadata} id={getTravelPhotoItemId(location.id, photoIndex)}
isDevMode={isDevMode} onClick={() => {
isActive={ const path = getTravelPhotoPath(
activeProjectIndex !== null && index === activeProjectIndex location,
} photo,
/> );
))} setActiveLocationIndex(index);
</div> setExpandedLocationIndex(index);
)} setTravelFocusLevel("photo");
setActivePhotoIndexByLocation((prev) => ({
...prev,
[location.id]: photoIndex,
}));
setPreviewPhotoPath(path);
}}
className={cn(
"flex text-sm border cursor-pointer hover:border-accent items-center justify-start p-0 pl-2 ",
activeHomeTab === "travel" &&
travelFocusLevel === "photo" &&
activePhotoIndexByLocation[location.id] ===
photoIndex &&
"border-accent",
)}
variant="dummy"
size="sm"
>
<Image size={22} />
{photo}
</Button>
),
)}
</div>
<div
className={
"flex-1 max-w-lg border flex items-center h-128 justify-center text-sm gap-4"
}
>
{previewPhotoPath ? (
<img
className={"flex-1 object-contain max-h-full"}
src={previewPhotoPath}
alt={"active-photo"}
/>
) : (
<span>
<ImageDelete />
No photo selected
</span>
)}
</div>
</div>
))}
</div>
))}
</div>
</TabsContent>
</Tabs>
<div className="w-full max-w-5xl grid grid-cols-1 md:grid-cols-[1fr_auto_1fr] items-center gap-3 md:gap-4"> <div className="w-full max-w-5xl grid grid-cols-1 md:grid-cols-[1fr_auto_1fr] items-center gap-3 md:gap-4">
<div className="flex items-center gap-6"> <div className="flex items-center gap-6">
<AskAI name="me" inline /> <AskAI name="me" inline />