diff --git a/src/components/AnimatedBackground.tsx b/src/components/AnimatedBackground.tsx index 1c33f83..28de948 100644 --- a/src/components/AnimatedBackground.tsx +++ b/src/components/AnimatedBackground.tsx @@ -222,7 +222,6 @@ const AnimatedBackground: React.FC = () => { const particleCount = 500; const gridSize = 50; // Spatial partitioning grid size const mouseRadius = 800; - const mouseRadiusSquared = mouseRadius * mouseRadius; const maxLineLength = 95; const maxLineLengthSquared = maxLineLength * maxLineLength; const propagationRadius = 40; // Valor mais realista para propagação visível @@ -242,20 +241,49 @@ const AnimatedBackground: React.FC = () => { const opacityCache = new OpacityCache(); const mouse = { x: -1000, y: -1000 }; + let globalOpacity = 0; + let targetOpacity = 0; + const opacitySpeed = 0.01; // Velocidade suave de fade + let effectiveRadius = 0; + let targetRadius = 0; + const radiusSpeed = 0.005; // Velocidade de shrink/implode mais lenta + + const checkMouseInHero = (x: number, y: number) => { + if (x === -1000 || y === -1000) return false; + const elementUnderMouse = document.elementFromPoint(x, y); + return elementUnderMouse?.closest(".hero") !== null; + }; const handleMouseMove = (e: MouseEvent) => { - mouse.x = e.clientX; - mouse.y = e.clientY; - opacityCache.updateMouse(mouse.x, mouse.y, mouseRadius); + const isInHero = checkMouseInHero(e.clientX, e.clientY); + if (isInHero) { + mouse.x = e.clientX; + mouse.y = e.clientY; + opacityCache.updateMouse(mouse.x, mouse.y, mouseRadius); + targetOpacity = 1; + targetRadius = mouseRadius; + } else { + // Não setar mouse.x = -1000 imediatamente, deixar o raio controlar + targetOpacity = 0; + targetRadius = 0; + } }; const handleMouseLeave = () => { - mouse.x = -1000; - mouse.y = -1000; + targetOpacity = 0; + targetRadius = 0; + }; + + const handleScroll = () => { + if (!checkMouseInHero(mouse.x, mouse.y)) { + targetOpacity = 0; + targetRadius = 0; + } }; window.addEventListener("mousemove", handleMouseMove, { passive: true }); window.addEventListener("mouseleave", handleMouseLeave, { passive: true }); + window.addEventListener("scroll", handleScroll, { passive: true }); const particles: Particle[] = []; for (let i = 0; i < particleCount; i++) { @@ -268,6 +296,16 @@ const AnimatedBackground: React.FC = () => { const animate = () => { frameCount++; + // Update global opacity and effective radius for smooth transitions + globalOpacity += (targetOpacity - globalOpacity) * opacitySpeed; + effectiveRadius += (targetRadius - effectiveRadius) * radiusSpeed; + + // Stop animation when radius reaches zero + if (effectiveRadius <= 1) { + mouse.x = -1000; + mouse.y = -1000; + } + // Clear canvas ctx.fillStyle = "#000000"; ctx.fillRect(0, 0, canvas.width, canvas.height); @@ -293,11 +331,12 @@ const AnimatedBackground: React.FC = () => { ? spatialGrid.getNeighbors(mouseGridX, mouseGridY, mouseRadius) : []; - // Filter particles within mouse radius + // Filter particles within effective radius + const effectiveRadiusSquared = effectiveRadius * effectiveRadius; const connectedParticles: Particle[] = []; for (const p of nearbyParticles) { const distSquared = distanceCache.get(mouse.x, mouse.y, p.x, p.y); - if (distSquared < mouseRadiusSquared) { + if (distSquared < effectiveRadiusSquared) { p.layer = 0; // Partículas conectadas diretamente ao mouse = camada 0 connectedParticles.push(p); } @@ -306,6 +345,7 @@ const AnimatedBackground: React.FC = () => { if (connectedParticles.length > 0) { ctx.save(); ctx.globalCompositeOperation = "lighter"; + ctx.globalAlpha = globalOpacity; const processedSet = new Set(connectedParticles); @@ -565,12 +605,24 @@ const AnimatedBackground: React.FC = () => { window.removeEventListener("resize", resize); window.removeEventListener("mousemove", handleMouseMove); window.removeEventListener("mouseleave", handleMouseLeave); + window.removeEventListener("scroll", handleScroll); cancelAnimationFrame(animationFrameId); }; }, []); return ( -
+
); diff --git a/src/sections/About.scss b/src/sections/About.scss index 299d5fd..5fb1439 100644 --- a/src/sections/About.scss +++ b/src/sections/About.scss @@ -9,6 +9,9 @@ display: flex; flex-direction: column; align-items: center; + background: rgba(0, 0, 0, 0.85); // Contraste com o background animado + padding: 2rem; + border-radius: 10px; @media (max-width: 1500px) { width: 1100px; diff --git a/src/sections/Contact.scss b/src/sections/Contact.scss index f276a91..b4ce4c7 100644 --- a/src/sections/Contact.scss +++ b/src/sections/Contact.scss @@ -13,6 +13,9 @@ justify-content: center; z-index: 10; margin-bottom: 10rem; + background: rgba(0, 0, 0, 0.85); // Contraste com o background animado + padding: 2rem; + border-radius: 10px; @media (max-width: 700px) { width: 400px; diff --git a/src/sections/Experience.scss b/src/sections/Experience.scss index 48d5fcc..c04883c 100644 --- a/src/sections/Experience.scss +++ b/src/sections/Experience.scss @@ -19,6 +19,9 @@ width: 1300px; margin-left: auto; margin-right: auto; + background: rgba(0, 0, 0, 0.85); // Contraste com o background animado + padding: 2rem; + border-radius: 10px; display: flex; flex-direction: column; align-items: center; diff --git a/src/sections/Hero.tsx b/src/sections/Hero.tsx index 344d737..a71f772 100644 --- a/src/sections/Hero.tsx +++ b/src/sections/Hero.tsx @@ -1,6 +1,5 @@ import { ArrowRight, Download } from "lucide-react"; import { Helmet } from "react-helmet-async"; -import AnimatedBackground from "../components/AnimatedBackground"; import "./Hero.scss"; const Hero: React.FC = () => { @@ -13,7 +12,6 @@ const Hero: React.FC = () => { content="Portfólio de Matheus Caiser, desenvolvedor web Full Stack especialista em criar soluções modernas e performáticas com React, Node.js, TypeScript e outras tecnologias de ponta." /> -

From 7f529eb96c56fd47ce2784ae387d295824e3fb04 Mon Sep 17 00:00:00 2001 From: Matheus Henrique Caiser Barrozo Date: Wed, 29 Oct 2025 20:57:54 -0300 Subject: [PATCH 2/2] ci: definitive config workflow --- .github/workflows/preview.yml | 73 ++++++++++++++++ .github/workflows/{ci.yml => production.yml} | 90 +++++--------------- vercel.json | 5 +- 3 files changed, 96 insertions(+), 72 deletions(-) create mode 100644 .github/workflows/preview.yml rename .github/workflows/{ci.yml => production.yml} (50%) diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml new file mode 100644 index 0000000..5c1d8b2 --- /dev/null +++ b/.github/workflows/preview.yml @@ -0,0 +1,73 @@ +name: Vercel Preview Deployment + +# Variáveis de ambiente para os jobs da Vercel +env: + VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} + VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} + +on: + push: + branches: + - develop + pull_request: + branches: [main, develop] + +jobs: + # ----------------------------------------------------------------- + # JOB 1: Testa e Linta o código + # ----------------------------------------------------------------- + test-and-lint: + name: Test & Lint + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [22.x] + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 10 + + - name: Setup Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: "pnpm" + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Run linter + run: pnpm run lint + + - name: Run tests + run: pnpm run test:ci + + # ----------------------------------------------------------------- + # JOB 2: Deploy de Preview (Vercel) + # ----------------------------------------------------------------- + deploy-preview: + name: Deploy Preview + needs: test-and-lint + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install Vercel CLI + run: npm install --global vercel@latest + + - name: Pull Vercel Environment Information + run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }} + + - name: Build Project Artifacts + run: vercel build --token=${{ secrets.VERCEL_TOKEN }} + + - name: Deploy Project Artifacts to Vercel + # A Vercel CLI detecta o contexto de PR e posta o comentário automaticamente + run: vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }} diff --git a/.github/workflows/ci.yml b/.github/workflows/production.yml similarity index 50% rename from .github/workflows/ci.yml rename to .github/workflows/production.yml index 5f42982..8ad1060 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/production.yml @@ -1,14 +1,18 @@ -name: CI/CD Pipeline com Tagging +name: Vercel Production Deployment and Tagging + +# Variáveis de ambiente para os jobs da Vercel +env: + VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} + VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} on: push: - branches: [main, develop] - pull_request: - branches: [main, develop] + branches: + - main jobs: # ----------------------------------------------------------------- - # JOB 1: Apenas Testa e Linta + # JOB 1: Testa e Linta o código # ----------------------------------------------------------------- test-and-lint: name: Test & Lint @@ -48,11 +52,6 @@ jobs: name: Deploy to Production needs: test-and-lint runs-on: ubuntu-latest - permissions: - contents: write - pull-requests: write - deployments: write - if: github.ref == 'refs/heads/main' && github.event_name == 'push' steps: - name: Checkout code @@ -71,62 +70,7 @@ jobs: run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }} # ----------------------------------------------------------------- - # JOB 3: Deploy de Preview - # ----------------------------------------------------------------- - deploy-preview: - name: Deploy Preview - needs: test-and-lint - runs-on: ubuntu-latest - permissions: - contents: write - pull-requests: write - deployments: write - if: github.event_name == 'pull_request' || (github.ref == 'refs/heads/develop' && github.event_name == 'push') - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Install Vercel CLI - run: npm install --global vercel@latest - - - name: Pull Vercel Environment Information - run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }} - - - name: Build Project Artifacts - run: vercel build --token=${{ secrets.VERCEL_TOKEN }} - - - name: Deploy Project Artifacts to Vercel - run: vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }} - - - name: Get Repo ID - if: github.event_name == 'pull_request' - run: | - REPO_ID=$(curl -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" https://api.github.com/repos/${{ github.repository }} | jq -r .id) - echo "REPO_ID=$REPO_ID" >> $GITHUB_ENV - - - name: Notify Vercel for PR Comment (if PR) - if: github.event_name == 'pull_request' - run: | - curl -X POST "https://api.vercel.com/v13/deployments" \ - -H "Authorization: Bearer ${{ secrets.VERCEL_TOKEN }}" \ - -H "Content-Type: application/json" \ - -d '{ - "name": "mrdeveloper", - "source": "cli", - "gitSource": { - "type": "github", - "repo": "${{ github.repository }}", - "ref": "${{ github.head_ref }}", - "sha": "${{ github.sha }}", - "repoId": ${{ env.REPO_ID }} - } - }' - - - - # ----------------------------------------------------------------- - # JOB 4: Criar Tag de Versão (Sem mudanças) + # JOB 3: Criar Tag de Versão # ----------------------------------------------------------------- tag-release: name: Tag Release @@ -137,6 +81,9 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 + with: + # Necessário para buscar tags existentes + fetch-depth: 0 - name: Get version from package.json id: get_version @@ -145,12 +92,13 @@ jobs: echo "TAG_VERSION=v$VERSION" >> $GITHUB_ENV - name: Check if tag already exists + id: check_tag run: | - if git ls-remote --tags origin | grep -q "refs/tags/${TAG_VERSION}"; then - echo "Tag $TAG_VERSION already exists. Skipping..." + if git rev-parse "refs/tags/${{ env.TAG_VERSION }}" >/dev/null 2>&1; then + echo "Tag ${{ env.TAG_VERSION }} already exists. Skipping..." echo "SKIP_TAG=true" >> $GITHUB_ENV else - echo "Tag $TAG_VERSION does not exist. Proceeding..." + echo "Tag ${{ env.TAG_VERSION }} does not exist. Proceeding..." echo "SKIP_TAG=false" >> $GITHUB_ENV fi @@ -159,5 +107,5 @@ jobs: run: | git config --global user.name "github-actions[bot]" git config --global user.email "github-actions[bot]@users.noreply.github.com" - git tag $TAG_VERSION -m "Release $TAG_VERSION" - git push origin $TAG_VERSION \ No newline at end of file + git tag ${{ env.TAG_VERSION }} -m "Release ${{ env.TAG_VERSION }}" + git push origin ${{ env.TAG_VERSION }} diff --git a/vercel.json b/vercel.json index db46a80..4ae9f15 100644 --- a/vercel.json +++ b/vercel.json @@ -1,5 +1,8 @@ { "buildCommand": "npx pnpm@10 build", "installCommand": "npx pnpm@10 install", - "devCommand": "npx pnpm@10 dev" + "devCommand": "npx pnpm@10 dev", + "git": { + "deploymentEnabled": false + } } \ No newline at end of file