feat(experience): skills e experiencia visiveis (aberta em telas largas) e link Experiencia no menu
- ExperienceDisclosure abre a gaveta em >=1024px e quando o link aponta para #experience/#skills; no celular segue recolhida - novo item Experiencia em NAVIGATION_ITEMS (desktop e menu mobile); testes do Header atualizados Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
This commit is contained in:
1 parent
d5f04162a8
commit
2b5b4a2267
4 files changed
+82
-7
No files matched your search
@@ -16,6 +16,7 @@ import Projects from "../Projects";
|
||||
import Skills from "../Skills";
|
||||
import NotebookStory from "../story/NotebookStory";
|
||||
import { WorkModalities } from "../WorkModalities";
|
||||
import ExperienceDisclosure from "./ExperienceDisclosure";
|
||||
import ScrollVelocityText from "./ScrollVelocityText";
|
||||
import SectionDivider from "./SectionDivider";
|
||||
import { useHomeFragmentNavigation } from "./useHomeFragmentNavigation";
|
||||
@@ -56,13 +57,10 @@ export default function CinematicHome({
|
||||
|
||||
<About />
|
||||
|
||||
<details className="ds-section !pt-0">
|
||||
<summary className="ds-section-shell cursor-pointer py-sp-5 text-lg font-semibold">
|
||||
Experiência e tecnologias por trás das entregas
|
||||
</summary>
|
||||
<ExperienceDisclosure>
|
||||
<Skills categories={skillCategories} />
|
||||
<Experience experiences={experiences} />
|
||||
</details>
|
||||
</ExperienceDisclosure>
|
||||
|
||||
<div className="overflow-hidden bg-[var(--ink)] py-6 text-[rgba(244,242,237,0.05)]">
|
||||
<ScrollVelocityText text="VAMOS CONSTRUIR" direction="left" />
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
"use client";
|
||||
|
||||
import { type ReactNode, useEffect, useState } from "react";
|
||||
|
||||
const TARGETS = new Set(["#experience", "#skills"]);
|
||||
|
||||
/**
|
||||
* Skills e Experiência ficavam numa gaveta sempre fechada e sem link no menu.
|
||||
* Agora abre sozinha em telas largas (onde há espaço) e quando um link aponta para #experience ou #skills;
|
||||
* no celular continua recolhida para a página não crescer.
|
||||
*/
|
||||
export default function ExperienceDisclosure({
|
||||
children,
|
||||
}: {
|
||||
children: ReactNode;
|
||||
}) {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const reveal = (hash: string) => {
|
||||
if (!TARGETS.has(hash)) return;
|
||||
setOpen(true);
|
||||
// espera o React abrir a gaveta para o alvo existir no layout
|
||||
requestAnimationFrame(() =>
|
||||
document
|
||||
.getElementById(hash.slice(1))
|
||||
?.scrollIntoView({ behavior: "instant", block: "start" }),
|
||||
);
|
||||
};
|
||||
if (window.matchMedia("(min-width: 1024px)").matches) setOpen(true);
|
||||
else if (TARGETS.has(window.location.hash)) setOpen(true);
|
||||
|
||||
const onClick = (event: MouseEvent) => {
|
||||
const link =
|
||||
event.target instanceof Element
|
||||
? event.target.closest("a[href*='#']")
|
||||
: null;
|
||||
if (!(link instanceof HTMLAnchorElement)) return;
|
||||
const url = new URL(link.href);
|
||||
if (url.pathname === window.location.pathname) reveal(url.hash);
|
||||
};
|
||||
const onHashChange = () => reveal(window.location.hash);
|
||||
document.addEventListener("click", onClick);
|
||||
window.addEventListener("hashchange", onHashChange);
|
||||
return () => {
|
||||
document.removeEventListener("click", onClick);
|
||||
window.removeEventListener("hashchange", onHashChange);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<details
|
||||
open={open}
|
||||
onToggle={(event) => setOpen(event.currentTarget.open)}
|
||||
className="ds-section !pt-0"
|
||||
>
|
||||
<summary className="ds-section-shell cursor-pointer py-sp-5 text-lg font-semibold">
|
||||
Experiência e tecnologias por trás das entregas
|
||||
</summary>
|
||||
{children}
|
||||
</details>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user