TourKit
@tour-kit/checklistsHeadless

ChecklistHeadless

HeadlessChecklist component: unstyled checklist container exposing tasks, progress, and actions via render props

ChecklistHeadless

Headless component that provides checklist state and actions via render props, without any styling.

Usage

import { ChecklistHeadless } from '@tour-kit/checklists/headless';

<ChecklistHeadless checklistId="onboarding">
  {({ checklist, visibleTasks, completeTask }) => (
    <div>
      <h2>{checklist.config.title}</h2>
      {visibleTasks.map((task) => (
        <button
          key={task.config.id}
          onClick={() => completeTask(task.config.id)}
          disabled={task.locked}
        >
          {task.completed ? '✓' : '○'} {task.config.title}
        </button>
      ))}
    </div>
  )}
</ChecklistHeadless>

Props

Prop

Type

Render Props

Prop

Type

Examples

Material UI

import { Card, CardContent, Checkbox, List, ListItem } from '@mui/material';

<ChecklistHeadless checklistId="onboarding">
  {({ checklist, visibleTasks, completeTask }) => (
    <Card>
      <CardContent>
        <h2>{checklist.config.title}</h2>
        <List>
          {visibleTasks.map((task) => (
            <ListItem key={task.config.id}>
              <Checkbox
                checked={task.completed}
                disabled={task.locked}
                onChange={() => completeTask(task.config.id)}
              />
              {task.config.title}
            </ListItem>
          ))}
        </List>
      </CardContent>
    </Card>
  )}
</ChecklistHeadless>

Chakra UI

import { Box, Checkbox, Stack } from '@chakra-ui/react';

<ChecklistHeadless checklistId="onboarding">
  {({ checklist, visibleTasks, completeTask }) => (
    <Box p={4} borderWidth="1px" borderRadius="lg">
      <Heading size="md">{checklist.config.title}</Heading>
      <Stack spacing={3} mt={4}>
        {visibleTasks.map((task) => (
          <Checkbox
            key={task.config.id}
            isChecked={task.completed}
            isDisabled={task.locked}
            onChange={() => completeTask(task.config.id)}
          >
            {task.config.title}
          </Checkbox>
        ))}
      </Stack>
    </Box>
  )}
</ChecklistHeadless>

Custom Animations

import { AnimatePresence, motion } from 'framer-motion';

<ChecklistHeadless checklistId="onboarding">
  {({ visibleTasks, completeTask, progress }) => (
    <div>
      <motion.div
        initial={{ width: 0 }}
        animate={{ width: `${progress.percentage}%` }}
        className="progress-bar"
      />

      <AnimatePresence>
        {visibleTasks.map((task) => (
          <motion.div
            key={task.config.id}
            initial={{ opacity: 0, x: -20 }}
            animate={{ opacity: 1, x: 0 }}
            exit={{ opacity: 0, x: 20 }}
          >
            <button onClick={() => completeTask(task.config.id)}>
              {task.config.title}
            </button>
          </motion.div>
        ))}
      </AnimatePresence>
    </div>
  )}
</ChecklistHeadless>

On this page