TLX DIGITAL//Motion System//v2.0
05

Motion

Animações que fazem seu site parecer vivo, não parado. Cada movimento guia o olho do visitante para onde importa. Aqui estão todas as regras.

01FILOSOFIA

5 princípios que guiam toda animação na TLX. Nada se mexe sem motivo. Cada transição existe para mostrar algo ou facilitar a navegação.

#PrincípioDescrição
01IntencionalToda animação tem propósito funcional ou comunicativo. Nenhum movimento é decorativo sem razão.
02RápidoFeedback imediato. Durações curtas (150-400ms) para manter a interface responsiva e profissional.
03SuaveCurvas de easing naturais. Sem movimentos lineares ou abruptos. Tudo flui organicamente.
04CoerenteMesmos tokens em toda plataforma. Uma curva, uma duração, um padrão. Consistência absoluta.
05AcessívelRespeita prefers-reduced-motion. Animações nunca são o único canal de informação.
02EASING CURVES

8 curvas de easing padronizadas (4 core + 4 Awwwards). Clique em cada card para ver a animação em ação.

03DURAÇÕES

3 níveis de duração. Clique para visualizar o tempo relativo de cada token.

04PADRÕES

Padrões de animação reutilizáveis. Composições das curvas e durações para cenários comuns.

fadeInUpEntrada

Elemento entra de baixo com fade. Easing spring premium extraido do CERNE Studio.

// fadeInUp (upgraded — CERNE spring)
initial: { opacity: 0, y: 32 }
animate: { opacity: 1, y: 0 }
transition: {
  duration: 0.8,
  ease: [0.16, 1, 0.3, 1]  // Spring
}
clipRevealEntrada

Texto aparece palavra por palavra, subindo de tras de um mask. Extraido do CERNE Studio.

// clipReveal — text reveal word-by-word
<span className="overflow-hidden pb-[0.15em]">
  <motion.span
    initial={{ y: "120%" }}
    animate={{ y: "0%" }}
    transition={{
      duration: 0.8,
      delay: index * 0.06,
      ease: [0.16, 1, 0.3, 1]  // Spring
    }}
  >
    {word}
  </motion.span>
</span>
staggerChildrenEntrada

Cards/items entram com delay escalonado. Delays extraidos do Koto (83ms, 133ms, 167ms).

// staggerChildren — Koto pattern
// CSS utility class:
.stagger-children > *:nth-child(1) { animation-delay: 0ms; }
.stagger-children > *:nth-child(2) { animation-delay: 83ms; }
.stagger-children > *:nth-child(3) { animation-delay: 133ms; }
.stagger-children > *:nth-child(4) { animation-delay: 167ms; }
.stagger-children > *:nth-child(5) { animation-delay: 200ms; }

// Framer Motion:
staggerContainer: {
  visible: { transition: { staggerChildren: 0.083 } }
}
drawLineDecorativo

Linha se desenha da esquerda para direita. Divider animado extraido do CERNE Studio.

// drawLine — CERNE pattern
@keyframes draw-line {
  from { transform-origin: left; transform: scaleX(0); }
  to { transform-origin: left; transform: scaleX(1); }
}

// Framer Motion:
initial: { scaleX: 0, transformOrigin: "left" }
animate: { scaleX: 1 }
transition: { duration: 1.2, ease: [0.16, 1, 0.3, 1] }
fadeOutDownSaída

Elemento sai para baixo com fade. Saida rapida extraida do Koto.

// fadeOutDown (upgraded — Koto exit)
animate: { opacity: 0, y: 16 }
transition: {
  duration: 0.25,
  ease: [0.7, 0, 1, 1]  // Quick exit
}
cardHoverInteração

Card escala suavemente no hover. Easing spring de 900ms extraido do CERNE Studio.

// cardHover — CERNE pattern
.card-hover {
  transition: transform 0.9s cubic-bezier(0.16, 1, 0.3, 1);
}
.card-hover:hover {
  transform: scale(1.03);
}
.card-hover:hover img {
  transform: scale(1.05);
}
underlineSlideInteração

Underline desliza da esquerda no hover, sai pela direita. Extraido do Koto.

// underlineSlide — Koto pattern
.link-underline {
  position: relative;
  overflow: hidden;
}
.link-underline::after {
  content: '';
  position: absolute;
  bottom: 0; left: 0;
  width: 100%; height: 1px;
  background: currentColor;
  transform: translateX(-100%);
  transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
.link-underline:hover::after {
  transform: translateX(0);
}
Scroll EntranceViewport

Elementos revelados ao entrar na viewport. Usa IntersectionObserver com once: true.

// Scroll Entrance (upgraded)
const ref = useRef(null);
const isInView = useInView(ref, {
  once: true,
  margin: "-10% 0px"
});

<motion.div
  ref={ref}
  initial={{ opacity: 0, y: 32 }}
  animate={isInView
    ? { opacity: 1, y: 0 }
    : { opacity: 0, y: 32 }
  }
  transition={{
    duration: 0.8,
    ease: [0.16, 1, 0.3, 1]  // Spring
  }}
/>
05ACESSIBILIDADE

Respeitar preferências do usuário. Toda animação deve ser desativável via prefers-reduced-motion.

/* CSS — Desativar animações para usuários que preferem */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Framer Motion — Hook */
import { useReducedMotion } from "framer-motion";

function Component() {
  const shouldReduce = useReducedMotion();

  return (
    <motion.div
      animate={{ opacity: 1, y: shouldReduce ? 0 : 16 }}
      transition={{
        duration: shouldReduce ? 0 : 0.4
      }}
    />
  );
}

Checklist

  • Animações decorativas desativadas com prefers-reduced-motion
  • Transições de estado mantidas (opacity ok, transform removido)
  • Nenhuma informação transmitida exclusivamente por animação
  • Durações nunca excedem 400ms para feedback de interação
06LOGO ANIMATIONS

8 animações oficiais do logo TLX. Cada uma projetada para um contexto de uso específico.

01

Structural Reveal

1.2s

Logo se constrói letra por letra, simulando o processo de construção da marca. Stroke path animation com fill progressivo.

Uso:Hero sections, landing pages
02

Teal Pulse

2.0s

Logo pulsa com glow teal suave em loop. Indica processamento ou carregamento ativo.

Uso:Loading states, splash screens
03

Data Stream

1.5s

Partículas de dados fluem através das letras do logo, representando o fluxo de informação e análise.

Uso:Dashboards, analytics contexts
04

Blueprint Grid

1.8s

Logo aparece sobre grid blueprint que fade out, referenciando o aspecto projetual e construtivo da marca.

Uso:Apresentações, pitch decks
05

Layer Reveal

1.0s

Camadas do logo se empilham de baixo para cima com stagger. Comunica profundidade e construção em camadas.

Uso:Transições de página, apps
06

Metric Counter

1.5s

Letras do logo se comportam como contadores numéricos antes de resolver na forma final. Conecta marca e métricas.

Uso:Relatórios, resultados
07

Stagger Letters

0.8s

Cada letra entra com stagger de 50ms usando curva Decelerate. Simples, elegante, rápido.

Uso:Navegação, headers
08

Convergence

1.2s

Letras convergem de posições dispersas para a posição final. Comunica unificação e resolução.

Uso:Fechamento, CTA sections
07TOKENS

Tokens YAML completos do motion system. Source of truth para todas as plataformas.

motion:
  easing:
    smooth: "cubic-bezier(0.4, 0, 0.2, 1)"       # Default
    decelerate: "cubic-bezier(0, 0, 0.2, 1)"      # Entrada
    accelerate: "cubic-bezier(0.4, 0, 1, 1)"      # Saida
    emphasis: "cubic-bezier(0.34, 1.56, 0.64, 1)" # Bounce
    spring: "cubic-bezier(0.16, 1, 0.3, 1)"       # Premium (CERNE)
    overshoot: "cubic-bezier(0.23, 1, 0.32, 1)"   # Buttons (Digital Present)
    in-decisive: "cubic-bezier(0, 0, 0, 1)"       # Entrada decisiva (Koto)
    out-quick: "cubic-bezier(0.7, 0, 1, 1)"       # Saida rapida (Koto)

  duration:
    fast: "150ms"
    normal: "300ms"
    slow: "500ms"
    reveal: "1000ms"    # Scroll reveals, text animations
    marquee: "30s"      # Infinite ticker

  patterns:
    fadeInUp:
      initial: { opacity: 0, y: 16 }
      animate: { opacity: 1, y: 0 }
      easing: decelerate
      duration: slow

    fadeOutDown:
      animate: { opacity: 0, y: 16 }
      easing: accelerate
      duration: normal

    stateChange:
      easing: smooth
      duration: fast

    scrollEntrance:
      initial: { opacity: 0, y: 16 }
      animate: { opacity: 1, y: 0 }
      easing: decelerate
      duration: slow
      trigger: viewport
      once: true

  logo:
    structural-reveal: { duration: "1.2s", loop: false }
    teal-pulse: { duration: "2.0s", loop: true }
    data-stream: { duration: "1.5s", loop: false }
    blueprint-grid: { duration: "1.8s", loop: false }
    layer-reveal: { duration: "1.0s", loop: false }
    metric-counter: { duration: "1.5s", loop: false }
    stagger-letters: { duration: "0.8s", loop: false }
    convergence: { duration: "1.2s", loop: false }

  a11y:
    reduced-motion: "remove transform, keep opacity"
    max-feedback-duration: "400ms"
    no-animation-only-info: true
08IMPLEMENTAÇÃO

Referência de implementação com Framer Motion. Padrões prontos para copiar e usar.

Framer Motion: Variantes base

import { motion, type Variants } from "framer-motion";

const fadeInUp: Variants = {
  hidden: { opacity: 0, y: 16 },
  visible: {
    opacity: 1,
    y: 0,
    transition: {
      duration: 0.4,
      ease: [0, 0, 0.2, 1], // Decelerate
    },
  },
};

<motion.div
  variants={fadeInUp}
  initial="hidden"
  animate="visible"
>
  {children}
</motion.div>

Framer Motion: Stagger children

const staggerContainer: Variants = {
  hidden: { opacity: 0 },
  visible: {
    opacity: 1,
    transition: {
      staggerChildren: 0.05,
      delayChildren: 0.1,
    },
  },
};

const staggerItem: Variants = {
  hidden: { opacity: 0, y: 12 },
  visible: {
    opacity: 1,
    y: 0,
    transition: {
      duration: 0.4,
      ease: [0, 0, 0.2, 1],
    },
  },
};

<motion.ul variants={staggerContainer} initial="hidden" animate="visible">
  {items.map((item) => (
    <motion.li key={item.id} variants={staggerItem}>
      {item.content}
    </motion.li>
  ))}
</motion.ul>

CSS Custom Properties

:root {
  /* Easing — base */
  --ease-smooth: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-decel: cubic-bezier(0, 0, 0.2, 1);
  --ease-accel: cubic-bezier(0.4, 0, 1, 1);
  --ease-emphasis: cubic-bezier(0.34, 1.56, 0.64, 1);

  /* Easing — Awwwards premium */
  --ease-spring: cubic-bezier(0.16, 1, 0.3, 1);     /* CERNE */
  --ease-overshoot: cubic-bezier(0.23, 1, 0.32, 1); /* Digital Present */
  --ease-in-decisive: cubic-bezier(0, 0, 0, 1);     /* Koto */
  --ease-out-quick: cubic-bezier(0.7, 0, 1, 1);     /* Koto */

  /* Duration */
  --duration-fast: 150ms;
  --duration-normal: 300ms;
  --duration-slow: 500ms;
  --duration-reveal: 1000ms;

  /* Blur */
  --blur-glass: 16px;
  --blur-decorative: 50px;
}

/* Uso premium */
.card-hover {
  transition: transform 0.9s var(--ease-spring);
}
.card-hover:hover { transform: scale(1.03); }

Tailwind: Classes utilitárias

/* tailwind.config.js */
theme: {
  extend: {
    transitionTimingFunction: {
      smooth: "cubic-bezier(0.4, 0, 0.2, 1)",
      decelerate: "cubic-bezier(0, 0, 0.2, 1)",
      accelerate: "cubic-bezier(0.4, 0, 1, 1)",
      emphasis: "cubic-bezier(0.34, 1.56, 0.64, 1)",
    },
    transitionDuration: {
      fast: "150ms",
      normal: "250ms",
      slow: "400ms",
    },
  },
}

/* Uso no JSX */
<button className="transition-all duration-fast ease-smooth">
  Hover me
</button>