openpencil/openspec/specs/app-menu/spec.md

211 lines
7 KiB
Markdown

# app-menu Specification
## Purpose
Browser-mode menu bar (`src/components/AppMenu.vue`) with File, Edit, View, Object, Text, and Arrange menus. Uses reka-ui Menubar components. Only visible when `!IS_TAURI` (Tauri provides native menus).
## Requirements
### Requirement: App menu bar for browser mode
The system SHALL display a menu bar in browser mode (`!IS_TAURI`) with File, Edit, View, Object, Text, and Arrange menus.
#### Scenario: Menu visibility in browser
- **WHEN** app runs in browser (not Tauri desktop)
- **THEN** system displays menu bar at top of window
#### Scenario: Menu hidden in Tauri
- **WHEN** app runs in Tauri desktop mode
- **THEN** system hides menu bar (Tauri provides native menus)
### Requirement: File menu
The system SHALL provide File menu with Open, Save, Save As, and Export actions.
#### Scenario: Open file
- **WHEN** user clicks File → Open… or presses ⌘O (Ctrl+O on Windows/Linux)
- **THEN** system opens file picker dialog
#### Scenario: Save file
- **WHEN** user clicks File → Save or presses ⌘S
- **THEN** system saves current document
#### Scenario: Save As
- **WHEN** user clicks File → Save as… or presses ⌘⇧S
- **THEN** system opens save dialog for new filename
#### Scenario: Export selection
- **WHEN** user clicks File → Export selection… or presses ⌘⇧E with selection
- **THEN** system exports selected nodes as PNG
#### Scenario: Export disabled when no selection
- **WHEN** user has no selection
- **THEN** system disables "Export selection…" menu item
### Requirement: Edit menu
The system SHALL provide Edit menu with undo, redo, clipboard, and selection actions.
#### Scenario: Undo
- **WHEN** user clicks Edit → Undo or presses ⌘Z
- **THEN** system reverts last action
#### Scenario: Redo
- **WHEN** user clicks Edit → Redo or presses ⌘⇧Z
- **THEN** system reapplies undone action
#### Scenario: Copy/Paste
- **WHEN** user clicks Edit → Copy (⌘C) or Paste (⌘V)
- **THEN** system performs clipboard operation
#### Scenario: Duplicate
- **WHEN** user clicks Edit → Duplicate or presses ⌘D
- **THEN** system duplicates selected nodes
#### Scenario: Delete
- **WHEN** user clicks Edit → Delete or presses ⌫
- **THEN** system removes selected nodes
#### Scenario: Select all
- **WHEN** user clicks Edit → Select all or presses ⌘A
- **THEN** system selects all nodes on current page
### Requirement: View menu
The system SHALL provide View menu with zoom and ruler controls.
#### Scenario: Zoom to fit
- **WHEN** user clicks View → Zoom to fit or presses ⇧1
- **THEN** system fits all content in viewport
#### Scenario: Zoom in
- **WHEN** user clicks View → Zoom in or presses ⌘=
- **THEN** system zooms in toward center
#### Scenario: Zoom out
- **WHEN** user clicks View → Zoom out or presses ⌘-
- **THEN** system zooms out from center
#### Scenario: Toggle rulers
- **WHEN** user clicks View → Rulers or presses ⇧R
- **THEN** system shows/hides canvas rulers
### Requirement: Object menu
The system SHALL provide Object menu with grouping, framing, and component actions.
#### Scenario: Group selection
- **WHEN** user clicks Object → Group or presses ⌘G
- **THEN** system creates GROUP containing selected nodes
#### Scenario: Ungroup
- **WHEN** user clicks Object → Ungroup or presses ⌘⇧G with grouped selection
- **THEN** system dissolves group and reparents children
#### Scenario: Frame selection
- **WHEN** user clicks Object → Frame selection or presses ⌘⌥F
- **THEN** system wraps selected nodes in FRAME
#### Scenario: Create component
- **WHEN** user clicks Object → Create component or presses ⌘⌥K
- **THEN** system converts selection to COMPONENT
#### Scenario: Create component set
- **WHEN** user clicks Object → Create component set with multiple components selected
- **THEN** system creates COMPONENT_SET containing components
### Requirement: Text menu
The system SHALL provide Text menu with font size and style controls.
#### Scenario: Font size adjustment
- **WHEN** user clicks Text → Increase font size (⌘⇧>) or Decrease (⌘⇧<)
- **THEN** system adjusts font size of selected text by 2px
#### Scenario: Bold toggle
- **WHEN** user clicks Text → Bold or presses ⌘B
- **THEN** system toggles bold weight for selected text
#### Scenario: Italic toggle
- **WHEN** user clicks Text → Italic or presses ⌘I
- **THEN** system toggles italic style for selected text
#### Scenario: Underline toggle
- **WHEN** user clicks Text → Underline or presses ⌘U
- **THEN** system toggles underline decoration for selected text
#### Scenario: Strikethrough toggle
- **WHEN** user clicks Text → Strikethrough or presses S button
- **THEN** system toggles strikethrough decoration for selected text
#### Scenario: Text alignment submenu
- **WHEN** user clicks Text → Align → Left/Center/Right
- **THEN** system aligns selected text horizontally
### Requirement: Arrange menu
The system SHALL provide Arrange menu with z-order controls.
#### Scenario: Bring to front
- **WHEN** user clicks Arrange → Bring to front or presses ]
- **THEN** system moves selected node to top of parent's children
#### Scenario: Send to back
- **WHEN** user clicks Arrange → Send to back or presses [
- **THEN** system moves selected node to bottom of parent's children
#### Scenario: Bring forward
- **WHEN** user clicks Arrange → Bring forward
- **THEN** system moves selected node up one position
#### Scenario: Send backward
- **WHEN** user clicks Arrange → Send backward
- **THEN** system moves selected node down one position
### Requirement: Keyboard shortcut display
The system SHALL display keyboard shortcuts next to menu items.
#### Scenario: Platform-specific modifier
- **WHEN** app runs on Mac
- **THEN** system displays ⌘ for Command key
#### Scenario: Windows/Linux modifiers
- **WHEN** app runs on Windows or Linux
- **THEN** system displays Ctrl+ for Control key
### Requirement: reka-ui integration
The system SHALL use reka-ui Menubar components for menu implementation.
#### Scenario: Menu structure
- **WHEN** component renders
- **THEN** system uses MenubarRoot, MenubarMenu, MenubarTrigger, MenubarContent, MenubarItem
#### Scenario: Submenus
- **WHEN** menu has nested items (e.g., Text → Align)
- **THEN** system uses MenubarSub, MenubarSubTrigger, MenubarSubContent
#### Scenario: Separators
- **WHEN** menu defines separator: true
- **THEN** system renders MenubarSeparator divider
### Requirement: Action binding
The system SHALL bind menu actions to editor store methods.
#### Scenario: Calling store actions
- **WHEN** user selects menu item
- **THEN** system invokes corresponding method on useEditorStore (e.g., `store.saveFigFile()`, `store.duplicateSelected()`)
### Requirement: Dynamic disabled state
The system SHALL disable menu items based on current editor state.
#### Scenario: Export requires selection
- **WHEN** no nodes are selected
- **THEN** system disables "Export selection…" item
#### Scenario: Text menu requires text selection
- **WHEN** selected node is not TEXT
- **THEN** system may disable text formatting items (if implemented)