|
| 1 | +--- |
| 2 | +name: build-partner-logo-hover |
| 3 | +description: Construct, extend, and QA the Computational Biology at Berkeley partner-logo collage with transparent light/dark assets, shared Home and Collaborations data, linked depth-and-zoom hover motion, responsive fallback layout, reduced-motion support, and collision-safe desktop placement. Use when adding or replacing a partner logo, changing collage positions, modifying the DepthCard hover effect, fixing logo overlap, or verifying the partner wall in this repository. |
| 4 | +--- |
| 5 | + |
| 6 | +# Build Partner Logo Hover |
| 7 | + |
| 8 | +Build the existing irregular logo composition without duplicating data, introducing opaque cards, or letting rest, drift, and hover envelopes collide. |
| 9 | + |
| 10 | +## Read the implementation first |
| 11 | + |
| 12 | +Inspect these files in order: |
| 13 | + |
| 14 | +1. `src/data/partners.ts` — single partner registry and desktop placement. |
| 15 | +2. `src/components/PartnerLogoWall.tsx` — shared rendering for Home and Collaborations. |
| 16 | +3. `src/components/react-bits/depth-card.tsx` — pointer-driven depth and spotlight behavior. |
| 17 | +4. `src/index.css` — drift, lift, scale, shadow, focus, and reduced-motion rules. |
| 18 | +5. `src/lib/publicAsset.ts` — GitHub Pages-safe public asset paths. |
| 19 | +6. `public/partners/SOURCES.md` and `scripts/build-partner-logos.mjs` — asset provenance and reproducible processing. |
| 20 | + |
| 21 | +Preserve `PartnerLogoWall` as the only rendering implementation. Keep both pages connected to `partners`; never maintain separate Home and Collaborations logo lists. |
| 22 | + |
| 23 | +## Add or replace a partner |
| 24 | + |
| 25 | +1. Verify the organization name and outbound website. |
| 26 | +2. Prefer an official transparent SVG, EPS, PNG, or WebP. Keep a low-resolution official mark when no better source exists; do not invent fidelity. |
| 27 | +3. Store production assets under `public/partners/raster/`. Add a dark variant only when the original loses contrast in dark mode. |
| 28 | +4. Document the original source and any transformation in `public/partners/SOURCES.md`. |
| 29 | +5. Update `scripts/build-partner-logos.mjs` when the asset is generated or reproducibly transformed. |
| 30 | +6. Add exactly one entry to `src/data/partners.ts` with: |
| 31 | + - `name` |
| 32 | + - canonical `website` |
| 33 | + - local `logoPath` |
| 34 | + - optional `darkLogoPath` |
| 35 | + - `logoClassName` |
| 36 | + - responsive `collageClassName` |
| 37 | + - `brandSourceUrl` or `sourceNote` |
| 38 | +7. Resolve assets through `publicAssetPath`; do not concatenate `/` paths that break the GitHub Pages subpath. |
| 39 | + |
| 40 | +Keep transparent pixels transparent. Do not add a white rectangle behind a mark to make dark mode pass. |
| 41 | + |
| 42 | +## Construct the hover effect |
| 43 | + |
| 44 | +Reuse `DepthCard` as the semantic `<a>` wrapper. Keep the motion split into independent layers: |
| 45 | + |
| 46 | +- `.partner-collage-slot`: slow vertical drift and stacking context. |
| 47 | +- `.partner-logo-link`: hover/focus lift and `scale(1.065)`. |
| 48 | +- `DepthCard` inner layer: pointer-relative `rotateX` and `rotateY`. |
| 49 | +- `DepthCard` content layer: small pointer-relative translation at positive Z depth. |
| 50 | +- `.partner-logo-image`: transparent artwork and hover drop shadow. |
| 51 | +- Caption: organization name plus external-link affordance. |
| 52 | + |
| 53 | +Keep these behavior contracts: |
| 54 | + |
| 55 | +- Open partner websites in a new tab with `rel="noopener noreferrer"`. |
| 56 | +- Give every link an accessible name: `Visit {partner.name} website`. |
| 57 | +- Make `:focus-visible` equivalent to hover. |
| 58 | +- Disable pointer tilt below 768 px. |
| 59 | +- Honor `prefers-reduced-motion`. |
| 60 | +- Keep motion restrained: use the existing `maxRotation={6}`, `maxTranslation={4}`, 5 px lift, and 1.065 scale unless the entire collision model is revalidated. |
| 61 | +- Raise only the active slot with `z-index`; do not use z-index to hide a collision. |
| 62 | + |
| 63 | +Do not add a global cursor, opaque card shell, silk-wave background, or site-wide 3D tilt. Preserve the Signal Light visual language. |
| 64 | + |
| 65 | +## Place the collage |
| 66 | + |
| 67 | +Use the mobile grid as the fallback and apply freeform coordinates only at `md:`: |
| 68 | + |
| 69 | +```ts |
| 70 | +collageClassName: |
| 71 | + "col-span-1 md:left-[58%] md:top-[57%] md:w-[16%]" |
| 72 | +``` |
| 73 | + |
| 74 | +Treat `left`, `top`, and `width` as a composition system: |
| 75 | + |
| 76 | +- Keep primary horizontal wordmarks wider. |
| 77 | +- Give tall marks narrower slots. |
| 78 | +- Preserve intentional negative space. |
| 79 | +- Move neighboring marks in small percentage increments. |
| 80 | +- Avoid solving one collision by creating another downstream. |
| 81 | + |
| 82 | +### Validate the full motion envelope |
| 83 | + |
| 84 | +Do not compare resting rectangles only. For each logo, include: |
| 85 | + |
| 86 | +- Half of the scale growth: `width × 0.0325` horizontally and `height × 0.0325` vertically. |
| 87 | +- Up to 4 px of pointer translation. |
| 88 | +- 5 px of hover lift above the logo. |
| 89 | +- Relative drift between neighboring animation phases. |
| 90 | +- At least 6–8 px of visual safety margin. |
| 91 | + |
| 92 | +Two logos may overlap on one axis. They must remain separated on the other axis after both envelopes are expanded. |
| 93 | + |
| 94 | +Use the rendered DOM as the authority. Measure every `a[aria-label^="Visit "]` with `getBoundingClientRect()`, expand each rectangle for the maximum motion envelope, and compare every pair. A valid desktop result has zero intersecting pairs on both routes. |
| 95 | + |
| 96 | +## Verify the result |
| 97 | + |
| 98 | +Run: |
| 99 | + |
| 100 | +```bash |
| 101 | +npx tsc --noEmit |
| 102 | +npx eslint src/data/partners.ts src/components/PartnerLogoWall.tsx src/components/react-bits/depth-card.tsx |
| 103 | +VITE_BASE_PATH=/compbioatberkeley.github.io/ npm run build:preview |
| 104 | +``` |
| 105 | + |
| 106 | +Then check in a real browser: |
| 107 | + |
| 108 | +1. Home and `/collaborations`. |
| 109 | +2. Light and dark themes. |
| 110 | +3. Resting geometry and maximum hover/focus enlargement. |
| 111 | +4. The narrow/mobile grid. |
| 112 | +5. Keyboard focus, visible caption, and reduced motion. |
| 113 | +6. Every local logo request under the GitHub Pages base path. |
| 114 | +7. Every partner link destination without transmitting data. |
| 115 | + |
| 116 | +After pushing `dev`, wait for the staging workflow and repeat the collision check on the public staging URL. A successful build alone is not visual proof. |
| 117 | + |
| 118 | +## Protect repository scope |
| 119 | + |
| 120 | +Stage only files belonging to the requested change. Preserve unrelated local asset work. Push to `dev` for staging unless the user explicitly requests production; leave `main` untouched. |
0 commit comments