Skip to content
xpodevPublic

About

Yes, it's a ToDo app.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Todo

A fast, bilingual (English / עברית) todo app built with React 19 and TypeScript.

  • English and Hebrew, with full right-to-left layout. User text uses dir="auto", so mixed-language tasks render correctly.
  • Themes: System, Light, Dark, Midnight, Paper, Forest, High contrast. There is also a compact density setting.
  • Lists and smart views: Today (includes overdue), Upcoming, Overdue and All, with live counts.
  • Quick add with inline syntax: Call Dana tomorrow !high #work. The parsed date, priority and tags show as chips while you type.
    • Priority: !high !med !low (or !!! !! !). Hebrew: !גבוה !בינוני !נמוך.
    • Tags: #anything.
    • Due date: today, tomorrow, friday, @mon, +3d, +2w, 2026-10-12. Hebrew: היום, מחר, מחרתיים, @שישי.
  • Details panel: title, due date with quick picks, priority, list, tags, subtasks with progress, and notes. It docks beside the list on wide screens and becomes a drawer, or a full-screen sheet on phones.
  • Search across titles, notes, tags and subtasks, with match highlighting.
  • Filters and sorting:
    • filter: All / Active / Completed;
    • sort: Manual / Due date / Priority / Newest / A–Z.
  • Drag and drop:
    • drag to reorder tasks (manual sort);
    • drop tasks onto a list in the sidebar to move them;
    • drag the selection to move several tasks at once.
  • Multi-select: Shift-click or Ctrl-click, then complete, move or delete in bulk.
  • Undo for every change: a toast offers Undo, and Ctrl+Z works too.
  • Keyboard-first: press ? in the app for the full list. Highlights:
    • N new task, / search;
    • J/K move between tasks, X complete;
    • Enter open details, E rename;
    • Alt+↑/↓ reorder, 1–9 jump to a view.
  • Export and import JSON backups, merging or replacing.
  • Mobile:
    • the sidebar becomes a slide-in drawer and the add bar sits at the bottom of the screen;
    • tap targets are large and the layout respects safe areas;
    • installable as a PWA, with offline support through a service worker.
  • Multi-tab sync: changes in one tab show up in the others.

Getting started

pnpm install
pnpm dev
Script What it does
pnpm dev Vite dev server
pnpm build Type-check and build to dist/
pnpm build:static Build the static site (used by the deploy job)
pnpm preview Serve the production build
pnpm test Vitest (unit and integration)
pnpm lint ESLint
pnpm typecheck tsc -b

Static hosting

The build has no server requirements and works from any URL path, for example https://example.com/tools/todo/:

  • vite.config.ts sets base: './', so every asset URL is relative.
  • There is no client-side router. The current view lives in the URL hash (#/today, #/list/<id>), so deep links and the back button work without rewrite rules.
  • The service worker and manifest are registered relative to the page.

CI (.github/workflows/ci.yml) lints, builds and tests every push. Pushes to main are deployed via Site Manager.

Architecture

src/
  data/          Domain types, the TodoRepository interface, and its localStorage implementation
  state/         TodoStore (optimistic updates + undo), view/filter/sort logic
  i18n/          Typed dictionaries (en is the source of truth; he must match it)
  settings/      Persisted UI preferences (language, theme, density, sort, …)
  theme/         Theme ids and swatches; colors live in styles/themes.css
  components/    UI, one folder per component with a CSS module
  utils/         Dates, quick-add parser, search highlighting

Data source

The UI talks only to the async TodoRepository interface in src/data/TodoRepository.ts. The only concrete implementation is LocalStorageTodoRepository, which:

  • stores everything under a single versioned key, with migrations;
  • recovers from corrupt data by backing up the bad payload under …:corrupt:<timestamp> and starting fresh;
  • syncs across tabs through the storage event.

To add another backend (REST, IndexedDB, …):

  1. Implement TodoRepository. subscribe is optional and lets the backend push external changes.
  2. Construct it in src/main.tsx. That is the only place that knows which implementation is in use.

Themes

Every color is a CSS custom property, defined per theme in src/styles/themes.css. To add a theme:

  1. Add a :root[data-theme='…'] block there.
  2. Add its id to THEME_IDS and THEME_SWATCHES in src/theme/themes.ts.
  3. Add a name to both dictionaries.

Translations

src/i18n/en.ts defines the keys. he.ts is typed against it, so a missing or extra key is a compile error. Plurals use Intl.PluralRules categories (one / two / other …).

Layout uses CSS logical properties throughout (margin-inline-start, inset-inline-end, …), so RTL needs almost no special casing.

About

Yes, it's a ToDo app.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages