Files
tolaria/src/hooks/useZoom.ts
Luca Rossi 384cffec48 feat: zoom in/out keyboard shortcuts (Cmd+=, Cmd+-, Cmd+0) (#134)
* feat: zoom in/out keyboard shortcuts (Cmd+=, Cmd+-, Cmd+0)

Add zoom control with keyboard shortcuts, native menu items, command
palette integration, and StatusBar zoom indicator with localStorage
persistence (80-150%, 10% step).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: add zoom-shortcuts design file with StatusBar zoom indicator

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* design: zoom-shortcuts — StatusBar zoom indicator + Command Palette entries

---------

Co-authored-by: Test <test@test.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 12:41:57 +01:00

62 lines
1.6 KiB
TypeScript

import { useState, useEffect, useCallback } from 'react'
const ZOOM_KEY = 'laputa:zoom-level'
const MIN_ZOOM = 80
const MAX_ZOOM = 150
const STEP = 10
const DEFAULT_ZOOM = 100
function loadPersistedZoom(): number {
try {
const stored = localStorage.getItem(ZOOM_KEY)
if (stored !== null) {
const val = Number(stored)
if (val >= MIN_ZOOM && val <= MAX_ZOOM && val % STEP === 0) return val
}
} catch { /* localStorage unavailable */ }
return DEFAULT_ZOOM
}
function applyZoomToDocument(level: number): void {
document.documentElement.style.setProperty('zoom', `${level}%`)
}
function persistZoom(level: number): void {
try { localStorage.setItem(ZOOM_KEY, String(level)) } catch { /* ignore */ }
}
export function useZoom() {
const [zoomLevel, setZoomLevel] = useState(loadPersistedZoom)
// Apply persisted zoom on mount
useEffect(() => {
applyZoomToDocument(zoomLevel)
}, []) // eslint-disable-line react-hooks/exhaustive-deps -- only on mount
const zoomIn = useCallback(() => {
setZoomLevel(prev => {
const next = Math.min(MAX_ZOOM, prev + STEP)
applyZoomToDocument(next)
persistZoom(next)
return next
})
}, [])
const zoomOut = useCallback(() => {
setZoomLevel(prev => {
const next = Math.max(MIN_ZOOM, prev - STEP)
applyZoomToDocument(next)
persistZoom(next)
return next
})
}, [])
const zoomReset = useCallback(() => {
setZoomLevel(DEFAULT_ZOOM)
applyZoomToDocument(DEFAULT_ZOOM)
persistZoom(DEFAULT_ZOOM)
}, [])
return { zoomLevel, zoomIn, zoomOut, zoomReset }
}