Download frontend/src/components/DisplayMenu.jsx from kiyer/beacon: direct link, hf CLI and curl.
- Browser
- Download file 4.53 kB
-
https://huggingface.co/spaces/kiyer/beacon/resolve/main/frontend/src/components/DisplayMenu.jsx
- Command line
-
hf download hf://spaces/kiyer/beacon/frontend/src/components/DisplayMenu.jsx
-
curl -L -o DisplayMenu.jsx https://huggingface.co/spaces/kiyer/beacon/resolve/main/frontend/src/components/DisplayMenu.jsx
4.53 kB
| import React from 'react'; | |
| // DisplayMenu — display preferences popover. | |
| // Mirrors AnnotatorPanel chrome: ap-pop-backdrop + ap-settings panel. | |
| // Controls four settings exposed to the user: | |
| // 1. Palette (three swatch chips) | |
| // 2. Body size (range slider) | |
| // 3. Justify (checkbox) | |
| // 4. Notes side (two chips: left / right) | |
| // | |
| // All other tweak fields (dropCaps, showScores) are preserved in the parent | |
| // tweaks object but not exposed here. | |
| export const PALETTES = [ | |
| { label: 'Parchment', value: ['#f6f1e6', '#2b2418', '#9a3b20'] }, | |
| { label: 'Ivory', value: ['#fbf8f1', '#231f17', '#8a5a18'] }, | |
| { label: 'Chalk', value: ['#f3f2ee', '#22241f', '#3f5a96'] }, | |
| ]; | |
| export default function DisplayMenu({ tweaks, onChange, onClose }) { | |
| const set = (patch) => onChange({ ...tweaks, ...patch }); | |
| React.useEffect(() => { | |
| const onKey = (e) => { if (e.key === 'Escape') onClose(); }; | |
| window.addEventListener('keydown', onKey); | |
| return () => window.removeEventListener('keydown', onKey); | |
| }, [onClose]); | |
| // Determine which palette is active by matching all three colour values. | |
| const activePalIdx = PALETTES.findIndex( | |
| (p) => | |
| p.value[0] === tweaks.paperPalette[0] && | |
| p.value[1] === tweaks.paperPalette[1] && | |
| p.value[2] === tweaks.paperPalette[2], | |
| ); | |
| return ( | |
| <div> | |
| <div className="ap-pop-backdrop" onClick={onClose}></div> | |
| <div className="ap-settings" data-screen-label="Display settings"> | |
| <div className="ap-settings-title">Display</div> | |
| <div className="ap-settings-sub">paper, type, and margin layout</div> | |
| {/* Palette */} | |
| <div className="ap-field"> | |
| <label className="ap-field-label">Palette</label> | |
| <div className="ap-provider-row"> | |
| {PALETTES.map((pal, i) => ( | |
| <button | |
| key={pal.label} | |
| className={'ap-provider' + (activePalIdx === i ? ' is-active' : '')} | |
| onClick={() => set({ paperPalette: pal.value })} | |
| title={pal.value.join(' · ')} | |
| style={{ | |
| background: activePalIdx === i ? undefined : pal.value[0], | |
| color: activePalIdx === i ? undefined : pal.value[1], | |
| borderColor: activePalIdx === i ? undefined : pal.value[1] + '44', | |
| }} | |
| > | |
| {pal.label} | |
| </button> | |
| ))} | |
| </div> | |
| </div> | |
| {/* Body size */} | |
| <div className="ap-field"> | |
| <label className="ap-field-label"> | |
| Body size — {tweaks.bodySize}px | |
| </label> | |
| <input | |
| type="range" | |
| min={16} | |
| max={23} | |
| step={0.5} | |
| value={tweaks.bodySize} | |
| onChange={(e) => set({ bodySize: Number(e.target.value) })} | |
| style={{ width: '100%', marginTop: '6px' }} | |
| /> | |
| </div> | |
| {/* Retrieved works */} | |
| <div className="ap-field"> | |
| <label className="ap-field-label"> | |
| Retrieved works — {tweaks.litCount ?? 3} | |
| </label> | |
| <input | |
| type="range" | |
| min={3} | |
| max={10} | |
| step={1} | |
| value={tweaks.litCount ?? 3} | |
| onChange={(e) => set({ litCount: Number(e.target.value) })} | |
| style={{ width: '100%', marginTop: '6px' }} | |
| /> | |
| </div> | |
| {/* Justify */} | |
| <div className="ap-field"> | |
| <label className="ap-field-label" style={{ display: 'flex', alignItems: 'center', gap: '8px', cursor: 'pointer' }}> | |
| <input | |
| type="checkbox" | |
| checked={tweaks.justify} | |
| onChange={(e) => set({ justify: e.target.checked })} | |
| /> | |
| Justified text | |
| </label> | |
| </div> | |
| {/* Notes side */} | |
| <div className="ap-field"> | |
| <label className="ap-field-label">Notes side</label> | |
| <div className="ap-provider-row"> | |
| {['right', 'left'].map((side) => ( | |
| <button | |
| key={side} | |
| className={'ap-provider' + (tweaks.notesSide === side ? ' is-active' : '')} | |
| onClick={() => set({ notesSide: side })} | |
| > | |
| {side} | |
| </button> | |
| ))} | |
| </div> | |
| </div> | |
| <div className="ap-settings-foot"> | |
| <button className="ap-textbtn" onClick={onClose}>done</button> | |
| </div> | |
| </div> | |
| </div> | |
| ); | |
| } | |