# Tech Architecture Document ## Stack | Layer | Choice | Rationale | |---|---|---| | Language | TypeScript | Type safety for arithmetic logic; catches operand/type bugs at compile time. | | UI Framework | React 18 (Vite) | Lightweight component model; Vite gives fast dev HMR and a zero-config static build output. | | Styling | CSS Modules | Scoped styles, no runtime overhead, easy responsive layout. | | Testing | Vitest + React Testing Library | Co-located with Vite; unit tests for arithmetic logic, component interaction tests for UI. | | Build / Deploy | Vite `build` → static files | Produces a plain `dist/` folder deployable to any static host (Netlify, GitHub Pages, S3, etc.). | | CI | GitHub Actions | Lint, type-check, test, and build on every push; deploy `dist/` on merge to `main`. | --- ## Components ```mermaid graph TD App["App (root)"] Display["Display\n• shows current operand A, operator, operand B\n• shows result or error"] OperandInput["OperandInput × 2\n• controlled numeric text field\n• accepts decimal & negative values"] OperatorSelector["OperatorSelector\n• four buttons: + − × ÷\n• highlights active operator"] ActionBar["ActionBar\n• = (Calculate) button\n• C (Clear) button"] Calculator["calculator.ts\n(pure logic module)"] App --> Display App --> OperandInput App --> OperatorSelector App --> ActionBar App -- "calls" --> Calculator ``` ### Component responsibilities | Component | Responsibility | |---|---| | `App` | Owns all state (operandA, operandB, operator, result, error). Wires child events to state updates and calls the calculator module. | | `Display` | Pure presentational; renders the current expression and result/error string. | | `OperandInput` | Controlled `` that accepts numeric strings including decimals; reports `onChange` to `App`. | | `OperatorSelector` | Renders four operator buttons; reports `onSelect` to `App`. | | `ActionBar` | Renders **=** and **C** buttons; fires `onCalculate` / `onClear` callbacks. | | `calculator.ts` | Pure-function module: `calculate(a: number, op: Operator, b: number): number \| CalcError`. No DOM dependency; fully unit-testable. | --- ## Data Model All state is ephemeral (in-memory React state). There is no database, localStorage, or network persistence. ```mermaid erDiagram APP_STATE { string operandA "raw input string for operand A" string operandB "raw input string for operand B" Operator operator "'+' | '-' | '*' | '/'" number result "computed result (null until calculated)" string errorMessage "non-null when a calc error occurs" } ``` ### Type definitions (TypeScript) ```ts type Operator = '+' | '-' | '*' | '/'; type CalcError = | { kind: 'DIVISION_BY_ZERO' } | { kind: 'INVALID_INPUT'; field: 'a' | 'b' }; type CalcResult = { ok: true; value: number } | { ok: false; error: CalcError }; ``` `calculator.ts` exports a single function: ```ts export function calculate(a: number, op: Operator, b: number): CalcResult; ``` --- ## Integrations This version has **no external integrations**. All computation runs entirely in the browser. | Integration | Status | Notes | |---|---|---| | Backend API | None | All arithmetic is client-side; NFR-6 (static deployability) rules out a server runtime. | | Authentication service | None | No accounts or sessions (Assumption 2). | | Analytics / telemetry | None | Out of scope for v1; can be added later without architectural change. | | CDN / static host | Optional | Any static host works (`dist/` is self-contained). Recommended: Netlify or GitHub Pages for zero-cost deployment. | --- ## Non-Functional Requirements | ID | NFR | Architectural approach | |---|---|---| | NFR-1 | Result ≤ 100 ms | All logic runs synchronously in the browser; no network round-trip. Vite-bundled output is ≤ 50 kB gzipped. | | NFR-2 | Responsive (desktop + mobile) | CSS Modules with a fluid grid; `OperandInput` and `OperatorSelector` reflow to single-column below 480 px. | | NFR-3 | WCAG 2.1 AA | Semantic HTML (`