Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 50 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,15 @@ yarn preview # Preview production build
yarn lint # Run ESLint
```

No test runner is configured yet. When adding tests, check `_specs/template.md` for the expected pattern — specs call for a `./tests` folder.
Tests use **Vitest** + `@testing-library/react`. Run them with:

```bash
yarn test # watch mode
yarn test --run # single run (CI)
yarn test:ui # Vitest browser UI
```

Test files live in `./tests/`. Use `renderHook` + `act` for hook tests.

## Environment

Expand Down Expand Up @@ -51,6 +59,35 @@ All term data lives in `src/data/*.json`. Each entry is:

Categories are defined in `src/components/TermInput.jsx` as a `CATEGORIES` array. Each entry maps an icon, title, description, and a reference to a JSON data file. To add a new category, add a JSON file to `src/data/` and add an entry to this array.

### Session components

`FlashcardSession` is the main session controller. It owns all playback state (`currentIndex`, `playing`, `repeat`, `playbackRate`, etc.) and renders one of five paths based on `useLayoutMode()`:

| Layout mode | Shell component |
|---|---|
| `phone-portrait` | `PhonePortraitLayout` |
| `phone-landscape` | `PhoneLandscapeLayout` |
| `tablet-portrait` | `TabletPortraitLayout` |
| `tablet-landscape` | `TabletLandscapeLayout` |
| `desktop` | Inline JSX in `FlashcardSession` |

Layout shells are purely presentational — they receive named slot props (`video`, `nav`, `termList`, `positionLabel`, `termText`, `termBg`, `termFg`, `onBack`, `swipeHandlers`, `title`, `description`) and have no state of their own.

The `termList` slot differs by context: on all mobile layouts (`isMobileLayout`) it is a bottom-sheet `.term-drawer` element (hidden until the "📋 Terms" nav button is tapped, CSS breakpoint `max-width: 1023px`); on desktop it is rendered inline as a sidebar.

**`FlashcardNav`** (`src/components/FlashcardNav.jsx`) — nav button bar (prev, next, shuffle, terms drawer toggle, autoplay, player-controls toggle, play/pause, speed, repeat). Pass `onOpenTerms={undefined}` to hide the terms button (desktop only; all mobile layouts pass a callback that opens the term drawer).

**`FlashcardPlayer`** (`src/components/FlashcardPlayer.jsx`) — thin wrapper around `react-player` with standardised props (`url`, `playing`, `loop`, `autoPlay`, `controls`, `playbackRate`, `onPlay`, `onPause`, `onEnded`, `onError`).

### Hooks

- `src/hooks/useLayoutMode.js` — returns the current layout mode string. Uses `screen.orientation.type` when available; falls back to `innerWidth > innerHeight`. Re-evaluates on `resize`, `orientationchange`, and `screen.orientation change`.
- `src/hooks/useSwipe.js` — returns `{ onTouchStart, onTouchEnd }` for spread onto a container. 50 px threshold; swipe-left → next, swipe-right → prev.

### Constants

- `src/constants/breakpoints.js` — `PHONE_MAX_WIDTH = 767`, `TABLET_MAX_WIDTH = 1023`. Use these instead of magic numbers.

### Utilities

- `src/utils/contrastColor.js` — given a hex background color, returns `#08060d` or `#ffffff` for legible text (used by `FlashcardSession` for card text color)
Expand All @@ -66,10 +103,21 @@ Categories are defined in `src/components/TermInput.jsx` as a `CATEGORIES` array
- Dark mode overrides are in `src/index.css` under `@media (prefers-color-scheme: dark)`
- All component styles live in `src/App.css` (no per-component CSS files)

**Per-layout CSS custom properties** — each layout shell block opens with a custom-property block for easy tweaking without touching shared styles. Prefixes:

| Prefix | Layout |
|---|---|
| `--lpp-` | phone-portrait |
| `--lpl-` | phone-landscape |
| `--ltp-` | tablet-portrait |
| `--ltl-` | tablet-landscape |

The old `.fcs-landscape` block in `App.css` is deprecated (commented) — it has been superseded by the layout shells and should be removed in a follow-up.

## Stack

- React 19, no router or state management library
- Vite 8 with `@vitejs/plugin-react` (Babel/Oxc transform, not SWC)
- Vite 8 with `@vitejs/plugin-react` (Babel/Oxc transform, not SWC); `base: "/asl"` set in `vite.config.js` for subdirectory deployment
- Plain CSS (`src/App.css`, `src/index.css`) — no CSS framework
- `react-hot-toast` — toast notifications (Toaster mounted in App)
- `react-player` — video playback in FlashcardSession (replaces iframe)
Expand Down
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,29 @@ The React Compiler is not enabled on this template because of its impact on dev
## Expanding the ESLint configuration

If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project.

### FTP Deployment

asl@lacinaslair.com

16)0c,L#E$n&A%U=

/home/lacinasl/lacinaslair.com/asl

### Mobile device resolutions

iPhone 14 Pro
393 x 665
734 x 337

768 x 904
1024 x 648

# Classmates

Stacy Maxwell - sr@stacyrosevear.com
Brianne O'Reilly - oreilly410@gmail.com
Lindsey Bogovich
Brittany Phillips
Karen McElrath
Cherie
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"dev": "vite --host",
"build": "vite build",
"lint": "eslint .",
"preview": "vite preview",
Expand Down
Loading
Loading