egjs-flicking

repository·master·Indexed 25 days ago

https://github.com/naver/egjs-flicking

A reliable, flexible, and extendable carousel component for modern web development. It supports SSR, circular mode, free scroll, and virtual scrolling. The project provides a core library (@egjs/flicking), a plugin system (@egjs/flicking-plugins) for effects like AutoPlay and Parallax, and official wrappers for React (@egjs/react-flicking) and Vue 3 (@egjs/vue3-flicking).

Tokens
60.8K
Snippets
161
Records
320
Agent score
83%

What's inside egjs-flicking

  1. Overview of Flicking Packages

    master

    Flicking is a monorepo containing the core library and framework-specific ports:

    PackageDescription
    @egjs/flickingCore carousel library
    @egjs/flicking-pluginsReadymade effects (AutoPlay, Fade, Parallax, Arrow, Pagination)
    @egjs/react-flickingReact port
    @egjs/vue3-flickingVue 3 port
  2. Understand the Documentation Versioning and Deployment Policy

    master

    The project uses a custom documentation versioning strategy instead of Docusaurus's built-in docs:version feature to avoid build bloat and duplicate files.

    Key Principles:

    • Major Versions Only: Static builds are archived only at the major version level.
    • Always Latest Minor: The docs/ directory always reflects the latest minor version; snapshots are not created for every minor/patch release.
    • Automated Release Notes: GitHub Releases are automatically converted into Docusaurus Blog posts via scripts/fetch-releases.js.
  3. Understand the API documentation generation pipeline

    master

    When running pnpm api-docs:generate, the following pipeline is executed:

    1. Type declaration files (.d.ts) are generated for packages/flicking and packages/flicking-plugins.
    2. api-extractor runs and saves flicking.api.json and flicking-plugins.api.json into the api-artifacts/ directory.
    3. The documentation generator runs to produce the final markdown files.
  4. Understand the Claude Code Harness Architecture

    master

    The Claude Code harness for this project is organized into three layers to manage rules, enforcement, and specialized workflows:

    • AGENTS.md: Core rules and entry points (always loaded, located at the root).
    • Hooks: Physical enforcement of rules (deterministic actions, configured in .claude/settings.json).
    • Skills: Workflows and domain knowledge (loaded as needed, located in .claude/skills/).
    • Subagents: Isolated context for verification tasks (located in .claude/agents/).
  5. Implement Pagination HTML structure

    master

    The pagination element must be placed inside the viewport. The standard HTML structure is:

    <div class="flicking-viewport">
      <div class="flicking-camera">
        <!-- Panels -->
      </div>
      <div class="flicking-pagination"></div>
    </div>
    <div class="flicking-viewport">
      <div class="flicking-camera">
        <!-- Panels -->
      </div>
      <div class="flicking-pagination"></div>
    </div>
  6. Create a parallax effect using indexProgress

    master

    You can implement a parallax scrolling effect by utilizing the indexProgress property from the Reactive API. This property provides the camera position as a fractional panel index, allowing you to calculate how far each panel is from the center.

    To achieve the effect, calculate a childProgress for each panel using the formula: childProgress = panelIndex - indexProgress.

    You can then map this value to visual properties:

    1. Horizontal Offset: Translate elements by childProgress * offset. Using different offset values for different layers creates a sense of depth.
    2. Opacity: Fade elements from 1.0 (at the current panel) to 0.0 (at adjacent panels) based on the absolute value of childProgress.

    For smoother continuous parallax transitions, use moveType: "freeScroll".

  7. Style the Flicking viewport

    master

    The viewport controls the visible area of the carousel. How you apply styles depends on your framework:

    • Vanilla JavaScript: You must manually create the .flicking-viewport element and add your custom class to it.
    • React/Vue3: The component renders as .flicking-viewport automatically. Apply your custom class directly to the <Flicking> component via className (React) or class (Vue3).
    // React example
    <Flicking className="my-carousel">
      <div className="panel">Panel 1</div>
    </Flicking>
    
    /* CSS */
    .my-carousel {
      max-width: 1200px;
      margin: 0 auto;
      border-radius: 8px;
    }
  8. Build dot pagination using the Reactive API

    master

    You can build a custom dot pagination UI that stays in sync with a Flicking carousel by using the Reactive API. This involves monitoring the current panel index and the total number of panels to render and highlight dots, then using the moveTo method to navigate when a dot is clicked.

    Implementation Logic

    1. Render dot buttons based on totalPanelCount.
    2. Highlight the dot that matches the currentPanelIndex.
    3. On dot click, call moveTo(index) to navigate to that specific panel.
    4. The currentPanelIndex updates automatically when the user drags to a new panel, ensuring the dots re-sync.
    • align: "center": Using center alignment makes pagination feel most intuitive.
    • circular: true: In circular mode, dots cycle seamlessly as the first and last panels connect.
  9. Implement 2D cross-directional carousels with CrossFlicking

    master

    Use the CrossFlicking preset class to build a 2D carousel where users swipe horizontally to switch between groups and vertically to browse items within a group.

    DOM Structure Requirements

    To function correctly, your HTML must follow this structure:

    1. A viewport element (the container).
    2. A camera element (the direct child of the viewport).
    3. Group wrappers (direct children of the camera). Each group wrapper's children become the vertical items for that group.

    Implementation Pattern

    For React and Vue, it is recommended to instantiate the core class imperatively within lifecycle hooks (useEffect or onMounted) rather than using component wrappers to avoid initialization issues.

    Note: Ensure the viewport has an explicit height, as the vertical side instances require a fixed layout height to function.

    import { CrossFlicking } from "@egjs/flicking";
    
    // Initialize the 2D carousel
    new CrossFlicking("#cross", {
      align: "prev",
      moveType: "strict",
      bound: true,
      sideOptions: { moveType: "strict", bound: true }
    });
    <div id="cross" class="flicking-viewport">
      <div class="flicking-camera">
        <!-- group: Nature -->
        <div class="group-wrapper">
          <div class="cross-panel">Forest</div>
          <div class="cross-panel">Meadow</div>
        </div>
        <!-- group: Ocean -->
        <div class="group-wrapper">
          <div class="cross-panel">Reef</div>
          <div class="cross-panel">Wave</div>
        </div>
      </div>
    </div>