A sleek iPhone‑style calculator built with Next.js (App Router) and Material UI.
When you press =, a right‑side History Drawer opens automatically, and clicking a history item immediately restores its result to the display so you can continue calculating from there.
Default theme is Dark. Includes round keypad, live expression above result, Light/Dark/Night theme toggle, and large button typography.
- iPhone‑like round keys (square size with fully rounded corners)
- History auto‑opens on
=(also opens by tapping the display) - Click history ⇒ continue from that result instantly
- Live expression shown above the main result
- 3 Themes: Light / Dark (default) / Night (navy tone)
- Responsive layout powered by MUI Grid
- History persisted in LocalStorage
- Keyboard input:
0–9,.,+ - * /,Enter/=(calculate),Esc(AC),%
- Next.js 15 (App Router)
- React 18
- Material UI v5 (
@mui/material,@mui/icons-material,@emotion/*) - TypeScript
pnpm install # or: npm i / yarn
pnpm devProduction:
pnpm build && pnpm startTip: If you see an icon‑related error, install icons with:
pnpm add @mui/icons-material
app/
layout.tsx # Server component root layout + ThemeRegistry
page.tsx # Entry renders the client Calculator
globals.css # Global styles (type scale, resets, etc.)
components/
Calculator.tsx # iPhone keypad, chained ops, history/display logic
ThemeRegistry.tsx # MUI ThemeProvider, persists theme in localStorage
ThemeToggle.tsx # Light/Dark/Night toggle UI
theme.ts # getDesignTokens: palettes/shapes/typo for 3 themes
next.config.mjs # experimental.optimizePackageImports config
package.json # scripts & deps
tsconfig.json # TypeScript settings
-
State
display: current value shownprev: previous operandop: current operator (+ | - | × | ÷ | null)overwrite: whether next input overwritesdisplayhistory: calculation history (saved/loaded via LocalStorage)historyOpen: right drawer visibilityexpr: text for the live “current expression”
-
Key Behaviors
setOperator(op): chained operator handling (compute previous, queue next)equals(): compute → push to history → open Drawer → resetexprapplyHistory(item): clicking a history item sets its result todisplay- Global keyboard handling via
keydown
-
UI Notes
- Round keys:
borderRadius: '9999px',aspectRatio: '1 / 1' - Large labels:
xs 28px / sm 34px / md 38px,fontWeight: 700 - Top display:
expr(caption) +display(h3 weight/scale)
- Round keys:
- Supports Light/Dark/Night modes
- Default is Dark (when
calc-themenot found in LocalStorage)
- Defines palette for Dark/Night backgrounds/text/primary
- Orange primary for operator keys:
primary.main = #ff9f0a
- Button label size: tweak
sx.fontSizeinKey(insideCalculator.tsx) - Button height: adjust
sx.minHeight - Theme colors: edit
getDesignTokens()intheme.ts - Max history length: change
history.slice(0, 200) - Number formatting: extend
formatNumber()for currency/fixed decimals
- v1 (Initial)
- Next.js + MUI calculator scaffold
- History Drawer, LocalStorage persistence, theme toggle, keyboard input
- Fixes
- Resolved icon import error by adding
@mui/icons-material - Migrated deprecated
ListItem button⇒ListItemButton(MUI v5)
- Resolved icon import error by adding
- UI Enhancements
- Dark mode by default
- Uniform round buttons (including
0key) - Live expression above result
- iOS‑like orange for operator keys
- Readability
- Larger, heavier button typography
- Increased minimum button height
- Icon module error
- Install:
pnpm add @mui/icons-material
- Install:
- TypeScript warnings
- Use
ListItemButtoninstead ofListItem buttonin MUI v5.
- Use
- Digits & dot:
0–9,. - Operators:
+ - * / - Calculate:
Enteror= - All Clear:
Esc - Percent:
%
Demo / sample use. Replace with your project’s license as needed.