# 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 (`