add scroll
continuous-integration/drone/push Build is passing

This commit is contained in:
2026-04-09 14:12:44 +01:00
parent 3aab9adaea
commit 65a29f343c
3 changed files with 96 additions and 57 deletions
+56 -56
View File
@@ -1,5 +1,8 @@
"use client"; // Necessário para animações no Next.js App Router
import Image from "next/image";
import Link from "next/link";
import { motion } from "framer-motion";
const recentes = [
{
@@ -401,79 +404,76 @@ export function TvoneNegocios() {
export function TvoneEscolhaEditor() {
return (
<section className="mx-auto w-full max-w-[1200px] px-4 pb-20">
<section className="mx-auto w-full max-w-[1200px] px-4 pb-20 overflow-hidden">
{/* HEADER */}
<div className="mb-10 flex items-end justify-between border-b border-neutral-100 pb-6">
<div className="max-w-[600px]">
<h2 className="text-3xl font-bold tracking-tight text-neutral-900 md:text-4xl">
Escolha do Editor
</h2>
<p className="mt-2 text-sm md:text-base text-neutral-500 leading-relaxed">
Curadoria exclusiva das histórias mais impactantes do dia, selecionadas pela nossa redação.
</p>
</div>
<Link
href="/escolhas"
className="group flex items-center gap-1 text-sm font-semibold text-[#0066CC] transition-colors hover:text-[#004499] whitespace-nowrap mb-1"
>
<h2 className="text-3xl font-bold tracking-tight text-neutral-900 md:text-4xl">
Escolha do Editor
</h2>
<Link href="/escolhas" className="group flex items-center gap-1 text-sm font-semibold text-[#0066CC]">
Ver tudo
<svg className="h-4 w-4 transition-transform group-hover:translate-x-0.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2.5}>
<path strokeLinecap="round" strokeLinejoin="round" d="M9 5l7 7-7 7" />
<path d="M9 5l7 7-7 7" />
</svg>
</Link>
</div>
{/* CONTAINER DE SCROLL:
- flex e overflow-x-auto no mobile
- md:grid no desktop
- snap-x para efeito de 'imã' ao scrollar
*/}
<div className="no-scrollbar -mx-4 flex snap-x snap-mandatory overflow-x-auto px-4 gap-6 md:mx-0 md:grid md:grid-cols-3 md:overflow-x-visible md:gap-10">
{editorChoice.map((item, index) => (
{/* CONTAINER COM ANIMACÃO "WHILE IN VIEW" */}
<motion.div
initial={{ x: 80, opacity: 0 }}
whileInView={{ x: 0, opacity: 1 }} // Dispara quando entra na viewport
viewport={{ once: true, margin: "-100px" }} // Executa uma vez, 100px antes de chegar no centro
transition={{
type: "spring",
stiffness: 200, // Aumentado de 50 para 200 (muito mais rápido)
damping: 25, // Mantém o controle para não balançar demais
mass: 0.5 // Reduzimos a massa para o objeto parecer mais leve
}}
className="no-scrollbar flex flex-col gap-10 md:flex-row md:overflow-x-auto md:snap-x md:snap-mandatory md:gap-8 md:pb-6"
>
{editorChoice.slice(0, 6).map((item, index) => (
<article
key={index}
className="min-w-[85vw] snap-start flex flex-col gap-5 sm:min-w-[50vw] md:min-w-full"
className={`group flex flex-col gap-5 md:min-w-[31%] md:snap-start
${index >= 3 ? 'hidden md:flex' : 'flex'}`}
>
<div className="relative aspect-video overflow-hidden rounded-[24px] bg-neutral-100 shadow-sm transition-all duration-500 group-hover:shadow-md">
<Image
src={item.img}
alt=""
fill
className="object-cover transition-transform duration-700 group-hover:scale-105"
/>
</div>
<div className="px-1">
<div className="flex items-center gap-3">
<span className="text-[10px] font-bold uppercase tracking-wider text-blue-600">
{item.category}
</span>
<span className="h-1 w-1 rounded-full bg-neutral-300" />
<span className="text-[10px] font-semibold text-neutral-500 uppercase tracking-tight">
{item.publishDate}
</span>
<Link href="#" className="block">
<div className="relative aspect-video overflow-hidden rounded-[24px] bg-neutral-100 shadow-sm transition-all duration-500 group-hover:shadow-xl">
<Image
src={item.img}
alt={item.title}
fill
className="object-cover transition-transform duration-700 group-hover:scale-105"
/>
</div>
<h3 className="mt-3 text-xl font-bold leading-snug text-neutral-900 transition-colors group-hover:text-[#0066CC]">
{item.title}
</h3>
<div className="mt-5 px-1">
<div className="flex items-center gap-3">
<span className="text-[10px] font-bold uppercase tracking-wider text-blue-600">{item.category}</span>
<span className="h-1 w-1 rounded-full bg-neutral-300" />
<span className="text-[10px] font-semibold text-neutral-500 uppercase tracking-tight">{item.publishDate}</span>
</div>
<p className="mt-3 line-clamp-2 text-sm leading-relaxed text-neutral-500">
{item.description}
</p>
<h3 className="mt-3 text-xl font-bold leading-snug text-neutral-900 group-hover:text-[#0066CC] transition-colors">
{item.title}
</h3>
<p className="mt-3 line-clamp-2 text-sm leading-relaxed text-neutral-500">{item.description}</p>
<div className="mt-5 flex items-center gap-2 border-t border-neutral-50 pt-4">
<svg className="h-3.5 w-3.5 text-neutral-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span className="text-[10px] font-bold uppercase text-neutral-400">
{item.readTime} min de leitura
</span>
</div>
<div className="mt-5 flex items-center gap-2 border-t border-neutral-50 pt-4">
<svg className="h-3.5 w-3.5 text-neutral-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span className="text-[10px] font-bold uppercase text-neutral-400">
{item.readTime} min de leitura
</span>
</div>
</div>
</Link>
</article>
))}
</div>
</motion.div>
</section>
);
}
+1
View File
@@ -9,6 +9,7 @@
"lint": "eslint"
},
"dependencies": {
"framer-motion": "^12.38.0",
"next": "16.2.1",
"react": "19.2.4",
"react-dom": "19.2.4"
+38
View File
@@ -8,6 +8,9 @@ importers:
.:
dependencies:
framer-motion:
specifier: ^12.38.0
version: 12.38.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
next:
specifier: 16.2.1
version: 16.2.1(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
@@ -1130,6 +1133,20 @@ packages:
resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==}
engines: {node: '>= 0.4'}
framer-motion@12.38.0:
resolution: {integrity: sha512-rFYkY/pigbcswl1XQSb7q424kSTQ8q6eAC+YUsSKooHQYuLdzdHjrt6uxUC+PRAO++q5IS7+TamgIw1AphxR+g==}
peerDependencies:
'@emotion/is-prop-valid': '*'
react: ^18.0.0 || ^19.0.0
react-dom: ^18.0.0 || ^19.0.0
peerDependenciesMeta:
'@emotion/is-prop-valid':
optional: true
react:
optional: true
react-dom:
optional: true
function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
@@ -1521,6 +1538,12 @@ packages:
minimist@1.2.8:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
motion-dom@12.38.0:
resolution: {integrity: sha512-pdkHLD8QYRp8VfiNLb8xIBJis1byQ9gPT3Jnh2jqfFtAsWUA3dEepDlsWe/xMpO8McV+VdpKVcp+E+TGJEtOoA==}
motion-utils@12.36.0:
resolution: {integrity: sha512-eHWisygbiwVvf6PZ1vhaHCLamvkSbPIeAYxWUuL3a2PD/TROgE7FvfHWTIH4vMl798QLfMw15nRqIaRDXTlYRg==}
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
@@ -3140,6 +3163,15 @@ snapshots:
dependencies:
is-callable: 1.2.7
framer-motion@12.38.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
dependencies:
motion-dom: 12.38.0
motion-utils: 12.36.0
tslib: 2.8.1
optionalDependencies:
react: 19.2.4
react-dom: 19.2.4(react@19.2.4)
function-bind@1.1.2: {}
function.prototype.name@1.1.8:
@@ -3506,6 +3538,12 @@ snapshots:
minimist@1.2.8: {}
motion-dom@12.38.0:
dependencies:
motion-utils: 12.36.0
motion-utils@12.36.0: {}
ms@2.1.3: {}
nanoid@3.3.11: {}