WisarWisar
Dasturlash kitobi/11-QISM — React45 daqiqa

11.16-bob: Swiper va animatsiya (Framer Motion)

11-QISM — Frontend: React · 16-mavzu


1. Kirish va motivatsiya

11.15-bobda to'liq, funksional dashboard qurdik. U ishlaydi, lekin biroz "jonsiz" — elementlar darrov paydo bo'ladi va yo'qoladi, o'tishlar keskin, hech narsa "his qilinmaydi". Endi ilovamizni jonli va chiroyli qilamiz. Animatsiya — bu shunchaki bezak emas: u UX'ning "his qilinadigan sifati" (perceived quality). To'g'ri ishlatilgan animatsiya foydalanuvchiga fikr yuritishga yordam beradi (element qayerdan keldi, qayerga ketdi), holatni bildiradi (yuklanmoqda, muvaffaqiyatli), va ilovani professional, silliq, zamonaviy qiladi. Noto'g'ri (yoki ortiqcha) animatsiya esa — chalg'itadi va sekinlashtiradi. Bu bobda aynan to'g'ri animatsiyani o'rganamiz.

Ikkita kuchli vositani ko'ramiz. Swiper — zamonaviy, teginishga sezgir (touch) slayder/karusel kutubxonasi: mahsulot galereyasi, banner, onboarding ekranlari, rasm karuseli — bularning hammasi uchun standart yechim (mobil va desktop'da mukammal ishlaydi). Framer Motion (endi rasman "Motion" deb ataladi) — React uchun eng kuchli va eng keng ishlatiladigan animatsiya kutubxonasi: kirish/chiqish animatsiyalari, gesture'lar (hover, tap, drag), layout animatsiya, scroll'ga bog'liq effektlar, va micro-interaksiyalar — barchasini deklarativ (React falsafasiga mos) tarzda yozasiz. Bu ikkisi — zamonaviy, jonli React ilovasini qurishning asosiy vositalari.

Bu bob: nega animatsiya (UX, his qilinadigan sifat), animatsiya printsiplari (CSS vs JS, performance — qaysi xususiyatlar), Swiper (setup, modullar — Navigation/Pagination/Autoplay, responsive breakpoints), Framer Motion (motion komponentlar, animate/initial/transition, variants — orkestrlash, gesture'lar — hover/tap/drag, AnimatePresence — chiqish animatsiyasi, layout animatsiya, scroll animatsiya — whileInView), va performance va a11y (prefers-reduced-motion — animatsiyadan charchaydiganlar uchun). Bu mavzuni to'liq va amaliy holatda ochamiz.

O'xshatish: Animatsiya — bu suhbatda tana tili va ohang. Statik UI (animatsiyasiz) — bu robot kabi tekis ovoz bilan gapirish: ma'lumot yetkaziladi, lekin "jonsiz". Animatsiya — bu tabassum, qo'l harakati, ovoz ohangi: u bir xil ma'lumotni ancha tabiiy va yoqimli qiladi. Modal "paydo bo'ldi" emas, "silliq kirib keldi" (qayerdan kelganini ko'rasiz); element "yo'qoldi" emas, "chiqib ketdi" (qayerga ketganini tushunasiz). Swiper — bu fotoalbom varaqlash: barmoq bilan surib, sahifalar silliq almashadi (teginishga tabiiy javob). Framer Motion — bu rejissyor: u har "aktyor" (element) qachon, qaydan, qanday kirishini va chiqishini boshqaradi. Lekin yaxshi rejissyor biladi — ortiqcha effekt tomoshani buzadi (animatsiya maqsadli bo'lsin, ko'rsatish uchun emas).

Nega muhim?

  • His qilinadigan sifat — animatsiya ilovani "arzon"dan "professional"ga aylantiradi (foydalanuvchi sezadi).
  • UX yordami — to'g'ri animatsiya holatni (yuklanish, o'tish) va aloqani (qayerdan/qayerga) bildiradi.
  • Har real ilovada — slayder (Swiper), o'tishlar, micro-interaksiyalar — zamonaviy ilovada kutiladi.
  • Ajralib turish — silliq, jonli UI — portfolio va mahsulotni raqobatdan ajratadi.

2. Nazariya — chuqur tushuntirish

2.1. Nega animatsiya va animatsiya printsiplari

text
  ANIMATSIYA — UX'ning "his qilinadigan sifati" (perceived quality):

  ANIMATSIYA NIMA BERADI (maqsadli):
   Aloqa (continuity) — element qayerdan keldi/qayerga ketdi (modal, ro'yxat)
   Holat (feedback) — yuklanmoqda, muvaffaqiyatli, xato (foydalanuvchi tushunadi)
   E'tibor (attention) — muhim narsaga qaratadi (yangi xabar, tugma)
   Sifat (polish) — silliq, professional, zamonaviy his

  YAXSHI ANIMATSIYA PRINTSIPLARI:
   TEZ — 200-400ms (sekin animatsiya bezovta qiladi — foydalanuvchi kutadi)
   MAQSADLI — ma'no beradi (ko'rsatish uchun emas — ortiqcha = chalg'itadi)
   TABIIY — ease (tezlanish/sekinlanish — chiziqli emas, hayotiy)
   IZCHIL — bir xil harakat bir xil ma'no (butun ilovada)

   Animatsiya — MAQSADLI (UX yordami), bezak emas (ortiqcha = sekin + chalg'ituvchi)
   Tez (200-400ms) + tabiiy (ease) + izchil — yaxshi animatsiya qoidalari

Nega animatsiya va printsiplari — animatsiyani to'g'ri tushunishning asosi. Animatsiya — UX'ning "his qilinadigan sifati" (perceived quality): u maqsadli ishlatilganda foydani beradi: (1) aloqa (continuity — element qayerdan keldi/qayerga ketdi — modal yuqoridan tushdi, o'chirilgan element o'ngga surildi); (2) holat (feedback — yuklanmoqda, muvaffaqiyatli, xato — foydalanuvchi nima bo'layotganini tushunadi); (3) e'tibor (muhim narsaga qaratadi — yangi xabar, asosiy tugma); (4) sifat (silliq, professional his). Yaxshi animatsiya printsiplari: tez (200-400ms — sekin animatsiya foydalanuvchini kuttiradi, bezovta qiladi); maqsadli (ma'no beradi — ko'rsatish uchun emas; ortiqcha animatsiya chalg'itadi); tabiiy (ease — tezlanish/sekinlanish, chiziqli linear emas, hayotiy harakat); izchil (bir xil harakat butun ilovada bir xil ma'no). Ikki tamoyil: (1) animatsiya — maqsadli (UX yordami), bezak emas (ortiqcha animatsiya sekinlashtiradi va chalg'itadi — kamroq ko'pincha yaxshiroq); (2) tez + tabiiy + izchil — yaxshi animatsiyaning uch qoidasi. Bu — animatsiyani "professional" va "havaskor" qiladigan farq.

2.2. CSS vs JS animatsiya va performance

text
  IKKI XIL ANIMATSIYA:
  1. CSS animatsiya (transition, @keyframes) — oddiy, tez (brauzer optimallashtiradi):
     .btn { transition: transform 0.2s; }  .btn:hover { transform: scale(1.05); }
  2. JS animatsiya (Framer Motion) — murakkab, boshqariladigan (gesture, orkestr, exit):
     <motion.div animate={{ x: 100 }} />

  PERFORMANCE — QAYSI xususiyatlar arzon (60 FPS uchun):
   ARZON (GPU — reflow yo'q): transform (translate/scale/rotate), opacity
   QIMMAT (reflow/repaint — 11.1: 2.7): width, height, top, left, margin

   transform: translateX(100px)   (GPU — silliq)
   left: 100px                     (reflow — har kadrda — lag)

  QAYSI QACHON:
  - Oddiy (hover, transition)  CSS (yengil, tez)
  - Murakkab (gesture, exit, orkestr, layout)  Framer Motion (kuchli)

   transform/opacity bilan animatsiyala (GPU — 60 FPS); width/left'dan qoch (reflow — 11.1)
   CSS — oddiy holatda; Framer Motion — murakkab, boshqariladigan animatsiya

CSS vs JS animatsiya va performance — animatsiyani silliq (60 FPS) qilishning kaliti. Ikki xil animatsiya: CSS (transition, @keyframes — oddiy, brauzer avtomatik optimallashtiradi — hover, oddiy o'tishlar uchun) va JS (Framer Motion — murakkab, boshqariladigan — gesture, orkestr, exit animatsiya uchun). Performance — eng muhim qoida: faqat arzon xususiyatlarni animatsiyala. Arzon (GPU'da ishlaydi, reflow yo'q): transform (translate, scale, rotate) va opacity — bular kompozitsiya bosqichida (11.1: 2.1) ishlaydi, layoutni qayta hisoblamaydi. Qimmat (reflow/repaint — 11.1: 2.7): width, height, top, left, margin — bular har kadrda layoutni qayta hisoblab, lag (kechikish) keltiradi. Masalan, element surish: transform: translateX(100px) (GPU — silliq) o'rniga left: 100px (reflow — har kadrda). Ikki nuqta: (1) transform/opacity bilan animatsiya qiling (GPU — 60 FPS silliq); width/left/top'dan qoching (reflow — sakraydi); (2) qaysi vositani tanlash — oddiy (hover, oddiy o'tish) CSS (yengil); murakkab (gesture, exit, orkestr) Framer Motion. Bu — silliq, professional animatsiyaning texnik poydevori.

2.3. Swiper — setup va asoslari

text
  SWIPER — teginishga sezgir slayder/karusel (mobil + desktop):
  npm install swiper

  ASOSIY ISHLATISH (React):
  import { Swiper, SwiperSlide } from "swiper/react";
  import "swiper/css";                          // asosiy stillar (majburiy)

  <Swiper spaceBetween={20} slidesPerView={1}>  {/* slaydlar orasi, bir vaqtda nechta */}
    <SwiperSlide><img src="1.jpg" /></SwiperSlide>
    <SwiperSlide><img src="2.jpg" /></SwiperSlide>
    <SwiperSlide><img src="3.jpg" /></SwiperSlide>
  </Swiper>

  ASOSIY PROPS:
  slidesPerView — bir vaqtda nechta slayd (1, 3, "auto")
  spaceBetween — slaydlar orasi (px)
  loop — cheksiz aylanish (oxiridan boshiga)
  centeredSlides — markaziy slaydni o'rtaga

   Swiper — teginish (touch), sichqoncha, klaviatura — hammasi bilan ishlaydi (mobil + desktop)
   "swiper/css" — asosiy stillarni import qilish SHART (aks holda slayder buziladi)

Swiper — teginishga sezgir slayder/karusel kutubxonasi (npm install swiper). Asosiy ishlatish React'da: import { Swiper, SwiperSlide } from "swiper/react" va import "swiper/css" (asosiy stillar — majburiy), keyin <Swiper> ichida <SwiperSlide>lar. Asosiy props: slidesPerView (bir vaqtda nechta slayd ko'rinadi — 1, 3, yoki "auto"), spaceBetween (slaydlar orasidagi masofa — px), loop (cheksiz aylanish — oxiridan boshiga qaytadi), centeredSlides (markaziy slaydni o'rtaga joylashtiradi). Swiper teginish (touch — barmoq bilan surish), sichqoncha (drag), klaviatura — barchasi bilan ishlaydi (mobil va desktop'da mukammal). Ikki nuqta: (1) Swiper — har xil kirish usuli (teginish, sichqoncha, klaviatura) bilan ishlaydi (mobil-first, lekin desktop'da ham); (2) swiper/css import qilish shart — usiz slayder stillarsiz (buzilgan) ko'rinadi. Swiper — mahsulot galereyasi, banner, onboarding, rasm karuseli kabi har "suriladigan" UI uchun standart yechim (o'zi yozishdan ko'ra ancha ishonchli — touch fizikasi, momentum, edge case'lar hisobga olingan).

2.4. Swiper modullar — Navigation, Pagination, Autoplay

text
  SWIPER MODULLAR — qo'shimcha imkoniyatlar (alohida import — faqat keraklisi):

  import { Navigation, Pagination, Autoplay } from "swiper/modules";
  import "swiper/css/navigation";    import "swiper/css/pagination";

  <Swiper
    modules={[Navigation, Pagination, Autoplay]}   //  ishlatiladigan modullar
    navigation                                      // o'ng/chap o'qlar (tugmalar)
    pagination={{ clickable: true }}                // pastdagi nuqtalar (bosiladigan)
    autoplay={{ delay: 3000 }}                       // 3s'da avtomatik almashish
  >
    {slides.map(s => <SwiperSlide key={s.id}>{s.content}</SwiperSlide>)}
  </Swiper>

  KENG MODULLAR:
  Navigation — o'q tugmalar (oldingi/keyingi)
  Pagination — nuqtalar/progress (joriy holat)
  Autoplay — avtomatik almashish
  Scrollbar, Thumbs (kichik rasmlar), EffectFade/Coverflow (effektlar)

   Modullar alohida import (faqat keraklisi — bundle kichik — 11.8)
   modules={[...]} ga qo'shish + mos CSS import (navigation/pagination)

Swiper modullar — qo'shimcha imkoniyatlar (alohida import — faqat keraklisi yuklanadi). Asosiy modullar: Navigation (o'ng/chap o'q tugmalari — oldingi/keyingi slaydga), Pagination (pastdagi nuqtalar yoki progress — joriy holatni ko'rsatadi, clickable: true bilan bosiladigan), Autoplay (avtomatik almashish — delay: 3000 ms). Ishlatish: modullarni import { Navigation, ... } from "swiper/modules", ularning CSS'ini (swiper/css/navigation), va <Swiper modules={[Navigation, Pagination, Autoplay]} navigation pagination autoplay={{...}}>. Keng modullar: Scrollbar (skroll chizig'i), Thumbs (kichik rasm preview'lari — galereyada), EffectFade/EffectCoverflow (maxsus o'tish effektlari). Ikki nuqta: (1) modullar alohida import qilinadi (faqat keraklisi — bundle kichik qoladi — 11.8 code splitting tamoyili); (2) har modulni modules={[...]} massiviga qo'shish va mos CSS'ini import qilish kerak (aks holda modul stillarsiz). Bu modulli yondashuv — Swiper'ni yengil va moslashuvchan qiladi (faqat kerakli imkoniyatlar yuklanadi).

2.5. Swiper responsive — breakpoints

text
  RESPONSIVE — ekran o'lchamiga qarab turli sozlama (mobilda 1, desktop'da 3 slayd):

  <Swiper
    slidesPerView={1}                  // default (eng kichik ekran)
    spaceBetween={10}
    breakpoints={{
      640: { slidesPerView: 2, spaceBetween: 20 },    // ≥640px — 2 slayd
      1024: { slidesPerView: 3, spaceBetween: 30 },   // ≥1024px — 3 slayd
      1280: { slidesPerView: 4, spaceBetween: 40 },   // ≥1280px — 4 slayd
    }}
  >
    {products.map(p => <SwiperSlide key={p.id}><ProductCard product={p} /></SwiperSlide>)}
  </Swiper>

  ┌────────────────────────────────────────────────────────────┐
  │ Mobil (<640): 1 slayd | Tablet (640+): 2 | Desktop (1024+): 3│
  │  bir Swiper, ekran o'lchamiga moslashadi (responsive — 1.5)│
  └────────────────────────────────────────────────────────────┘

   breakpoints — ekran kengligiga qarab sozlama (mobil-first — kichikdan kattaga)
   Mahsulot karuseli — mobilda 1, desktop'da 3-4 (responsive — 1.5)

Swiper responsive (breakpoints) — slayderni ekran o'lchamiga moslash. breakpoints prop — turli ekran kengliklarida turli sozlama beradi: breakpoints={{ 640: { slidesPerView: 2 }, 1024: { slidesPerView: 3 } }} — har kalit (640, 1024) minimal piksel kenglik (mobil-first — kichikdan kattaga), va undan boshlab o'sha sozlama qo'llanadi. Masalan: default (eng kichik ekran) 1 slayd; ≥640px — 2 slayd; ≥1024px — 3 slayd; ≥1280px — 4 slayd. Bu mahsulot karuseli uchun klassik — mobilda bitta katta karta, desktop'da bir nechta yonma-yon. Ikki nuqta: (1) breakpoints — ekran kengligiga qarab slidesPerView/spaceBetween va boshqa sozlamalarni o'zgartiradi (mobil-first yondashuv — 1.5 responsive bilan bir xil falsafa); (2) bu CSS media query'larga o'xshaydi, lekin Swiper sozlamasi darajasida (slaydlar soni va joylashuvi). Responsive Swiper — har qurilmada (telefon, planshet, kompyuter) mukammal ko'rinadigan slayder yaratishning standart usuli.

2.6. Framer Motion — motion komponentlar

text
  FRAMER MOTION (Motion) — React animatsiya kutubxonasi (deklarativ):
  npm install motion

  motion KOMPONENTLAR — oddiy element + animatsiya imkoniyati:
  import { motion } from "motion/react";

  <motion.div animate={{ x: 100 }} />        // div, lekin animatsiyalanadi
  <motion.button whileHover={{ scale: 1.1 }} />
  <motion.h1 initial={{ opacity: 0 }} animate={{ opacity: 1 }} />

  HAR HTML ELEMENT motion versiyasi:
  motion.div, motion.button, motion.li, motion.span, motion.svg...

  3 ASOSIY PROP:
  initial — boshlang'ich holat (animatsiyadan OLDIN)
  animate — yakuniy holat (animatsiya BORADIGAN joy)
  transition — qanday (davomiylik, ease, turi)

   motion.X — oddiy X element + animatsiya props (initial/animate/transition/while*)
   Deklarativ — "boshlang'ich  yakuniy holat"ni tasvirlaysan (React falsafasiga mos)

Framer Motion (motion komponentlar) — React uchun deklarativ animatsiya kutubxonasi (npm install motion — endi rasman "Motion" deb ataladi). Asosiy g'oya — motion komponentlar: har HTML element'ning "motion versiyasi" bor (motion.div, motion.button, motion.li, motion.span, motion.svg...) — bular oddiy element kabi ishlaydi, lekin animatsiya imkoniyatini qo'shadi. Uch asosiy prop: initial (boshlang'ich holat — animatsiyadan oldin), animate (yakuniy holat — animatsiya boradigan joy), transition (qanday — davomiylik, ease, turi). Misol: <motion.h1 initial={{ opacity: 0 }} animate={{ opacity: 1 }} /> — h1 ko'rinmas (opacity 0)dan to'liq ko'rinadiganga (opacity 1) silliq paydo bo'ladi. <motion.button whileHover={{ scale: 1.1 }} /> — hover'da kattalashadi. Ikki nuqta: (1) motion.X — oddiy X element + animatsiya props (initial/animate/transition/while*); (2) deklarativ — siz "boshlang'ich yakuniy holat"ni tasvirlaysiz (qadamma-qadam animatsiya yozmasdan — React'ning UI = f(state) falsafasiga mos). Framer Motion'ning go'zalligi — animatsiya React komponent darajasida, deklarativ va o'qish oson.

2.7. animate, initial, transition — asosiy animatsiya

text
  3 PROP bilan animatsiya (boshlang'ich  yakuniy, qanday):

  <motion.div
    initial={{ opacity: 0, y: 20 }}      // boshlang'ich: ko'rinmas + 20px pastda
    animate={{ opacity: 1, y: 0 }}       // yakuniy: to'liq ko'rinadigan + joyida
    transition={{ duration: 0.4, ease: "easeOut" }}   // 0.4s, sekinlanish bilan
  />
  //  element pastdan silliq ko'tarilib paydo bo'ladi (fade + slide up)

  ANIMATSIYALANADIGAN xususiyatlar:
  x, y — joylashuv (transform — GPU — 2.2)
  opacity — shaffoflik    scale — o'lcham    rotate — burilish
  backgroundColor, borderRadius — rang/shakl

  TRANSITION:
  duration — davomiylik (s)    ease — "easeOut"/"easeInOut"/"linear"
  type: "spring" — prujinali (tabiiy, bouncy)    delay — kechikish

   x/y/scale/opacity — GPU (silliq — 2.2); duration 0.2-0.4s (tez — 2.1)
   type: "spring" — tabiiy, hayotiy harakat (chiziqli duration'dan jonliroq)

animate, initial, transition — asosiy animatsiya naqshi. initial (boshlang'ich holat), animate (yakuniy holat), transition (qanday) — bu uchchovi birga eng keng ishlatiladigan "kirish animatsiyasi"ni beradi: <motion.div initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.4, ease: "easeOut" }} /> — element ko'rinmas va 20px pastda boshlaydi, to'liq ko'rinadigan va joyiga silliq ko'tariladi (fade-in + slide-up — eng mashhur effekt). Animatsiyalanadigan xususiyatlar: x/y (joylashuv — transform, GPU — 2.2), opacity, scale, rotate, backgroundColor, borderRadius. Transition sozlamalari: duration (davomiylik — s), ease ("easeOut"/"easeInOut"/"linear"), type: "spring" (prujinali — tabiiy, biroz "bouncy" harakat), delay (kechikish). Ikki nuqta: (1) x/y/scale/opacity bilan animatsiya qiling (GPU — silliq — 2.2), va duration ni 0.2-0.4s tuting (tez — 2.1); (2) type: "spring" — chiziqli duration'dan ko'ra tabiiyroq, hayotiy harakat beradi (fizik prujina modeli — Framer Motion'ning kuchli tomon). Bu — har kirish/o'zgarish animatsiyasining asosi.

2.8. variants — animatsiyani orkestrlash

text
  VARIANTS — animatsiya holatlarini NOM bilan belgilash (orkestr — ko'p element birga):

  const container = {
    hidden: { opacity: 0 },
    visible: {
      opacity: 1,
      transition: { staggerChildren: 0.1 },   //  bolalar 0.1s farq bilan (ketma-ket)
    },
  };
  const item = {
    hidden: { opacity: 0, y: 20 },
    visible: { opacity: 1, y: 0 },
  };

  <motion.ul variants={container} initial="hidden" animate="visible">   {/* nom bilan */}
    {items.map(i => (
      <motion.li key={i.id} variants={item}>{i.name}</motion.li>        {/* ota'dan meros */}
    ))}
  </motion.ul>
  //  ro'yxat elementlari KETMA-KET (stagger) paydo bo'ladi (chiroyli, professional)

  ┌────────────────────────────────────────────────────────────┐
  │ Variants: holatlar nom bilan (hidden/visible) — qayta ishlat-│
  │ iladigan; staggerChildren — bolalar ketma-ket (orkestr)      │
  └────────────────────────────────────────────────────────────┘

   Variants — animatsiya holatlarini nom bilan (toza, qayta ishlatiladigan)
   staggerChildren — bolalar ketma-ket animatsiya (ro'yxat paydo bo'lishi — professional)

variants — animatsiya holatlarini nom bilan belgilash va orkestrlash (ko'p elementni birga boshqarish). Variants — obyekt, ichida nomli holatlar (hidden, visible): const container = { hidden: { opacity: 0 }, visible: { opacity: 1, transition: { staggerChildren: 0.1 } } }. Komponentda variants={container} initial="hidden" animate="visible" — holat nomini ko'rsatasiz (qiymatni emas). Eng kuchli imkoniyati — staggerChildren: ota komponentning bolalari ketma-ket (har biri 0.1s farq bilan) animatsiya qiladi — ro'yxat yoki karta to'plami birin-ketin silliq paydo bo'ladi (professional effekt). Bolalar variants={item} bilan ota'ning holat nomini meros oladi (hidden/visibleni qaytarmasdan). Ikki nuqta: (1) variants — animatsiya holatlarini nom bilan belgilaydi (toza, qayta ishlatiladigan — bir variants ko'p elementga), va ota-bola orqali orkestrlashni soddalashtiradi; (2) staggerChildren — ro'yxat/grid elementlarini ketma-ket animatsiya qiladi (bir vaqtda hammasi emas — bu yanada professional va o'qish oson). Variants — murakkab, koordinatsiyalangan animatsiyalarning standart usuli.

2.9. Gestures — hover, tap, drag

text
  GESTURES — foydalanuvchi harakatiga animatsiya (hover, bosish, sudrash):

  HOVER va TAP (micro-interaksiyalar — tugma, karta):
  <motion.button
    whileHover={{ scale: 1.05 }}        // hover — biroz kattalash
    whileTap={{ scale: 0.95 }}          // bosganda — biroz kichrash (bosildi his)
  >Bosish</motion.button>

  DRAG (sudrash — kartani surish, slider, swipe):
  <motion.div
    drag                                 // sudraladigan
    dragConstraints={{ left: 0, right: 300 }}   // chegara (qancha suriladi)
    dragElastic={0.2}                    // chegaradan tashqari cho'zilish (elastik)
  />

  // drag bilan "swipe to delete", draggable karta, slider — qo'lda quriladi

  ┌────────────────────────────────────────────────────────────┐
  │ whileHover/whileTap: micro-interaksiya (tugma jonliroq)     │
  │ drag: sudraladigan (swipe, draggable, slider)               │
  └────────────────────────────────────────────────────────────┘

   whileHover/whileTap — tugma/kartaga "jonli" his (bosildi/ustida — UX)
   drag — sudraladigan element (swipe-to-delete, draggable, custom slider)

Gestures — foydalanuvchi harakatiga (hover, bosish, sudrash) animatsiya. whileHover va whileTap — micro-interaksiyalar (eng keng): <motion.button whileHover={{ scale: 1.05 }} whileTap={{ scale: 0.95 }}> — sichqoncha ustiga kelganda tugma biroz kattalashadi (interaktiv ekanini bildiradi), bosganda biroz kichrayadi ("bosildi" his — tactile feedback). Bu — har tugma/karta/interaktiv elementni "jonli" qiladi (kichik, lekin sezilarli UX yaxshilanishi). drag — elementni sudraladigan qiladi: <motion.div drag dragConstraints={{ left: 0, right: 300 }} dragElastic={0.2} />dragConstraints (qancha surilishi mumkin — chegara), dragElastic (chegaradan tashqari biroz cho'zilish — elastik his). Drag bilan "swipe-to-delete" (chap/o'ngga surib o'chirish), draggable kartalar (kanban taxtasi), custom slider quriladi. Ikki nuqta: (1) whileHover/whileTap — har interaktiv elementga "jonli" his beradi (tugma, karta — UX); (2) drag — sudraladigan elementlar (swipe, draggable, custom slider). Gesture'lar — ilovani "his qilinadigan", interaktiv qiladi (foydalanuvchi harakatiga darrov javob).

2.10. AnimatePresence — chiqish animatsiyasi

text
  MUAMMO: React komponent O'CHGANDA (DOM'dan olinganda) — animatsiya qila olmaydi (darrov yo'qoladi)

  AnimatePresence — komponent CHIQISHIHI (exit) animatsiya qiladi:
  import { AnimatePresence, motion } from "motion/react";

  <AnimatePresence>
    {isOpen && (
      <motion.div
        initial={{ opacity: 0 }}        // kirish
        animate={{ opacity: 1 }}
        exit={{ opacity: 0, scale: 0.9 }}   //  CHIQISH (o'chganda — AnimatePresence kutadi)
      >
        Modal kontenti
      </motion.div>
    )}
  </AnimatePresence>
  //  modal silliq KIRADI (isOpen true) va silliq CHIQADI (isOpen false — darrov yo'qolmaydi)

  RO'YXAT elementi o'chishi (exit bilan):
  <AnimatePresence>
    {items.map(i => <motion.li key={i.id} exit={{ opacity: 0, x: -100 }}>...)}
  </AnimatePresence>

   AnimatePresence — exit animatsiyasini imkon beradi (komponent o'chganda — darrov emas)
   exit prop — chiqish holati (modal yopilish, ro'yxat elementi o'chish — silliq)

AnimatePresence — komponentning chiqish (exit) animatsiyasini imkon beradi. Muammo: React komponent o'chganda (DOM'dan olinganda — {isOpen && <Modal/>} da isOpen false bo'lganda) u darrov yo'qoladi — animatsiya qila olmaydi (chunki komponent allaqachon yo'q). AnimatePresence buni hal qiladi: u komponentni o'chirishdan oldin uning exit animatsiyasini kutadi (komponentni vaqtincha DOM'da ushlab turadi, animatsiya tugagach o'chiradi). Naqsh: <AnimatePresence>{isOpen && <motion.div initial={...} animate={...} exit={{ opacity: 0, scale: 0.9 }}>...</motion.div>}</AnimatePresence> — modal silliq kiradi (isOpen true) va silliq chiqadi (isOpen false — darrov yo'qolmaydi, balki exit holatiga animatsiya qiladi). Ro'yxat elementlari uchun ham (exit={{ opacity: 0, x: -100 }} — o'chirilgan element chapga surilib yo'qoladi). Ikki nuqta: (1) AnimatePresence — exit animatsiyasini imkon beradi (komponent o'chganda darrov emas, silliq); (2) exit prop — chiqish holati (modal yopilish, toast yo'qolish, ro'yxat elementi o'chish — barchasi silliq). Bu — modal, dropdown, toast, dinamik ro'yxatlar uchun zarur (kirish va chiqish ikkalasi silliq — to'liq professional his).

2.11. Layout va scroll animatsiya

text
  LAYOUT ANIMATSIYA — element JOYI/O'LCHAMI o'zgarganda avtomatik silliq (layout prop):
  <motion.div layout />   //  joy/o'lcham o'zgarsa — avtomatik animatsiya (qo'lda hisob yo'q)
  // masalan: ro'yxat tartiblansa, akkordeon ochilsa, grid o'zgarsa — silliq ko'chadi

  SCROLL ANIMATSIYA — element ko'ringanda animatsiya (whileInView):
  <motion.div
    initial={{ opacity: 0, y: 50 }}
    whileInView={{ opacity: 1, y: 0 }}    // ekranga KIRGAHda animatsiya (scroll)
    viewport={{ once: true }}              // faqat BIR marta (qayta scroll'da emas)
    transition={{ duration: 0.5 }}
  />
  //  sahifa scroll qilinganda, element ko'ringan sayin paydo bo'ladi (landing page)

  useScroll (ilg'or) — scroll holatiga bog'liq animatsiya (progress bar, parallax):
  const { scrollYProgress } = useScroll();   // 0  1 (scroll progress)

   layout prop — joy/o'lcham o'zgarishini avtomatik animatsiya (qo'lda hisob yo'q — kuchli)
   whileInView — element ko'ringanda (scroll-triggered — landing page, "reveal on scroll")

Layout va scroll animatsiya — ikki kuchli, keng ishlatiladigan imkoniyat. Layout animatsiya (layout prop): <motion.div layout /> — element joyi yoki o'lchami o'zgarganda (ro'yxat tartiblansa, akkordeon ochilsa, grid o'zgarsa, element qo'shilsa/o'chsa) — Framer Motion uni avtomatik silliq ko'chiradi (qo'lda koordinata hisoblamasdan — bu juda kuchli, chunki layout o'zgarishlarni animatsiyalash odatda qiyin — 11.1: 2.7). Scroll animatsiya (whileInView): <motion.div initial={{ opacity: 0, y: 50 }} whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true }} /> — element ekranga kirganda (scroll bilan ko'ringanda) animatsiya qiladi; viewport={{ once: true }} — faqat bir marta (qayta scroll'da takrorlamaydi). Bu — landing page'larda "reveal on scroll" (scroll qilingan sayin kontent paydo bo'lishi) effekti. useScroll (ilg'or) — scroll holatiga bog'liq animatsiya (progress bar — yuqorida o'qish progressi, parallax effektlar). Ikki nuqta: (1) layout prop — joy/o'lcham o'zgarishini avtomatik animatsiya (Framer Motion'ning eng kuchli imkoniyatlaridan biri); (2) whileInView — element ko'ringanda (scroll-triggered — landing page, marketing sahifalar). Bular — zamonaviy, jonli sahifalarning asosiy effektlari.

2.12. Performance va a11y — reduced motion

text
  PERFORMANCE:
   transform/opacity (GPU — 2.2); width/left'dan qoch (reflow)
   Ko'p element — layout prop yoki LazyMotion (bundle kichik)
   Animatsiya 60 FPS bo'lsin (Profiler/DevTools'da tekshir — 11.11)

  A11Y — REDUCED MOTION (animatsiyadan charchaydigan/kasallanadigan foydalanuvchilar):
  // Ba'zi foydalanuvchilar OS'da "harakatni kamaytir" yoqadi (vestibulyar buzilish)
  import { useReducedMotion } from "motion/react";
  const shouldReduceMotion = useReducedMotion();   // true bo'lsa — animatsiyani kamaytir
  <motion.div animate={{ x: shouldReduceMotion ? 0 : 100 }} />

  // yoki CSS: @media (prefers-reduced-motion: reduce) { * { animation: none; } }

  ┌────────────────────────────────────────────────────────────┐
  │ Performance: transform/opacity (GPU) | A11y: reduced motion │
  │ (animatsiyadan charchaydiganlarga — hurmat, qonuniy talab)  │
  └────────────────────────────────────────────────────────────┘

   prefers-reduced-motion — animatsiya hammaga mos kelmaydi (vestibulyar — bosh aylanish)
   useReducedMotion (Framer) yoki CSS media query — a11y (1.9 — har kim uchun)

Performance va a11y — animatsiyaning sifatli yakuni. Performance: transform/opacity bilan animatsiya qiling (GPU — 2.2), width/left'dan qoching (reflow); ko'p element bo'lsa layout prop yoki LazyMotion (Framer'ning bundle'ni kichraytiruvchi import usuli — 11.8); animatsiya 60 FPS bo'lishini DevTools Profiler bilan tekshiring 11.11-bob. A11y — reduced motion (juda muhim, lekin ko'p unutiladi): ba'zi foydalanuvchilar animatsiyadan jismonan azob chekadi (vestibulyar buzilishlar — bosh aylanish, ko'ngil aynishi), shuning uchun ular OS sozlamasida "harakatni kamaytir" (reduce motion)ni yoqadi. Bu sozlamani hurmat qilish kerak: useReducedMotion() (Framer Motion hook) — agar foydalanuvchi reduced motion yoqgan bo'lsa true qaytaradi, siz animatsiyani kamaytirasiz yoki o'chirasiz (animate={{ x: shouldReduceMotion ? 0 : 100 }}); yoki CSS @media (prefers-reduced-motion: reduce) bilan. Ikki nuqta: (1) performance — transform/opacity (GPU — silliq 60 FPS); (2) reduced motion — a11y 1.9-bob: animatsiya hammaga mos kelmaydi (vestibulyar buzilishlar — bu jismoniy ehtiyoj, didi emas), va ko'p mintaqada bu qonuniy a11y talabi. Animatsiyani har kim uchun mos qilish — professional, mas'uliyatli frontend belgisi.

2.13. Web animatsiya asoslari — CSS transition, keyframes, will-change

text
  CSS ANIMATSIYA — brauzerning tug'ma imkoniyati (JS'siz, yengil):

  1. transition — HOLAT o'zgarishida silliq o'tish (hover, focus, class qo'shilishi):
     .btn { background: blue; transition: background 0.3s ease, transform 0.2s; }
     .btn:hover { background: darkblue; transform: translateY(-2px); }
     //  transition: <xususiyat> <davomiylik> <ease> <kechikish>

  2. @keyframes + animation — KO'P bosqichli, takrorlanadigan (spinner, pulse):
     @keyframes spin { from { transform: rotate(0); } to { transform: rotate(360deg); } }
     .loader { animation: spin 1s linear infinite; }   // cheksiz aylanish

     @keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.5; } }
     .skeleton { animation: pulse 1.5s ease-in-out infinite; }   // yuklanish skeleti

  3. will-change — brauzerga OLDINDAN xabar (bu element animatsiya qilinadi — GPU'ga tayyorla):
     .card { will-change: transform; }   //  FAQAT kerak bo'lganda (doim emas — xotira)

  BROWSER RENDER QUVURI (nega transform/opacity arzon):
  JS  Style  Layout (reflow)  Paint  Composite (GPU)
   transform/opacity  faqat Composite (Layout/Paint'ni O'TKAZIB yuboradi — arzon)
   width/top/margin  Layout'dan boshlab hammasini qayta (qimmat — 11.1: 2.7)

   transition — oddiy holat o'tishi; @keyframes — ko'p bosqichli/takror (spinner, pulse)
   will-change: transform — GPU'ga tayyorla (lekin faqat kerakli elementga — ortiqcha = zarar)

Web animatsiya asoslari — Framer Motion va Swiper ostidagi poydevor. Barcha animatsiya brauzerning render quvuri ustida ishlaydi: Style Layout Paint Composite. transform va opacity faqat oxirgi Composite bosqichini o'zgartiradi (GPU'da, layout hisoblamasdan) — shuning uchun ular silliq 2.2-bob. CSS transition — holat o'zgarishida (hover, focus, class qo'shilishi) ikki qiymat orasida avtomatik o'tish: transition: transform 0.2s ease (sintaksis: xususiyat, davomiylik, ease, ixtiyoriy kechikish). CSS @keyframes + animation — ko'p bosqichli yoki takrorlanadigan animatsiya uchun (spinner rotate(360deg) infinite, pulse opacity — skeleton yuklanish): siz oraliq nuqtalarni (0%, 50%, 100%) belgilaysiz. will-change: transform — brauzerga oldindan "bu element animatsiya qilinadi" deb xabar beradi (u elementni alohida GPU qatlamiga ("layer") ko'taradi, tayyorlaydi) — lekin buni faqat kerak bo'lganda ishlating: har elementga will-change qo'yish xotirani behuda sarflaydi va aksincha sekinlashtiradi. Ikki nuqta: (1) transition — oddiy holat o'tishi, @keyframes — murakkab/takrorlanuvchi (spinner, pulse, skeleton); (2) will-change — GPU optimizatsiya bosqichi, lekin tejamli ishlatish kerak. Bu asoslar — Framer Motion aslida shu CSS mexanizmlarini deklarativ, boshqariladigan qobiqqa o'raydi.

2.14. Motion values, keyframes va useAnimate

text
  MOTION VALUES — animatsiya qiymatini QO'LDA kuzatish/boshqarish (re-render'siz):
  import { useMotionValue, useTransform } from "motion/react";
  const x = useMotionValue(0);                       // reaktiv qiymat (state emas — tezroq)
  const opacity = useTransform(x, [-150, 0, 150], [0, 1, 0]);   // x'ni opacity'ga MAP
  <motion.div style={{ x, opacity }} drag="x" />     // sudralganda cheklarda so'nadi

  KEYFRAMES — bir animatsiyada BIR NECHTA nuqta (massiv):
  <motion.div animate={{ x: [0, 100, 50, 0] }}       //  0100500 ketma-ket
    transition={{ duration: 2, times: [0, 0.4, 0.7, 1] }} />   // har nuqta vaqti

  useAnimate — IMPERATIV boshqaruv (ketma-ket, shartli animatsiya — kompleks oqim):
  const [scope, animate] = useAnimate();
  async function run() {
    await animate(scope.current, { x: 100 });        // await — ketma-ket
    await animate("li", { opacity: 1 }, { delay: stagger(0.1) });
  }

   Motion value — re-render'siz reaktiv qiymat (drag/scroll'da tez — performant)
   animate massivi — keyframes (ko'p nuqta); useAnimate — imperativ (murakkab ketma-ketlik)

Motion values, keyframes va useAnimate — Framer Motion'ning ilg'or, past darajali boshqaruvi. Motion value (useMotionValue) — animatsiya qiymatini React state'siz kuzatadigan maxsus reaktiv qiymat: uni o'zgartirsangiz komponent qayta render bo'lmaydi (Framer to'g'ridan-to'g'ri DOM'ni yangilaydi — drag, scroll kabi tez-tez o'zgaradigan qiymatlar uchun juda performant). useTransform — bir motion value'ni boshqasiga map qiladi: useTransform(x, [-150, 0, 150], [0, 1, 0]) — x -150 yoki 150'da opacity 0, 0'da opacity 1 (chekka tomon sudralganda element so'nadi). Keyframesanimate prop'ga qiymat o'rniga massiv berish: animate={{ x: [0, 100, 50, 0] }} — element bir necha nuqtadan o'tadi (times bilan har nuqtaning vaqtini boshqarasiz). useAnimateimperativ boshqaruv: const [scope, animate] = useAnimate() beradi, so'ng await animate(...) bilan animatsiyalarni ketma-ket yoki shartli boshqarasiz (murakkab oqim — masalan, "avval karta ochilsin, keyin ichidagi elementlar bittalab paydo bo'lsin"). Ikki nuqta: (1) motion value — re-render'siz reaktiv qiymat (drag/scroll uchun tez); (2) keyframes massiv — ko'p bosqichli, useAnimate — imperativ ketma-ketlik (deklarativ yetmagan murakkab hollarda). Bular — kundalik animatsiyada kamroq, lekin "yuqori darajali", boshqariladigan effektlar uchun zarur.

2.15. Scroll animatsiya — useScroll, useTransform, parallax

text
  useScroll — SCROLL holatini kuzatish (progress bar, parallax, reveal):
  import { useScroll, useTransform, motion } from "motion/react";

  1. Sahifa scroll progressi (o'qish indikatori — yuqorida chiziq):
     const { scrollYProgress } = useScroll();          // 0 (tepa)  1 (past)
     <motion.div style={{ scaleX: scrollYProgress }} className="progress-bar" />

  2. Element'ga bog'liq (element ekranda qanchalik ko'ringani):
     const ref = useRef(null);
     const { scrollYProgress } = useScroll({
       target: ref, offset: ["start end", "end start"],   // element kirdi  chiqdi
     });
     const y = useTransform(scrollYProgress, [0, 1], [0, -200]);   // PARALLAX
     <motion.img ref={ref} style={{ y }} />              // fon sekinroq harakat (chuqurlik)

   scrollYProgress — 01 scroll holati (progress bar, parallax'ning manbasi)
   useTransform bilan map — scroll'ni har xil effektga (y siljish = parallax, scale, opacity)

Scroll animatsiya (ilg'or)whileInView 2.11-bob oddiy "ko'ringanda paydo bo'l" uchun; useScroll esa scroll holatiga uzluksiz bog'liq effektlar uchun. useScroll()scrollYProgress motion value qaytaradi (0 = tepada, 1 = pastda). Eng keng ikki qo'llanish: (1) o'qish progress bar<motion.div style={{ scaleX: scrollYProgress }} /> (sahifa ustidagi chiziq scroll bilan to'ladi); (2) parallax — element'ga bog'lab (useScroll({ target: ref, offset: [...] })) va useTransform bilan scroll progressni y siljishga map qilib, fon rasmini kontentdan sekinroq harakatlantirasiz (chuqurlik illyuziyasi — landing page, hero seksiyalar). offset — element scroll'ning qaysi bosqichida "boshlanadi/tugaydi"ni belgilaydi ("start end" = element tepasi viewport tagiga tegdi, "end start" = element tagi viewport tepasiga chiqdi). Ikki nuqta: (1) scrollYProgress — 01 uzluksiz scroll holati (bir marta emas — har kadr yangilanadi); (2) useTransform bilan uni istalgan effektga (parallax y, scale, opacity, rotate) map qilasiz. Bu — zamonaviy "scrollytelling" va marketing sahifalarining asosi (lekin mo'l-ko'l ishlatilsa performansga e'tibor bering — 2.2).

2.16. Swiper — effektlar, thumbs, virtual, custom navigation, event

text
  SWIPER — ilg'or imkoniyatlar:

  1. EFFEKTLAR (o'tish uslubi) — modul + prop + CSS:
     import { EffectFade, EffectCoverflow } from "swiper/modules";
     import "swiper/css/effect-fade";
     <Swiper modules={[EffectFade]} effect="fade" />          // silliq fade (slide o'rniga)
     <Swiper modules={[EffectCoverflow]} effect="coverflow"   // 3D coverflow (galereya)
       coverflowEffect={{ rotate: 30, depth: 200 }} />

  2. THUMBS — asosiy + kichik rasm galereya (ikki Swiper bog'langan):
     const [thumbs, setThumbs] = useState(null);
     <Swiper modules={[Thumbs]} thumbs={{ swiper: thumbs }}>...</Swiper>   // katta
     <Swiper onSwiper={setThumbs} slidesPerView={4}>...</Swiper>          // kichiklar

  3. VIRTUAL — MINGLAB slayd (faqat ko'rinadiganini render — performance):
     <Swiper modules={[Virtual]} virtual>
       {items.map((it, i) => <SwiperSlide key={it.id} virtualIndex={i}>...)}
     </Swiper>

  4. CUSTOM NAVIGATION + EVENT (o'z tugmalaring, holat kuzatish):
     <Swiper onSlideChange={(sw) => setActive(sw.activeIndex)}
             onSwiper={(sw) => (ref.current = sw)} />
     <button onClick={() => ref.current.slideNext()}>Keyingi</button>

   effect (fade/coverflow) — modul + prop + CSS; thumbs — ikki bog'langan Swiper
   virtual — minglab slaydda faqat ko'rinadiganini render (performance); event — holat/boshqaruv

Swiper ilg'or imkoniyatlar — asosiy modullardan 2.4-bob tashqarida. Effektlar — slaydlar orasidagi o'tish uslubini o'zgartiradi: EffectFade (siljish o'rniga silliq fade — banner uchun chiroyli), EffectCoverflow (3D coverflow — kartalar burchak bilan orqaga ketadi, galereya effekti). Har effekt uchun modul + effect="..." prop + mos CSS (swiper/css/effect-fade). Thumbs — ikkita bog'langan Swiper: katta asosiy slayder va tagida kichik rasm ("thumbnail") galereyasi (thumbnail bosilsa asosiy slayder o'sha rasmga o'tadi — mahsulot sahifalarida klassik). Virtual — minglab slayd bo'lganda, Swiper faqat ko'rinadigan slaydlarni DOM'ga render qiladi (windowing — 11.11 virtualizatsiya tamoyili — katta ro'yxatda xotira/performansni saqlaydi). Custom navigation va event — Swiper instansiyasini onSwiper bilan olib (ref.current.slideNext()), yoki onSlideChange bilan joriy slaydni kuzatib, o'z tugmalaringiz va progress ko'rsatkichlaringizni qu: bu sizga to'liq dizayn erkinligini beradi. Ikki nuqta: (1) effect (fade/coverflow) — o'tish uslubini o'zgartiradi (modul + prop + CSS), thumbs — ikki bog'langan slayder; (2) virtual — juda ko'p slaydda performansni saqlaydi, onSlideChange/onSwiper event'lari — holat kuzatish va imperativ boshqaruv. Swiper juda boy — hujjatida ko'p modul va sozlama bor, lekin bu to'rt to'plam eng amaliyi.

2.17. Loading/skeleton animatsiya va micro-interaksiya

text
  LOADING — kutish paytida "jonli" his (bo'sh ekran o'rniga):

  1. SPINNER (CSS keyframes — 2.13):
     @keyframes spin { to { transform: rotate(360deg); } }
     .spinner { animation: spin 0.8s linear infinite; }

  2. SKELETON (kontent shakli + pulse — perceived tezlik):
     .skeleton { background: #eee; animation: pulse 1.5s infinite; }
     //  kontent kelguncha uning "shakli"ni ko'rsatadi (bo'shliqdan yaxshi — UX)

  3. Framer bilan skeletonkontent (silliq almashish):
     <AnimatePresence mode="wait">
       {loading
         ? <motion.div key="skel" exit={{ opacity: 0 }}><Skeleton/></motion.div>
         : <motion.div key="data" initial={{ opacity: 0 }} animate={{ opacity: 1 }}>{data}</motion.div>}
     </AnimatePresence>

  MICRO-INTERAKSIYA — kichik, maqsadli javob (tugma bosildi, like, toast):
  whileTap={{ scale: 0.9 }}   layout (like soni o'zgarsa)   toast (AnimatePresence)

   Skeleton — kutishda kontent shaklini ko'rsat (perceived tezlik — bo'shliqdan yaxshi)
   Micro-interaksiya — kichik javob (bosish, like, xato) — ilovani "tirik" his qiladi

Loading/skeleton animatsiya va micro-interaksiya — animatsiyaning UX'ga eng bevosita ta'siri. Loading animatsiya — ma'lumot yuklanayotganda (11.5 fetch, TanStack Query) bo'sh, muzlagan ekran o'rniga "jarayon ketmoqda" hissi: spinner (CSS rotate infinite — 2.13) oddiy hollarda; skeleton (kontentning kulrang "shakli" + pulse animatsiya) esa yaxshiroq — foydalanuvchi nima kelishini oldindan ko'radi ("perceived performance" — kutish qisqaroq tuyuladi). Skeleton'dan haqiqiy kontentga o'tishni AnimatePresence mode="wait" bilan silliq qiling (skeleton fade-out, kontent fade-in). Micro-interaksiya — kichik, maqsadli javoblar: tugma bosilganda whileTap={{ scale: 0.9 }} (tactile his), like tugmasi bosilganda son layout bilan silliq o'zgarishi, xato/muvaffaqiyat toast'i AnimatePresence bilan kirib-chiqishi. Bular kichik, lekin ilovani tirik va javobgar his qildiradi. Ikki nuqta: (1) skeleton — kutish paytida kontent shaklini ko'rsatib, kutishni qisqaroq his qildiradi (perceived tezlik); (2) micro-interaksiya — har harakatga darrov, kichik javob (professional ilovaning belgisi). Loading holati 11.5-bob + animatsiya birga — silliq, ishonchli UX.

2.18. Muqobil kutubxonalar — react-spring, GSAP, Lottie, auto-animate

text
  FRAMER MOTION'DAN BOSHQA (qachon kerak):

  - react-spring — fizik "spring" asosidagi (Framer'ga o'xshash, hook-first); tabiiy his
  - GSAP — eng kuchli/professional timeline animatsiya (murakkab ketma-ketlik, SVG, scroll);
    React'siz ham; og'irroq, imperativ (dizayn-og'ir loyihalarda kuchli)
  - Lottie (lottie-react) — dizayner After Effects'da chizgan animatsiyani (JSON) o'ynatish;
    murakkab illyustrativ animatsiya (onboarding, empty state) — kod'siz
  - @formkit/auto-animate — ENG oddiy: bitta hook, ro'yxat qo'shilish/o'chishi avtomatik silliq;
    "sozlamasiz" tez yechim (kichik loyihada yetarli)

   Framer Motion — React uchun standart (deklarativ, keng); boshqasi maxsus hollarda
   auto-animate (oddiy), Lottie (dizayner animatsiya), GSAP (murakkab timeline)

Muqobil kutubxonalar — Framer Motion React uchun standart tanlov (deklarativ, keng imkoniyat, yaxshi hujjat), lekin ba'zi hollarda boshqasi mos keladi. react-spring — fizik prujina modeliga asoslangan, hook-birinchi API (Framer'ga o'xshash falsafa; kimgadir hook uslubi qulayroq). GSAP (GreenSock) — eng kuchli, professional timeline animatsiya vositasi (murakkab ketma-ketliklar, SVG morphing, ScrollTrigger) — React'ga bog'liq emas, imperativ, biroz og'irroq; dizayn-og'ir marketing saytlar va murakkab animatsiyalar uchun sanoat standarti. Lottie (lottie-react) — dizayner After Effects'da yaratgan animatsiyani JSON sifatida eksport qilib, ilovada o'ynatish imkonini beradi (murakkab illyustrativ animatsiyalar — onboarding, bo'sh holat rasmlari — kod yozmasdan). @formkit/auto-animate — eng oddiysi: bitta hook'ni konteynerga ulaysiz, ichidagi elementlar qo'shilishi/o'chishi/tartiblanishi avtomatik silliq bo'ladi (sozlamasiz, tez yechim — kichik loyiha uchun yetarli). Ikki nuqta: (1) Framer Motion — React uchun standart va tavsiya etilgan boshlang'ich tanlov; (2) maxsus ehtiyoj bo'lsa: auto-animate (eng oddiy avtomatik), Lottie (dizayner animatsiya), GSAP (eng murakkab timeline/scroll). Vositani ehtiyojga qarab tanlang — ortiqcha kuchli vosita (GSAP) oddiy loyihada keraksiz murakkablik keltiradi.


3. Sintaksis — tez ma'lumotnoma

text
SWIPER 2.3-bob:      <Swiper slidesPerView={1} spaceBetween={20}><SwiperSlide>...</SwiperSlide></Swiper>
SWIPER MODUL 2.4-bob:modules={[Navigation,Pagination,Autoplay]} navigation pagination autoplay={{delay}}
BREAKPOINTS 2.5-bob: breakpoints={{ 640:{slidesPerView:2}, 1024:{slidesPerView:3} }}
MOTION 2.6-bob:      <motion.div initial={{opacity:0}} animate={{opacity:1}} transition={{duration:0.4}}/>
VARIANTS 2.8-bob:    variants={v} initial="hidden" animate="visible"  // staggerChildren
GESTURE 2.9-bob:     whileHover={{scale:1.05}} whileTap={{scale:0.95}}  |  drag dragConstraints={...}
PRESENCE 2.10-bob:   <AnimatePresence>{open && <motion.div exit={{opacity:0}}/>}</AnimatePresence>
LAYOUT 2.11-bob:     <motion.div layout/>
SCROLL 2.11-bob:     whileInView={{opacity:1}} viewport={{once:true}}
A11Y 2.12-bob:       const reduce = useReducedMotion()
CSS 2.13-bob:        @keyframes spin{to{transform:rotate(360deg)}} .x{animation:spin 1s linear infinite}
MOTION VAL 2.14-bob: const x=useMotionValue(0); const o=useTransform(x,[-150,0,150],[0,1,0])
KEYFRAMES 2.14-bob:  animate={{ x:[0,100,50,0] }} transition={{ times:[0,0.4,0.7,1] }}
useAnimate 2.14-bob: const [scope,animate]=useAnimate(); await animate(scope.current,{x:100})
useScroll 2.15-bob:  const {scrollYProgress}=useScroll(); const y=useTransform(scrollYProgress,[0,1],["0%","50%"])
SWIPER EFFEKT2.16-bob:modules={[EffectFade]} effect="fade" | effect="coverflow"
SWIPER EVENT2.16-bob:onSlideChange={(sw)=>...} onSwiper={(sw)=>ref.current=sw}

4. Batafsil kod namunalari

Misol 1 — Swiper asosiy (2.3)

tsx
import { Swiper, SwiperSlide } from "swiper/react";
import "swiper/css";

function Gallery({ images }: { images: string[] }) {
  return (
    <Swiper spaceBetween={20} slidesPerView={1}>
      {images.map((src, i) => (
        <SwiperSlide key={i}>
          <img src={src} alt={`Slayd ${i + 1}`} className="slide-img" />
        </SwiperSlide>
      ))}
    </Swiper>
  );
}

Misol 2 — Swiper modullar (navigation/pagination/autoplay — 2.4)

tsx
import { Swiper, SwiperSlide } from "swiper/react";
import { Navigation, Pagination, Autoplay } from "swiper/modules";
import "swiper/css";
import "swiper/css/navigation";
import "swiper/css/pagination";

function Banner({ slides }: { slides: Slide[] }) {
  return (
    <Swiper
      modules={[Navigation, Pagination, Autoplay]}
      navigation                                  // o'q tugmalari
      pagination={{ clickable: true }}            // nuqtalar
      autoplay={{ delay: 4000, disableOnInteraction: false }}   // 4s avtomatik
      loop                                         // cheksiz
    >
      {slides.map(s => (
        <SwiperSlide key={s.id}>
          <div className="banner" style={{ background: s.color }}>{s.title}</div>
        </SwiperSlide>
      ))}
    </Swiper>
  );
}

Misol 3 — Swiper responsive (breakpoints — 2.5)

tsx
function ProductCarousel({ products }: { products: Product[] }) {
  return (
    <Swiper
      slidesPerView={1}
      spaceBetween={10}
      breakpoints={{
        640: { slidesPerView: 2, spaceBetween: 20 },
        1024: { slidesPerView: 3, spaceBetween: 30 },
        1280: { slidesPerView: 4, spaceBetween: 40 },
      }}
    >
      {products.map(p => (
        <SwiperSlide key={p.id}><ProductCard product={p} /></SwiperSlide>
      ))}
    </Swiper>
  );
}
//  Mobilda 1, tabletda 2, desktopda 3-4 mahsulot (responsive — 2.5)

Misol 4 — Framer Motion: fade-in (2.6, 2.7)

tsx
import { motion } from "motion/react";

function Hero() {
  return (
    <motion.section
      initial={{ opacity: 0, y: 30 }}             // ko'rinmas + pastda
      animate={{ opacity: 1, y: 0 }}              // ko'rinadigan + joyida
      transition={{ duration: 0.6, ease: "easeOut" }}
    >
      <h1>Xush kelibsiz</h1>
      <p>Zamonaviy ilova</p>
    </motion.section>
  );
}
//  Sahifa ochilganda hero silliq pastdan ko'tarilib paydo bo'ladi (2.7)

Misol 5 — Variants va stagger (ro'yxat — 2.8)

tsx
const container = {
  hidden: { opacity: 0 },
  visible: { opacity: 1, transition: { staggerChildren: 0.1 } },   // bolalar ketma-ket
};
const item = {
  hidden: { opacity: 0, y: 20 },
  visible: { opacity: 1, y: 0 },
};

function ProductGrid({ products }: { products: Product[] }) {
  return (
    <motion.div className="grid" variants={container} initial="hidden" animate="visible">
      {products.map(p => (
        <motion.div key={p.id} variants={item} className="card">
          {p.name}
        </motion.div>
      ))}
    </motion.div>
  );
}
//  Kartalar birin-ketin (0.1s farq) paydo bo'ladi (professional — 2.8)

Misol 6 — Gestures: hover va tap (2.9)

tsx
function AnimatedButton({ children, onClick }: React.PropsWithChildren<{ onClick: () => void }>) {
  return (
    <motion.button
      whileHover={{ scale: 1.05 }}                // hoverkattalash
      whileTap={{ scale: 0.95 }}                  // bosgandakichrash
      transition={{ type: "spring", stiffness: 400 }}
      onClick={onClick}
    >
      {children}
    </motion.button>
  );
}

// Karta hover (ko'tarilish):
function Card({ title }: { title: string }) {
  return (
    <motion.div className="card" whileHover={{ y: -8, boxShadow: "0 10px 30px rgba(0,0,0,0.15)" }}>
      {title}
    </motion.div>
  );
}

Misol 7 — Drag (sudraladigan — 2.9)

tsx
function DraggableCard() {
  return (
    <motion.div
      className="card"
      drag
      dragConstraints={{ left: -100, right: 100, top: -50, bottom: 50 }}
      dragElastic={0.2}                           // chegaradan tashqari elastik
      whileDrag={{ scale: 1.1, cursor: "grabbing" }}
    >
      Meni sudra
    </motion.div>
  );
}
//  drag — sudraladigan; dragConstraints — chegara; whileDrag — sudrash paytidagi holat (2.9)

Misol 8 — AnimatePresence (modal kirish/chiqish — 2.10)

tsx
import { AnimatePresence, motion } from "motion/react";
import { createPortal } from "react-dom";   // 11.12

function Modal({ isOpen, onClose, children }: ModalProps) {
  return createPortal(
    <AnimatePresence>
      {isOpen && (
        <motion.div
          className="backdrop"
          initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }}   // fon
          onClick={onClose}
        >
          <motion.div
            className="modal"
            initial={{ opacity: 0, scale: 0.9, y: 20 }}        // kirish
            animate={{ opacity: 1, scale: 1, y: 0 }}
            exit={{ opacity: 0, scale: 0.9, y: 20 }}            //  chiqish (silliq yopilish)
            transition={{ type: "spring", duration: 0.3 }}
            onClick={e => e.stopPropagation()}
          >
            {children}
          </motion.div>
        </motion.div>
      )}
    </AnimatePresence>,
    document.body
  );
}
//  Modal silliq KIRADI va silliq CHIQADI (exit — AnimatePresence kutadi — 2.10)

Misol 9 — AnimatePresence: ro'yxat elementi o'chishi (2.10)

tsx
function TodoList({ todos, onRemove }: { todos: Todo[]; onRemove: (id: string) => void }) {
  return (
    <ul>
      <AnimatePresence>
        {todos.map(todo => (
          <motion.li
            key={todo.id}                          //  key MAJBURIY (AnimatePresence kuzatadi)
            layout                                  // boshqalar silliq ko'chsin (2.11)
            initial={{ opacity: 0, height: 0 }}
            animate={{ opacity: 1, height: "auto" }}
            exit={{ opacity: 0, x: -100 }}          // o'chganda chapga suriladi
          >
            {todo.text}
            <button onClick={() => onRemove(todo.id)}></button>
          </motion.li>
        ))}
      </AnimatePresence>
    </ul>
  );
}
//  Element o'chganda silliq chiqadi + qolganlar silliq ko'chadi (layout — 2.10, 2.11)

Misol 10 — Layout animatsiya (2.11)

tsx
function ExpandableCard() {
  const [expanded, setExpanded] = useState(false);
  return (
    <motion.div
      layout                                       // o'lcham o'zgarsaavtomatik silliq
      className="card"
      onClick={() => setExpanded(!expanded)}
    >
      <motion.h3 layout>Sarlavha</motion.h3>
      {expanded && (
        <motion.p layout initial={{ opacity: 0 }} animate={{ opacity: 1 }}>
          Qo'shimcha kontent (ochilganda silliq paydo bo'ladi)
        </motion.p>
      )}
    </motion.div>
  );
}
//  layout — karta kattalashganda (kontent qo'shilganda) silliq ko'chadi (2.11)

Misol 11 — Scroll animatsiya (whileInView — 2.11)

tsx
function FeatureSection({ feature }: { feature: Feature }) {
  return (
    <motion.div
      className="feature"
      initial={{ opacity: 0, y: 50 }}
      whileInView={{ opacity: 1, y: 0 }}           // ekranga kirganda (scroll)
      viewport={{ once: true, amount: 0.3 }}        // bir marta, 30% ko'ringanda
      transition={{ duration: 0.5 }}
    >
      <h3>{feature.title}</h3>
      <p>{feature.description}</p>
    </motion.div>
  );
}
//  Scroll qilingan sayin har feature paydo bo'ladi (landing page — 2.11)

Misol 12 — Sahifa o'tish animatsiyasi (routing bilan — 2.10)

tsx
import { AnimatePresence, motion } from "motion/react";
import { useLocation, Outlet } from "react-router-dom";

function AnimatedLayout() {
  const location = useLocation();
  return (
    <AnimatePresence mode="wait">                  {/* eski chiqgach yangi kirsin */}
      <motion.div
        key={location.pathname}                     //  yo'l o'zgarsayangi animatsiya
        initial={{ opacity: 0, x: 20 }}
        animate={{ opacity: 1, x: 0 }}
        exit={{ opacity: 0, x: -20 }}
        transition={{ duration: 0.25 }}
      >
        <Outlet />                                  {/* sahifa 11.9-bob */}
      </motion.div>
    </AnimatePresence>
  );
}
//  Sahifalar almashganda silliq o'tish (mode="wait" — eski chiqgach yangi — 2.10)

Misol 13 — Reduced motion (a11y — 2.12)

tsx
import { motion, useReducedMotion } from "motion/react";

function AnimatedCard({ title }: { title: string }) {
  const shouldReduceMotion = useReducedMotion();   // foydalanuvchi "harakatni kamaytir" yoqganmi

  return (
    <motion.div
      className="card"
      initial={{ opacity: 0, y: shouldReduceMotion ? 0 : 30 }}   // reducedsiljish yo'q
      animate={{ opacity: 1, y: 0 }}
      transition={{ duration: shouldReduceMotion ? 0 : 0.4 }}     // reduceddarrov
    >
      {title}
    </motion.div>
  );
}
//  Reduced motion'da — faqat opacity (siljish/spring yo'q) — vestibulyar foydalanuvchilar uchun (2.12)

Misol 14 — Swiper + Framer Motion birga (mahsulot galereyasi)

tsx
function ProductShowcase({ products }: { products: Product[] }) {
  return (
    <motion.section
      initial={{ opacity: 0 }}
      whileInView={{ opacity: 1 }}                 // scroll'da paydo
      viewport={{ once: true }}
    >
      <motion.h2 initial={{ y: 20, opacity: 0 }} whileInView={{ y: 0, opacity: 1 }}>
        Mashhur mahsulotlar
      </motion.h2>
      <Swiper
        modules={[Navigation, Pagination]}
        navigation pagination={{ clickable: true }}
        breakpoints={{ 640: { slidesPerView: 2 }, 1024: { slidesPerView: 4 } }}
      >
        {products.map(p => (
          <SwiperSlide key={p.id}>
            <motion.div whileHover={{ y: -8 }}>    {/* hover ko'tarilish */}
              <ProductCard product={p} />
            </motion.div>
          </SwiperSlide>
        ))}
      </Swiper>
    </motion.section>
  );
}
//  Swiper (karusel) + Framer Motion (scroll reveal + hover) birga — jonli galereya

Misol 15 — Sof CSS animatsiya: spinner va skeleton (2.13, 2.17)

css
/* CSS @keyframes — JS'siz, yengil (spinner, skeleton) */
@keyframes spin {
  to { transform: rotate(360deg); }        /* transform — GPU 2.13-bob */
}
.spinner {
  width: 32px; height: 32px;
  border: 3px solid #e5e7eb;
  border-top-color: #2563eb;               /* faqat bir chet rangli — aylanish ko'rinadi */
  border-radius: 50%;
  animation: spin 0.8s linear infinite;    /* cheksiz aylanish */
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.4; }
}
.skeleton {
  background: #e5e7eb;
  border-radius: 6px;
  animation: pulse 1.5s ease-in-out infinite;   /* yuklanish "shakli" 2.17-bob */
}

/* prefers-reduced-motion — a11y: animatsiyani o'chir 2.12-bob */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

Misol 16 — Skeleton kontent silliq almashish (AnimatePresence — 2.17)

tsx
import { AnimatePresence, motion } from "motion/react";

function UserProfile({ userId }: { userId: string }) {
  const { data, isLoading } = useUser(userId);       // 11.5 (TanStack Query)

  return (
    <AnimatePresence mode="wait">                     {/* eski chiqgach yangi kirsin */}
      {isLoading ? (
        <motion.div key="skeleton" exit={{ opacity: 0 }}>
          <div className="skeleton" style={{ height: 24, width: "60%" }} />
          <div className="skeleton" style={{ height: 16, width: "90%", marginTop: 8 }} />
        </motion.div>
      ) : (
        <motion.div key="data" initial={{ opacity: 0 }} animate={{ opacity: 1 }}>
          <h2>{data.name}</h2>
          <p>{data.bio}</p>
        </motion.div>
      )}
    </AnimatePresence>
  );
}
//  Yuklanishda skeleton, tayyor bo'lganda kontent — silliq fade (perceived tezlik — 2.17)

Misol 17 — Scroll progress bar va parallax (useScroll/useTransform — 2.15)

tsx
import { motion, useScroll, useTransform } from "motion/react";
import { useRef } from "react";

// 1. Sahifa o'qish progress bar (yuqorida)
function ReadingProgress() {
  const { scrollYProgress } = useScroll();            // 0 (tepa)  1 (past)
  return (
    <motion.div
      style={{ scaleX: scrollYProgress, transformOrigin: "left" }}   //  GPU (scaleX)
      className="progress-bar"                          // position: fixed; top: 0; height: 4px
    />
  );
}

// 2. Parallax hero (fon rasm kontentdan sekinroq)
function ParallaxHero() {
  const ref = useRef(null);
  const { scrollYProgress } = useScroll({
    target: ref,
    offset: ["start end", "end start"],                // element kirdi  chiqdi
  });
  const y = useTransform(scrollYProgress, [0, 1], ["0%", "50%"]);   // scroll  siljish

  return (
    <div ref={ref} className="hero" style={{ overflow: "hidden" }}>
      <motion.img src="/bg.jpg" style={{ y }} alt="" />  {/* sekinroq — chuqurlik */}
      <h1>Sarlavha</h1>
    </div>
  );
}

Misol 18 — Motion values + keyframes (drag fade, ko'p bosqich — 2.14)

tsx
import { motion, useMotionValue, useTransform } from "motion/react";

// Drag: chetga sudralganda so'nadi (motion value + useTransform)
function SwipeToDismiss({ onDismiss }: { onDismiss: () => void }) {
  const x = useMotionValue(0);                          // re-render'siz reaktiv (2.14)
  const opacity = useTransform(x, [-150, 0, 150], [0, 1, 0]);   // chetda 0

  return (
    <motion.div
      style={{ x, opacity }}
      drag="x"
      dragConstraints={{ left: 0, right: 0 }}            // qo'yib yuborilsa markazga qaytadi
      onDragEnd={(_, info) => {
        if (Math.abs(info.offset.x) > 120) onDismiss();  // yetarli surildi — o'chir
      }}
    >
      Meni chetga surib yuboring
    </motion.div>
  );
}

// Keyframes: bir animatsiyada ko'p nuqta (diqqat tortuvchi "wiggle")
function AttentionIcon() {
  return (
    <motion.span
      animate={{ rotate: [0, -10, 10, -10, 0] }}         //  ketma-ket nuqtalar (2.14)
      transition={{ duration: 0.5, repeat: Infinity, repeatDelay: 3 }}
    >
      
    </motion.span>
  );
}

Misol 19 — useAnimate: imperativ ketma-ket animatsiya (2.14)

tsx
import { useAnimate, stagger } from "motion/react";

function Notification() {
  const [scope, animate] = useAnimate();

  async function show() {
    await animate(scope.current, { opacity: 1, y: 0 }, { duration: 0.3 });   // avval konteyner
    await animate("li", { opacity: 1, x: 0 }, { delay: stagger(0.08) });     // keyin elementlar
  }

  return (
    <div ref={scope} style={{ opacity: 0, transform: "translateY(20px)" }}>
      <button onClick={show}>Ko'rsatish</button>
      <ul>
        <li style={{ opacity: 0 }}>Birinchi</li>
        <li style={{ opacity: 0 }}>Ikkinchi</li>
        <li style={{ opacity: 0 }}>Uchinchi</li>
      </ul>
    </div>
  );
}
//  await — animatsiyalar ketma-ket (deklarativ yetmagan murakkab oqim uchun — 2.14)

Misol 20 — Swiper effekt (coverflow) + thumbs galereya (2.16)

tsx
import { Swiper, SwiperSlide } from "swiper/react";
import { EffectCoverflow, Thumbs, Navigation } from "swiper/modules";
import { useState } from "react";
import "swiper/css";
import "swiper/css/effect-coverflow";
import "swiper/css/thumbs";
import "swiper/css/navigation";
import type { Swiper as SwiperClass } from "swiper";

function ProductGallery({ images }: { images: string[] }) {
  const [thumbs, setThumbs] = useState<SwiperClass | null>(null);

  return (
    <>
      <Swiper
        modules={[EffectCoverflow, Thumbs, Navigation]}
        effect="coverflow"                                  // 3D coverflow (2.16)
        coverflowEffect={{ rotate: 30, depth: 200, modifier: 1 }}
        navigation
        thumbs={{ swiper: thumbs }}                          // kichiklarga bog'la
        centeredSlides
        slidesPerView="auto"
      >
        {images.map((src, i) => (
          <SwiperSlide key={i} style={{ width: 300 }}>
            <img src={src} alt={`Rasm ${i + 1}`} />
          </SwiperSlide>
        ))}
      </Swiper>

      <Swiper onSwiper={setThumbs} slidesPerView={5} spaceBetween={10} watchSlidesProgress>
        {images.map((src, i) => (
          <SwiperSlide key={i}>
            <img src={src} alt={`Kichik ${i + 1}`} className="thumb" />
          </SwiperSlide>
        ))}
      </Swiper>
    </>
  );
}
//  Katta (coverflow) + kichik (thumbs) bog'langan galereya (2.16)

Misol 21 — Swiper custom navigation + event (2.16)

tsx
import { Swiper, SwiperSlide } from "swiper/react";
import { useState, useRef } from "react";
import type { Swiper as SwiperClass } from "swiper";
import "swiper/css";

function CustomCarousel({ slides }: { slides: Slide[] }) {
  const swiperRef = useRef<SwiperClass | null>(null);
  const [active, setActive] = useState(0);

  return (
    <div>
      <Swiper
        onSwiper={(sw) => (swiperRef.current = sw)}          // instansiyani saqla
        onSlideChange={(sw) => setActive(sw.activeIndex)}    // joriy slaydni kuzat
      >
        {slides.map((s) => (
          <SwiperSlide key={s.id}>{s.content}</SwiperSlide>
        ))}
      </Swiper>

      {/* O'z dizaynli boshqaruv */}
      <div className="controls">
        <button onClick={() => swiperRef.current?.slidePrev()}>‹ Oldingi</button>
        <span>{active + 1} / {slides.length}</span>
        <button onClick={() => swiperRef.current?.slideNext()}>Keyingi ›</button>
      </div>
    </div>
  );
}
//  onSwiper — imperativ boshqaruv (slideNext/slidePrev); onSlideChange — holat kuzatish (2.16)

5. To'g'ri va noto'g'ri holatlar

1) Animatsiya xususiyati

text
 animate={{ left: 100, width: 200 }}  (reflow — lag — 2.2)
 animate={{ x: 100, scale: 1.2 }}  (transform — GPU — silliq)

2) Animatsiya tezligi

text
 transition={{ duration: 2 }}  (sekin — bezovta qiladi — 2.1)
 duration: 0.2-0.4  (tez, silliq)

3) Swiper CSS

text
 "swiper/css" import qilmaslik (slayder buzilgan ko'rinadi — 2.3)
 import "swiper/css" + modul CSS (navigation/pagination — 2.4)

4) Exit animatsiya

text
 {open && <motion.div exit={...}/>}  (AnimatePresence'siz — exit ishlamaydi — 2.10)
 <AnimatePresence>{open && <motion.div exit={...}/>}</AnimatePresence>

5) Ortiqcha animatsiya

text
 har element animatsiya (chalg'ituvchi, sekin — 2.1)
 maqsadli (muhim o'tishlar, holatlar — kamroq ko'pincha yaxshiroq)

6) A11y

text
 reduced motion'ni e'tiborsiz (vestibulyar foydalanuvchilar azoblanadi — 2.12)
 useReducedMotion / prefers-reduced-motion (1.9)

6. Keng tarqalgan xatolar va yechimlari

Xato 1 — Swiper buzilgan ko'rinadi (stillarsiz)

Sababi: swiper/css import qilinmagan 2.3-bob. Yechimi: import "swiper/css" + ishlatilgan modul CSS (swiper/css/navigation — 2.4).

Xato 2 — Swiper modul (navigation/autoplay) ishlamaydi

Sababi: modul modules={[...]}ga qo'shilmagan 2.4-bob. Yechimi: modules={[Navigation, Autoplay]} + prop (navigation, autoplay).

Xato 3 — Exit animatsiya ishlamaydi

Sababi: AnimatePresence yo'q, yoki key yo'q 2.10-bob. Yechimi: komponentni <AnimatePresence> bilan o'ra; ro'yxatda har elementga key.

Xato 4 — Animatsiya sakraydi/lag qiladi

Sababi: width/left/top animatsiya qilinmoqda (reflow — 2.2). Yechimi: transform (x/y/scale) va opacity ishlat.

Xato 5 — Layout animatsiya butun sahifani "sakratadi"

Sababi: layout prop noto'g'ri joyda (ortiqcha). Yechimi: faqat o'zgaradigan elementga layout; LayoutGroup bilan guruhla.

Xato 6 — Sahifa o'tishda ikki sahifa birga ko'rinadi

Sababi: AnimatePresence mode belgilanmagan. Yechimi: mode="wait" (eski chiqgach yangi kirsin — Misol 12).

Xato 7 — Animatsiya bundle juda katta

Sababi: butun Framer Motion import qilingan. Yechimi: LazyMotion + domAnimation (faqat keraklisi — 11.8 tamoyili).

Xato 8 — Swiper effekt (fade/coverflow) ishlamaydi

Sababi: effekt moduli yoki uning CSS'i import qilinmagan 2.16-bob. Yechimi: modules={[EffectFade]} + effect="fade" + import "swiper/css/effect-fade" (uchalasi kerak).

Xato 9 — Scroll/parallax animatsiya tutiladi (janky)

Sababi: useScroll'ni qimmat xususiyatlarga (top, height) map qilinmoqda, yoki useState orqali (har kadr re-render). Yechimi: motion value + useTransformni faqat transform/opacityga bog'lang (2.14, 2.15) — state emas.


7. Integratsiya — bu mavzu stack'ning qayerida uchraydi

  • Performance 11.11-bob: transform/opacity (GPU), reflow'dan qoch (60 FPS).
  • Portal 11.12-bob: modal animatsiya (createPortal + AnimatePresence).
  • Routing 11.9-bob: sahifa o'tish animatsiyasi (location.pathname + AnimatePresence).
  • State 11.4-bob: animatsiya holatga bog'liq (isOpen — modal kirish/chiqish).
  • a11y 1.9-bob: reduced motion (vestibulyar foydalanuvchilar).
  • Dashboard 11.15-bob: sidebar, modal, ro'yxat, statistika — animatsiya bilan jonli.
  • Code splitting 11.8-bob: LazyMotion (Framer bundle kichraytirish).
  • CSS (1-QISM): CSS transition/@keyframes (oddiy — 2.13) vs Framer Motion (murakkab).
  • Fetch/Query 11.5-bob: loading holati skeleton animatsiya (perceived tezlik — 2.17).
  • Virtualizatsiya 11.11-bob: Swiper virtual — minglab slaydda faqat ko'rinadiganini render 2.16-bob.

8. Eng yaxshi amaliyotlar (best practices)

  • Maqsadli animatsiya (UX yordami — bezak emas; kamroq ko'pincha yaxshiroq — 2.1).
  • Tez (200-400ms; sekin bezovta qiladi — 2.1).
  • transform/opacity (GPU — 60 FPS; width/left'dan qoch — 2.2).
  • Swiper CSS import (asosiy + modul — aks holda buziladi — 2.3, 2.4).
  • Responsive Swiper (breakpoints — mobil 1, desktop 3-4 — 2.5).
  • type: "spring" (tabiiy, hayotiy harakat — 2.7).
  • AnimatePresence exit uchun (modal, ro'yxat — silliq chiqish — 2.10).
  • layout prop (joy/o'lcham o'zgarishi — avtomatik silliq — 2.11).
  • whileInView scroll reveal (landing page — 2.11).
  • will-change tejamli (faqat animatsiyalanadigan elementga — ortiqcha = zarar — 2.13).
  • Motion value + useTransform (drag/scroll — re-render'siz, performant — 2.14, 2.15).
  • Skeleton yuklanishda (spinner'dan yaxshiroq — perceived tezlik — 2.17).
  • useReducedMotion (a11y — vestibulyar foydalanuvchilar — 2.12).

9. Amaliy loyiha: "Jonli Landing Page va Galereya"

Swiper va Framer Motion bilan to'liq jonli, professional landing page yaratish.

Maqsad

Animatsiyali landing page yarat: hero (fade-in), feature'lar (scroll reveal), mahsulot karuseli (Swiper), modal (AnimatePresence) — barchasi silliq va a11y bilan.

Talablar (requirements)

  1. Hero: sahifa ochilganda fade-in + slide-up (Misol 4, 2.7).
  2. Stagger: feature/karta to'plami ketma-ket paydo (variants — Misol 5, 2.8).
  3. Scroll reveal: har bo'lim scroll'da paydo (whileInView — Misol 11, 2.11).
  4. Swiper karusel: mahsulot/sharh karuseli, responsive + modullar (Misol 2, 3).
  5. Hover/tap: tugma/karta micro-interaksiya (Misol 6, 2.9).
  6. Modal: AnimatePresence bilan kirish/chiqish (portal — Misol 8, 11.12).
  7. Layout animatsiya: akkordeon/expandable yoki ro'yxat (Misol 9, 10, 2.11).
  8. Sahifa o'tish: routing bilan animatsiya (Misol 12, mode="wait").
  9. Performance: transform/opacity (GPU); 60 FPS (Profiler — 2.2, 11.11).
  10. A11y: useReducedMotion (animatsiyani kamaytirish — Misol 13, 2.12).

Maslahatlar (hint)

  • Swiper CSS import qilishni unutma (asosiy + modul — Xato 1, 2).
  • Animatsiya tez (0.3-0.5s) va transform/opacity bilan (GPU — Xato 4).
  • Exit animatsiya — AnimatePresence + key (Xato 3).
  • Stagger — variants + staggerChildren (Misol 5).
  • Scroll reveal — whileInView + viewport once (Misol 11).
  • Reduced motion'ni boshidan qo'sh (a11y — Misol 13).
  • Ortiqcha animatsiyadan qoch (maqsadli — kamroq yaxshiroq — 2.1).

"Tayyor" mezonlari (acceptance criteria)

  • Hero fade-in/slide-up.
  • Stagger (ketma-ket paydo).
  • Scroll reveal (har bo'lim).
  • Swiper karusel (responsive + navigation/pagination).
  • Hover/tap micro-interaksiya.
  • Modal AnimatePresence (kirish/chiqish).
  • Layout animatsiya (akkordeon/ro'yxat).
  • Sahifa o'tish animatsiyasi.
  • 60 FPS (transform/opacity — Profiler).
  • useReducedMotion (a11y).

Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.


10. Xulosa va keyingi bobga ko'prik

Bu bobda ilovani jonli va chiroyli qilishni o'rgandik:

  • Nega animatsiya (his qilinadigan sifat — 2.1); CSS vs JS, performance (transform/opacity — 2.2).
  • Web animatsiya asoslari (CSS transition/@keyframes/will-change, render quvuri — 2.13).
  • Swiper (setup — 2.3, modullar — 2.4, responsive — 2.5, effekt/thumbs/virtual/event — 2.16); Framer Motion (motion — 2.6, animate/transition — 2.7, variants — 2.8, gestures — 2.9, AnimatePresence — 2.10, layout/scroll — 2.11, motion values/keyframes/useAnimate — 2.14, useScroll/parallax — 2.15).
  • Loading/skeleton va micro-interaksiya (perceived tezlik — 2.17); muqobil kutubxonalar (react-spring, GSAP, Lottie, auto-animate — 2.18).
  • Performance va a11y (reduced motion — 2.12).

Endi siz ilovani jonli, silliq, professional qila olasiz — slayder (Swiper), kirish/chiqish animatsiyalari, gesture'lar, scroll effektlari — barchasi maqsadli va a11y bilan. Animatsiya — UX'ning "his qilinadigan sifati", va siz uni to'g'ri (ortiqcha emas) ishlatishni bilasiz.

Keyingi bob — 11.17-bob: Testing — Vitest, React Testing Library, Playwright. 11-QISM'ning yakuniy bobi. Ilovamiz funksional, jonli, lekin ishonchlimi? Test — bu ishonch: kod o'zgarganda eski narsa buzilmaganini (regression), yangi feature to'g'ri ishlashini avtomatik tekshiradi. Vitest (zamonaviy, tez test runner — Jest muqobili), React Testing Library (komponentni foydalanuvchi nuqtai nazaridan sinash — implementatsiya emas), va Playwright (e2e — butun ilovani real brauzerda sinash). Bu — professional, ishonchli kodning yakuniy qatlami.


Foydalanilgan rasmiy/ishonchli manbalar

  • Swiper rasmiy hujjati — React ishlatilishi, modullar (Navigation/Pagination/Autoplay/Thumbs/Virtual), effektlar (Fade/Coverflow), breakpoints, API/event
  • Framer Motion / Motion rasmiy hujjati — motion komponentlar, animate/initial/transition, variants va orkestratsiya, gesture'lar, AnimatePresence, layout, useScroll/useTransform, useMotionValue, useAnimate, useReducedMotion, LazyMotion
  • MDN Web Docs — CSS transition, @keyframes/animation, will-change, transform, prefers-reduced-motion
  • web.dev — brauzer render quvuri (Layout/Paint/Composite), animatsiya performansi (transform/opacity, 60 FPS)
  • W3C WCAG — "Animation from Interactions" va motion a11y (vestibulyar buzilishlar — reduced motion)
  • Muqobil kutubxonalar rasmiy hujjatlari — react-spring, GSAP (GreenSock), Lottie, @formkit/auto-animate

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
11.16-bob: Swiper va animatsiya (Framer Motion) — Wisar