gluestack-ui logo
Get Updates
Prompt to React Native UI
Home
Components
Hooks
Apps
MCP Server
Guides
Home
Overview
IntroductionQuick Start
Getting Started
InstallationTooling SetupVS Code ExtensionsFigma UI KitCLIgluestack-ui-nativewind-utils
Core Concepts
AccessibilityUniversal
Performance
Benchmarks
Theme Configuration
Default TokensCustomizing ThemeDark Mode
Components
All Components
Typography
HeadingrscTextrsc
Layout
BoxrscCenterrscDividerHStackrscVStackrscGridalpha, rsc
Feedback
AlertProgressSpinnerToast
Data Display
BadgeCardrscTablealpha
Forms
ButtonCheckboxFormControlInputLinkPressableRadioSelectSliderSwitchTextarea
Overlay
AlertDialogDrawerMenuModalPopoverPortalTooltip
Disclosure
ActionsheetAccordionBottomSheetalpha
Media And Icons
AvatarImageIconrsc
Others
FabSkeletonalpha, rsc
Hooks
useBreakPointValue
useMediaQuery
Apps
Dashboard App
Kitchensink App
Todo App
Starter Kit
MCP Server
MCP Server
Guides
Recipes
LinearGradient
Tutorials
Building Ecommerce App
More
Upgrade to v2Upgrade to v3FAQsReleasesRoadmapTroubleshootingDiscord FAQs

Todo App

This Todo App is built using
gluestack-ui v2
.

TodoApp.tsx

import React, { useState } from 'react';
import { VStack } from '@/components/ui/vstack';
import { FormControl } from '@/components/ui/form-control';
import { Input, InputField, InputIcon } from '@/components/ui/input';
import { AddIcon } from '@/components/ui/icon';
import { Pressable } from '@/components/ui/pressable';
import { defaultTodos } from './todo';
import TodoContainer, { Todo } from './todoContainer';

import { nanoid } from 'nanoid';

const TodoApp = () => {
  const [item, setItem] = useState('');
  const [todos, setTodos] = useState<Todo[]>(defaultTodos);

  const addTodo = (task: string) => {
    const lastTodo = todos[todos?.length - 1];
    if (lastTodo?.task !== '' && task !== '') {
      setTodos([
        ...todos,
        {
          id: nanoid(),
          task: task,
          completed: false,
        },
      ]);
      setItem('');
    }
  };

  const toggleTodo = (id: string) => {
    const updatedTodos = todos?.map((todo) => {
      if (todo.id === id) {
        todo.completed = !todo.completed;
      }
      return todo;
    });
    setTodos(updatedTodos);
  };

  const deleteTodo = (id: string) => {
    const updatedTodos = todos.filter((todo) => todo.id !== id);
    setTodos(updatedTodos);
  };

  return (
    
    <VStack className="flex-1 bg-secondary-100 md:bg-secondary-0 md:items-center md:justify-center ">
      <VStack className="rounded-md bg-secondary-100 md:h-[500px] md:w-[700px]">
        <FormControl className="my-4">
          <Input variant="underlined" size="sm" className="mx-6 my-2">
            <InputField
              placeholder="What is your next task?"
              value={item}
              onChangeText={(value) => setItem(value)}
              onSubmitEditing={() => addTodo(item)}
            />
            <Pressable onPress={() => addTodo(item)}>
              <InputIcon as={AddIcon} className="cursor-pointer h-3 w-3" />
            </Pressable>
          </Input>
        </FormControl>
        {todos?.map((todo: Todo, index: number) => (
          <TodoContainer
            key={index}
            todo={todo}
            toggleTodo={toggleTodo}
            deleteTodo={deleteTodo}
          />
        ))}
      </VStack>
    </VStack>
    
  );
};

export default TodoApp;

TodoContainer.tsx

import React from 'react';
import { HStack } from '@/components/ui/hstack';
import { Pressable } from '@/components/ui/pressable';
import { CheckIcon, CloseIcon, Icon } from '@/components/ui/icon';
import {
  Checkbox,
  CheckboxIcon,
  CheckboxIndicator,
  CheckboxLabel,
} from '@/components/ui/checkbox';

export interface Todo {
  id: string;
  task: string;
  completed: boolean;
}

const TodoContainer = ({
  todo,
  toggleTodo,
  deleteTodo,
  ...props
}: {
  todo: Todo;
  toggleTodo: (id: string) => void;
  deleteTodo: (id: string) => void;
}) => {
  return (
    <HStack
      {...props}
      className="rounded-md hover:bg-secondary-200 justify-between items-center"
    >
      <Checkbox
        onChange={(_isChecked) => toggleTodo(todo.id)}
        size="sm"
        aria-label={todo.task}
        value={todo.task}
        isChecked={todo.completed}
        className="pl-6 py-2 flex-1"
      >
        <CheckboxIndicator>
          <CheckboxIcon as={CheckIcon} />
        </CheckboxIndicator>
        <CheckboxLabel className="text-sm data-[checked=true]:line-through">
          {todo.task}
        </CheckboxLabel>
      </Checkbox>
      <Pressable className="pr-6 py-2" onPress={() => deleteTodo(todo.id)}>
        {({ hovered }: { hovered: boolean }) => {
          return (
            <Icon
              as={CloseIcon}
              size="xs"
              className={hovered ? 'stroke-red-400' : 'stroke-primary-50'}
            />
          );
        }}
      </Pressable>
    </HStack>
  );
};

export default TodoContainer;
Edit this page on GitHub
Go backKitchensink App
Up nextStarter Kit
Go backKitchensink App
Up nextStarter Kit