diff --git a/.claude/rules/editor.md b/.claude/rules/editor.md index 3b04fd26fb..76b4375cca 100644 --- a/.claude/rules/editor.md +++ b/.claude/rules/editor.md @@ -12,6 +12,7 @@ paths: - **A slot exists only with a reader.** `ThemeSlot` is the one registry the gate, the theme editor and the decoder enumerate, and `ThemeSlotCoverageTests` fails a slot nothing reads. A theme file must declare every slot of its schema, as `#hex` or `system:`. - **Two color tiers.** `palette[slot]` is a dynamic color that answers for the theme in effect; use it wherever a view holds a color. `resolved[slot]` is a snapshot for code that bakes one (`CALayer`, the editor theme, the grid's cell drawing), paired with an `AppEvents.shared.themeChanged` subscription. - **A theme change has to reach the view.** A SwiftUI view that reads the engine observes it (`@ObservedObject private var themeEngine = ThemeEngine.shared`), because SwiftUI caches `Color(nsColor:)` by object identity; an AppKit view subscribes to `themeChanged` and redisplays. +- **A theme colors content, never chrome.** `NSApp.appearance` is the only lever on the sidebar, the trailing pane, the editor tab strip and the window background: a theme declares `light` or `dark` and the frame follows. Painting them means covering views AppKit owns (the sidebar's `NSGlassEffectView`, the titlebar band, the source-list selection), so every slot is namespaced `content.` and none is added for chrome. - **Fonts are not theme.** `TypographySettings` is device-local and stays out of `AppSettingsCategory.synced`: sync replaces a category wholesale, so an older Mac would reset it and each zoom press would push a record. - **Two font domains.** A view that also wears the editor's colors (the SQL editor, `JSONCodeEditor`, previews) uses `editorFonts`. Every control that shows or edits a stored value uses `ThemeEngine.valueFont` or `valueFontSwiftUI` (the Data Grid Font), so a value reads the same in the grid, the inspector and a popover; a system text style there looks right only while the two settings are equal. `InspectorFieldRow` sets it for the whole inspector, and its `FieldEditorKind` switch is exhaustive on purpose. - **Multi-cursor lives in `cursorPositions: [CursorPosition]`.** diff --git a/CHANGELOG.md b/CHANGELOG.md index f9feaf852a..3944d16251 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Theme file format 2. Themes written for earlier versions are not read and need to be recreated. +- Settings > Editor grouped into Display, Gutter and Editing. - Editor Font and Data Grid Font moved to Settings > Editor and Settings > Data, and kept per Mac. - Editor font size range of 10 to 24 points everywhere, including zoom. @@ -39,6 +40,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Content panes outside the editor and the data grid ignoring the theme. - JSON and PHP tree values colored differently from the same values in the row inspector. - Autocomplete icon colors ignoring the theme. +- Theme color wells and the theme preview unreadable to VoiceOver. ## [0.80.0] - 2026-10-11 diff --git a/TablePro/Resources/Localizable.xcstrings b/TablePro/Resources/Localizable.xcstrings index 9d4955a3fe..e0664fe551 100644 --- a/TablePro/Resources/Localizable.xcstrings +++ b/TablePro/Resources/Localizable.xcstrings @@ -86062,6 +86062,9 @@ } } } + }, + "Gutter" : { + }, "gzip executable not found" : { "localizations" : { @@ -167514,6 +167517,7 @@ } }, "SQL Editor" : { + "extractionState" : "stale", "localizations" : { "fr" : { "stringUnit" : { diff --git a/TablePro/Views/Settings/EditorSettingsView.swift b/TablePro/Views/Settings/EditorSettingsView.swift index 34f4b84bce..7475fc4ff7 100644 --- a/TablePro/Views/Settings/EditorSettingsView.swift +++ b/TablePro/Views/Settings/EditorSettingsView.swift @@ -13,16 +13,22 @@ struct EditorSettingsView: View { Form { TypographySection(domain: .editor, settings: $typography) - Section("SQL Editor") { + Section("Display") { Toggle("Show line numbers", isOn: $settings.showLineNumbers) Toggle("Highlight current line", isOn: $settings.highlightCurrentLine) Toggle("Highlight current statement", isOn: $settings.highlightCurrentStatement) + Toggle("Show invisible characters", isOn: $settings.showInvisibleCharacters) Toggle("Word wrap", isOn: $settings.wordWrap) + } + + Section("Gutter") { Toggle("Code folding", isOn: $settings.codeFoldingEnabled) Toggle("Run button beside each statement", isOn: $settings.showStatementRunControls) .disabled(!settings.showLineNumbers) .help(Text("The run button sits in the gutter, which needs line numbers.")) - Toggle("Show invisible characters", isOn: $settings.showInvisibleCharacters) + } + + Section("Editing") { Picker("Tab width:", selection: $settings.tabWidth) { Text("2 spaces").tag(2) Text("4 spaces").tag(4) diff --git a/TablePro/Views/Settings/Sections/TypographySection.swift b/TablePro/Views/Settings/Sections/TypographySection.swift index cb50b3a815..1817451d6e 100644 --- a/TablePro/Views/Settings/Sections/TypographySection.swift +++ b/TablePro/Views/Settings/Sections/TypographySection.swift @@ -29,7 +29,7 @@ internal struct TypographySection: View { @Binding internal var settings: TypographySettings internal var body: some View { - Section(domain.title) { + Section { Picker(String(localized: "Family:"), selection: familyBinding) { ForEach(EditorFontResolver.availableMonospacedFamilies) { family in Text(family.displayName).tag(family.id) @@ -41,10 +41,10 @@ internal struct TypographySection: View { Text(verbatim: "\(size) pt").tag(size) } } - + } header: { + Text(domain.title) + } footer: { Text(domain.caption) - .font(.caption) - .foregroundStyle(.secondary) } } diff --git a/TablePro/Views/Settings/ThemePreviewCard.swift b/TablePro/Views/Settings/ThemePreviewCard.swift index c43c1147d7..9f5d7bec03 100644 --- a/TablePro/Views/Settings/ThemePreviewCard.swift +++ b/TablePro/Views/Settings/ThemePreviewCard.swift @@ -91,6 +91,7 @@ struct ThemePreviewCard: View { size == .compact ? 14 : 28 } + /// The name and kind beside it carry the meaning, so the miniature is decorative. private var thumbnail: some View { HStack(spacing: 0) { sidebarStrip @@ -102,6 +103,7 @@ struct ThemePreviewCard: View { } } .environment(\.colorScheme, previewColorScheme) + .accessibilityHidden(true) } /// The system colours a theme leaves undeclared resolve in the appearance the theme is used