Skip to content

About

NPM Library : Drag & drop customizable component (Kanban Board) for react native application, using smooth reanimated animation and UI Thread render.

Topics

Resources

Stars

10 stars

Watchers

0 watching

Forks

Latest commit

Β 

History

30 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

React Native Expo Kanban Board

πŸ“‹ Interactive Kanban Board for React Native

A feature-rich, customizable Kanban board component built for Expo and React Native. Perfect for task management, sales pipelines, project tracking, and any workflow that benefits from visual organization.


✨ Features

πŸ‘† Drag-and-Drop Smooth card movement between columns powered by Reanimated + Gesture Handler.
🎨 Fully Customizable Colors, styles, and behavior tailored to your app via style props and render functions.
πŸ“± Responsive Works flawlessly across iOS and Android mobile devices.
πŸ”’ Real-time Counts Automatic tracking of items per column.
♻️ CRUD Built-in support for moving items across columns via onDragEnd.
🟦 TypeScript Fully typed components and props.
⚑ Performance Built with Reanimated for buttery-smooth 60fps interactions.

πŸš€ Installation

npm install react-native-expo-kanban react-native-reanimated

react-native-reanimated is required for drag animations:
https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started


πŸ›  Usage

1. Define your columns and cards

import ReactNativeKanbanBoard from "react-native-expo-kanban";
import {
  KanbanBoardProps,
  ItemParams,
  HeaderParams,
} from "react-native-expo-kanban";

const columnData: KanbanBoardProps<ItemParams, HeaderParams>["columnData"] = [
  {
    header: { title: "Enquiry", subtitle: "Target 20 leads" },
    items: [
      {
        id: "101",
        first_name: "Bhageerathan",
        last_name: "Pillai",
        email: "Bhageerathan@Pillai.com",
        phone: "+1 555-123-4567",
        company: "Muthalali Inc.",
        created_on: new Date().toISOString(),
        priority: "high",
        status: "New",
        notes: "Interested in premium package",
        assigned_to: {
          first_name: "Ramanan",
          last_name: "",
          profile_pic: null,
        },
      },
      {
        id: "102",
        first_name: "Kittunni",
        last_name: "",
        email: "kittunni@kilukkam.com",
        phone: "+1 555-123-4567",
        company: "Army Inc.",
        created_on: new Date().toISOString(),
        priority: "high",
        status: "New",
        notes: "Interested in premium package",
        assigned_to: {
          first_name: "Pankajakshan",
          last_name: "Pillai",
          profile_pic: null,
        },
      },
    ],
  },
  {
    header: { title: "Interested", subtitle: "Make sure fixed" },
    items: [
      {
        id: "104",
        first_name: "Shaji",
        last_name: "Pappan",
        email: "ShajiPappan@Aadu.com",
        phone: "+1 555-123-4567",
        company: "Kalasamithi Inc.",
        created_on: new Date().toISOString(),
        priority: "high",
        status: "New",
        notes: "Interested in premium package",
        assigned_to: {
          first_name: "Eppan",
          last_name: "Pappachi",
          profile_pic: null,
        },
      },
    ],
  },
];

2. Render item and header

const renderItem = (item: any) => (
  <View style={styles.card}>
    <Text>{item.first_name}</Text>
    <Text>{item.email}</Text>
  </View>
);

const renderHeader = (header: any) => (
  <View style={styles.header}>
    <Text>{header.title}</Text>
    <Text>{header.subtitle}</Text>
  </View>
);

3. Render the board

<ReactNativeKanbanBoard
  columnData={columnData}
  renderItem={renderItem}
  renderHeader={renderHeader}
  columnHeaderStyle={styles.columnHeader}
  columnContainerStyle={styles.columnContainer}
  gapBetweenColumns={12}
  columnWidth={SCREEN_WIDTH * 0.85}
  columnContainerStyleOnDrag={styles.columnActive}
  onDragEnd={({ fromColumnIndex, toColumnIndex, itemId }) => {
    // update your state here and pass new columnData back
  }}
/>

πŸ“‹ Props

Prop Type Default Required Description
columnData columnData<T, K>[] [] βœ… Array of columns, each with header and items.
renderItem (props: T, isDragged?: boolean) => JSX.Element β€” βœ… Renders each card inside a column.
renderHeader (props: K) => JSX.Element β€” βœ… Renders the header for each column.
onDragEnd (params: { fromColumnIndex, toColumnIndex, itemId }) => void undefined ❌ Fired when an item is dropped into a new column.
columnHeaderStyle ViewStyle {} ❌ Style for the column header.
columnContainerStyle ViewStyle {} ❌ Style for the column container.
columnContainerStyleOnDrag ViewStyle 0.7 ❌ Style applied while an item is being dragged into the column.
gapBetweenColumns number 8 ❌ Horizontal gap between columns.
columnWidth number screen width Γ— 0.8 ❌ Width of each column.

πŸ— Architecture

The package is nine source files under src/. Data flows one way: the board reports indices/ids on drop, and the parent produces the new columns.

Entry point β€” src/index.tsx

Board container generic over T extends ItemType and K. Computes screen constants, renders one horizontal FlatList per column, wires the drag gesture, and draws the floating preview.

Components

File Role
src/index.tsx Board container β€” column FlatList, drag wiring, floating preview
src/components/DataCard.tsx Memoized Pressable card wrapper; measures itself on layout

Hooks

Hook Role
useDragGesture Gesture lifecycle and drop decisions; calls onDragEnd on release
useColumnPagination Throttled horizontal paging (left / right / re-center)
useLayoutAnimation LayoutAnimation presets with Android workaround

Utilities β€” src/utils/DraggedCardContext.tsx

React context exposing the dragged card and shared drag coordinates (dragX, dragY). Provided by the board, consumed by cards/overlays via useDragContext.

Data flow

long press
  β†’ DataCard.onLongPress
  β†’ measureInWindow()
  β†’ setDragCard({ props, x, y, width, columnIndex, id })
  β†’ gesture activates on touch move
  β†’ dragX / dragY shared values update
  β†’ near edge? paginate('left' | 'right')
  β†’ release
  β†’ drop()
  β†’ onDragEnd({ fromColumnIndex, toColumnIndex, itemId })

The board never mutates columnData. It reports the indices and item id, then waits for the parent to produce new columns β€” keeping the component predictable and compatible with any state library.

Types β€” src/types.ts

KanbanBoardProps, columnDataType, ItemType, DraggedCardProps, and example HeaderParams/ItemParams shapes.


πŸ“– Documentation

Full architecture, props, types, hooks, and examples are hosted at:
πŸ‘‰ https://rnkanban.vercel.app


🀝 Contributing

Contributions, issues, and feature requests are welcome!
Feel free to open a PR or file an issue on GitHub.


πŸ“„ License

MIT Β© Naveen Mathramkott


Built with ❀️ for the React Native community

About

NPM Library : Drag & drop customizable component (Kanban Board) for react native application, using smooth reanimated animation and UI Thread render.

Topics

Resources

Stars

10 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages