aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Map/Business/CustomStage.swift6
-rw-r--r--Map/Business/Stage.swift26
-rw-r--r--Map/Localizable.xcstrings50
-rw-r--r--Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenu.swift1
-rw-r--r--Map/Presentation/Base Components/MapTextEditor.swift38
-rw-r--r--Map/Presentation/MapEditor.swift15
-rw-r--r--Map/Presentation/Preferences/StagesPreferencesView.swift6
-rw-r--r--Map/Presentation/Preferences/TemplatesPreferencesView.swift255
-rw-r--r--Map/Presentation/PreferencesWindow.swift10
-rw-r--r--Map/Presentation/Theme/Dimensions.swift17
-rw-r--r--MapTests/StageTests.swift1
11 files changed, 270 insertions, 155 deletions
diff --git a/Map/Business/CustomStage.swift b/Map/Business/CustomStage.swift
index 388531b..924e814 100644
--- a/Map/Business/CustomStage.swift
+++ b/Map/Business/CustomStage.swift
@@ -24,7 +24,7 @@ struct CustomStage: Identifiable, Codable {
self.name = name
self.stage = stage
}
-
+
static func cynefinDefault() -> CustomStage {
return CustomStage(
name: String(localized: "stage_type.cynefin"),
@@ -36,7 +36,7 @@ struct CustomStage: Identifiable, Codable {
)
)
}
-
+
static func placeholderDefault() -> CustomStage {
return CustomStage(
name: String(localized: "stage_type.placeholder"),
@@ -48,4 +48,4 @@ struct CustomStage: Identifiable, Codable {
)
)
}
-} \ No newline at end of file
+}
diff --git a/Map/Business/Stage.swift b/Map/Business/Stage.swift
index fcbdb62..4b98ecc 100644
--- a/Map/Business/Stage.swift
+++ b/Map/Business/Stage.swift
@@ -20,7 +20,6 @@ struct Stage: Codable {
var iii: String
var iv: String
-
static func stages(_ type: StageType) -> Stage {
switch type {
case .general:
@@ -127,15 +126,15 @@ struct Stage: Codable {
iv: "Known / common usage")
case .custom(let uuid):
if let customStagesData = UserDefaults.standard.data(forKey: "customStages"),
- let customStagesList = try? JSONDecoder().decode([CustomStage].self, from: customStagesData),
- let customStage = customStagesList.first(where: { $0.id == uuid }) {
+ let customStagesList = try? JSONDecoder().decode(
+ [CustomStage].self, from: customStagesData),
+ let customStage = customStagesList.first(where: { $0.id == uuid })
+ {
return customStage.stage
}
- return stages(.behavior) // fallback
+ return stages(.behavior) // fallback
}
}
-
-
static func title(_ type: StageType) -> String {
switch type {
@@ -181,11 +180,13 @@ struct Stage: Codable {
return String(localized: "stage_type.behavior")
case .custom(let uuid):
if let customStagesData = UserDefaults.standard.data(forKey: "customStages"),
- let customStagesList = try? JSONDecoder().decode([CustomStage].self, from: customStagesData),
- let customStage = customStagesList.first(where: { $0.id == uuid }) {
+ let customStagesList = try? JSONDecoder().decode(
+ [CustomStage].self, from: customStagesData),
+ let customStage = customStagesList.first(where: { $0.id == uuid })
+ {
return customStage.name
}
- return String(localized: "stage_type.behavior") // fallback
+ return String(localized: "stage_type.behavior") // fallback
}
}
}
@@ -216,7 +217,7 @@ enum StageType: Identifiable, Equatable {
case behavior
case custom(UUID)
- var id: String {
+ var id: String {
switch self {
case .general: return "general"
case .practice: return "practice"
@@ -249,10 +250,11 @@ enum StageType: Identifiable, Equatable {
.perceptionInIndustry, .focusOfValue, .understanding, .comparison, .failure,
.marketAction, .efficiency, .decisionDrivers,
]
-
+
static var customStages: [StageType] {
if let customStagesData = UserDefaults.standard.data(forKey: "customStages"),
- let customStagesList = try? JSONDecoder().decode([CustomStage].self, from: customStagesData) {
+ let customStagesList = try? JSONDecoder().decode([CustomStage].self, from: customStagesData)
+ {
return customStagesList.map { .custom($0.id) }
}
return []
diff --git a/Map/Localizable.xcstrings b/Map/Localizable.xcstrings
index f5fd775..22f8e6b 100644
--- a/Map/Localizable.xcstrings
+++ b/Map/Localizable.xcstrings
@@ -72,6 +72,39 @@
"Map settings will be available here in a future version." : {
},
+ "map_template.default.content" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "Anchor (95, 80)\nUsers (90, 20)\nWalking App (70, 20)\nWalking App Database (50, 60)\nUser Interface (80, 50)\nWeb Server (60, 30)\nCRM (30, 70)\n\nUsers -> Walking App\nUsers -> User Interface\nWalking App -> Walking App Database\nWalking App -> Web Server\nUser Interface -> Web Server\nWeb Server -> CRM\n\n[Note] (80, 5) Social walking app for everyone\n\n[Group] Client Side, Walking App, User Interface\n\n[Evolution] Walking App +5\n\n[Blocker] Unreliable Data"
+ }
+ }
+ }
+ },
+ "map_template.default.title" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "Basic Map"
+ }
+ }
+ }
+ },
+ "map_template.empty.title" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "Empty Map"
+ }
+ }
+ }
+ },
"Name" : {
},
@@ -108,6 +141,17 @@
}
}
},
+ "preferences.templates.table.title" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "Templates"
+ }
+ }
+ }
+ },
"preferences.templates.title" : {
"extractionState" : "manual",
"localizations" : {
@@ -125,6 +169,9 @@
"Select a template to edit" : {
},
+ "Set as default template" : {
+
+ },
"Stage I" : {
},
@@ -530,9 +577,6 @@
"Template: %@" : {
},
- "Templates" : {
-
- },
"Uncharted" : {
},
diff --git a/Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenu.swift b/Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenu.swift
index 9478346..94a87d7 100644
--- a/Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenu.swift
+++ b/Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenu.swift
@@ -3,7 +3,6 @@ import SwiftUI
struct EvolutionPickerMenu: View {
@Binding var selectedEvolution: StageType
-
private func select(_ stageType: StageType) {
selectedEvolution = stageType
diff --git a/Map/Presentation/Base Components/MapTextEditor.swift b/Map/Presentation/Base Components/MapTextEditor.swift
index 18b2fbc..4790a70 100644
--- a/Map/Presentation/Base Components/MapTextEditor.swift
+++ b/Map/Presentation/Base Components/MapTextEditor.swift
@@ -17,7 +17,8 @@ import SwiftUI
class MapTextEditorController: NSViewController {
- @Binding var document: MapDocument
+ @Binding var text: String
+
var highlightRanges: [Range<String.Index>] {
didSet {
updateHighlights()
@@ -44,10 +45,10 @@ class MapTextEditorController: NSViewController {
private let changeDebouncer: Debouncer = Debouncer(seconds: 1)
init(
- document: Binding<MapDocument>, highlightRanges: [Range<String.Index>], selectedRange: Int,
+ text: Binding<String>, highlightRanges: [Range<String.Index>], selectedRange: Int,
onChange: @escaping () -> Void
) {
- self._document = document
+ self._text = text
self.onChange = onChange
self.highlightRanges = highlightRanges
self.selectedRange = selectedRange
@@ -68,7 +69,7 @@ class MapTextEditorController: NSViewController {
textView.allowsUndo = true
textView.delegate = self
textView.textStorage?.delegate = self
- textView.string = self.document.text
+ textView.string = self.text
textView.isEditable = true
textView.font = .monospacedSystemFont(ofSize: 16.0, weight: .regular)
self.view = scrollView
@@ -79,12 +80,12 @@ class MapTextEditorController: NSViewController {
updateHighlights()
}
- private var textView: NSTextView? {
+ var currentTextView: NSTextView? {
return (view as? NSScrollView)?.documentView as? NSTextView
}
private func updateHighlights() {
- if let textView {
+ if let textView = currentTextView {
if let textStorage = textView.textStorage {
textStorage.removeAttribute(
.backgroundColor, range: NSRange(location: 0, length: textStorage.length))
@@ -105,7 +106,7 @@ class MapTextEditorController: NSViewController {
}
private func focusOnResult() {
- if let textView {
+ if let textView = currentTextView {
if let textStorage = textView.textStorage {
if selectedRange < highlightRanges.count {
let range = highlightRanges[selectedRange]
@@ -121,7 +122,7 @@ extension MapTextEditorController: NSTextViewDelegate {
func textDidChange(_ obj: Notification) {
if let textField = obj.object as? NSTextView {
- self.document.text = textField.string
+ self.text = textField.string
changeDebouncer.debounce {
DispatchQueue.main.async {
@@ -235,16 +236,26 @@ extension MapTextEditorController: NSTextStorageDelegate {
struct MapTextEditor: NSViewControllerRepresentable {
- @Binding var document: MapDocument
+ @Binding var text: String
var highlightRanges: [Range<String.Index>]
var selectedRange: Int
var onChange: () -> Void = {}
+ init(
+ text: Binding<String>, highlightRanges: [Range<String.Index>] = [], selectedRange: Int = 0,
+ onChange: @escaping () -> Void = {}
+ ) {
+ self._text = text
+ self.highlightRanges = highlightRanges
+ self.selectedRange = selectedRange
+ self.onChange = onChange
+ }
+
func makeNSViewController(
context: NSViewControllerRepresentableContext<MapTextEditor>
) -> MapTextEditorController {
return MapTextEditorController(
- document: $document, highlightRanges: highlightRanges, selectedRange: selectedRange,
+ text: $text, highlightRanges: highlightRanges, selectedRange: selectedRange,
onChange: onChange)
}
@@ -256,5 +267,12 @@ struct MapTextEditor: NSViewControllerRepresentable {
if nsViewController.selectedRange != selectedRange {
nsViewController.selectedRange = selectedRange
}
+
+ // Update text view content if text has changed
+ if let textView = nsViewController.currentTextView {
+ if textView.string != text {
+ textView.string = text
+ }
+ }
}
}
diff --git a/Map/Presentation/MapEditor.swift b/Map/Presentation/MapEditor.swift
index 5dc1adb..5005a73 100644
--- a/Map/Presentation/MapEditor.swift
+++ b/Map/Presentation/MapEditor.swift
@@ -91,10 +91,17 @@ struct MapEditor: View {
}
adaptiveStack {
ZStack(alignment: .topLeading) {
- MapTextEditor(document: $document, highlightRanges: results, selectedRange: selectedTerm)
- .background(Color.Theme.UI.background)
- .foregroundColor(Color.Theme.UI.foreground)
- .frame(minHeight: 96.0)
+ MapTextEditor(
+ text: Binding(
+ get: { document.text },
+ set: { document.text = $0 }
+ ),
+ highlightRanges: results,
+ selectedRange: selectedTerm
+ )
+ .background(Color.Theme.UI.background)
+ .foregroundColor(Color.Theme.UI.foreground)
+ .frame(minHeight: 96.0)
}
.background(Color.Theme.UI.background)
.cornerRadius(5.0)
diff --git a/Map/Presentation/Preferences/StagesPreferencesView.swift b/Map/Presentation/Preferences/StagesPreferencesView.swift
index 1e57cbf..b1ce31c 100644
--- a/Map/Presentation/Preferences/StagesPreferencesView.swift
+++ b/Map/Presentation/Preferences/StagesPreferencesView.swift
@@ -129,7 +129,7 @@ struct StagesPreferencesView: View {
} else {
// First use - create default Cynefin stage
customStages = [CustomStage.cynefinDefault()]
- saveStages() // Save the default to UserDefaults
+ saveStages() // Save the default to UserDefaults
}
}
@@ -156,7 +156,9 @@ struct StagesPreferencesView: View {
}
}
- private func updateStageValue(_ id: UUID, _ keyPath: WritableKeyPath<Stage, String>, _ value: String) {
+ private func updateStageValue(
+ _ id: UUID, _ keyPath: WritableKeyPath<Stage, String>, _ value: String
+ ) {
if let index = customStages.firstIndex(where: { $0.id == id }) {
customStages[index].stage[keyPath: keyPath] = value
saveStages()
diff --git a/Map/Presentation/Preferences/TemplatesPreferencesView.swift b/Map/Presentation/Preferences/TemplatesPreferencesView.swift
index 42db1a3..2994450 100644
--- a/Map/Presentation/Preferences/TemplatesPreferencesView.swift
+++ b/Map/Presentation/Preferences/TemplatesPreferencesView.swift
@@ -19,10 +19,12 @@ struct Template: Identifiable, Codable, Hashable {
var id = UUID()
var name: String
var content: String
+ var isDefault: Bool = false
- init(name: String, content: String) {
+ init(name: String, content: String, isDefault: Bool = false) {
self.name = name
self.content = content
+ self.isDefault = isDefault
}
func hash(into hasher: inout Hasher) {
@@ -34,56 +36,47 @@ struct Template: Identifiable, Codable, Hashable {
}
}
-struct SimpleTextEditor: NSViewRepresentable {
- @Binding var text: String
-
- func makeNSView(context: Context) -> NSScrollView {
- let scrollView = NSTextView.scrollableTextView()
- let textView = scrollView.documentView as! NSTextView
-
- textView.backgroundColor = .textBackgroundColor
- textView.allowsUndo = true
- textView.delegate = context.coordinator
- textView.string = text
- textView.isEditable = true
- textView.font = .monospacedSystemFont(ofSize: 14.0, weight: .regular)
-
- return scrollView
- }
-
- func updateNSView(_ nsView: NSScrollView, context: Context) {
- let textView = nsView.documentView as! NSTextView
- if textView.string != text {
- textView.string = text
- }
- }
+struct TemplatesPreferencesView: View {
+ @AppStorage("mapTemplates") private var templatesData: Data = Data()
+ @State private var selectedTemplate: Template?
+ @State private var showingAddSheet = false
+ @State private var newTemplateName = ""
- func makeCoordinator() -> Coordinator {
- Coordinator(self)
+ private var templates: Binding<[Template]> {
+ Binding(
+ get: {
+ if let decoded = try? JSONDecoder().decode([Template].self, from: templatesData) {
+ return decoded
+ }
+ return []
+ },
+ set: { newValue in
+ if let encoded = try? JSONEncoder().encode(newValue) {
+ templatesData = encoded
+ }
+ }
+ )
}
- class Coordinator: NSObject, NSTextViewDelegate {
- var parent: SimpleTextEditor
-
- init(_ parent: SimpleTextEditor) {
- self.parent = parent
- }
+ private var selectedTemplateContent: Binding<String> {
+ Binding(
+ get: {
+ guard let selected = selectedTemplate,
+ let template = templates.wrappedValue.first(where: { $0.id == selected.id })
+ else { return "" }
+ return template.content
+ },
+ set: { newContent in
+ guard let selected = selectedTemplate,
+ let index = templates.wrappedValue.firstIndex(where: { $0.id == selected.id })
+ else { return }
- func textDidChange(_ notification: Notification) {
- if let textView = notification.object as? NSTextView {
- parent.text = textView.string
+ var currentTemplates = templates.wrappedValue
+ currentTemplates[index].content = newContent
+ templates.wrappedValue = currentTemplates
}
- }
+ )
}
-}
-
-struct TemplatesPreferencesView: View {
- @AppStorage("mapTemplates") private var templatesData: Data = Data()
- @State private var templates: [Template] = []
- @State private var selectedTemplate: Template?
- @State private var templateText: String = ""
- @State private var showingAddSheet = false
- @State private var newTemplateName = ""
var body: some View {
VStack(alignment: .leading, spacing: Dimensions.Spacing.regular) {
@@ -97,35 +90,65 @@ struct TemplatesPreferencesView: View {
.padding(.top, Dimensions.Spacing.loose)
.padding(.bottom, Dimensions.Spacing.regular)
HStack(spacing: 0) {
- VStack(alignment: .leading, spacing: 8) {
+ VStack(alignment: .leading, spacing: Dimensions.Spacing.regular) {
HStack {
- Text("Templates")
- .font(.headline)
-
+ Text("preferences.templates.table.title")
+ .font(.Theme.Body.emphasized)
+
Spacer()
-
+
Button(action: { showingAddSheet = true }) {
Image(systemName: "plus")
}
.buttonStyle(.borderless)
-
- Button(action: removeTemplate) {
+
+ Button(action: {
+ removeTemplate(selectedTemplate)
+ }) {
Image(systemName: "minus")
}
.buttonStyle(.borderless)
.disabled(selectedTemplate == nil)
}
-
- List(templates, selection: $selectedTemplate) { template in
- Text(template.name)
- .tag(template)
+
+ List(templates.wrappedValue) { template in
+ HStack {
+ Button(action: { setDefaultTemplate(template) }) {
+ Image(systemName: template.isDefault ? "largecircle.fill.circle" : "circle")
+ .foregroundColor(
+ selectedTemplate?.id == template.id
+ ? Color.white
+ : (template.isDefault
+ ? Color.Theme.UI.accent : Color.Theme.UI.foreground.opacity(0.5))
+ )
+ }
+ .buttonStyle(.plain)
+ .help("Set as default template")
+
+ Text(template.name)
+ .tag(template)
+ .foregroundColor(
+ selectedTemplate?.id == template.id ? Color.white : Color.Theme.UI.foreground
+ )
+
+ Spacer()
+ }
+ .padding(Dimensions.Spacing.cozy)
+ .background(selectedTemplate?.id == template.id ? Color.Theme.UI.accent : Color.clear)
+ .clipShape(RoundedRectangle(cornerRadius: Dimensions.Preferences.Sidebar.radius))
+ .padding(Dimensions.Spacing.coziest)
+ .listRowInsets(EdgeInsets())
+ .listRowSeparator(.hidden)
+ .onTapGesture {
+ selectedTemplate = template
+ }
}
- .listStyle(.sidebar)
+ .listStyle(.plain)
}
- .frame(width: 200)
-
+ .frame(width: Dimensions.Preferences.Sidebar.width)
+
Divider()
-
+
VStack(alignment: .leading, spacing: 8) {
if let selected = selectedTemplate {
HStack {
@@ -133,11 +156,8 @@ struct TemplatesPreferencesView: View {
.font(.headline)
Spacer()
}
-
- SimpleTextEditor(text: $templateText)
- .onChange(of: templateText) { _, newValue in
- updateSelectedTemplate(newValue)
- }
+
+ MapTextEditor(text: selectedTemplateContent)
} else {
VStack {
Spacer()
@@ -151,89 +171,102 @@ struct TemplatesPreferencesView: View {
.frame(maxWidth: .infinity, maxHeight: .infinity)
.padding(.leading)
}
- .padding()
.onAppear {
- loadTemplates()
- }
- .onChange(of: selectedTemplate) { _, newSelection in
- if let template = newSelection {
- templateText = template.content
+ // Initialize default templates if needed
+ if templates.wrappedValue.isEmpty
+ || !templates.wrappedValue.contains(where: { $0.isDefault })
+ {
+ createDefaultTemplates()
+ }
+ // Set first template as selected if none is selected
+ if selectedTemplate == nil && !templates.wrappedValue.isEmpty {
+ selectedTemplate = templates.wrappedValue.first
}
}
.sheet(isPresented: $showingAddSheet) {
- VStack(spacing: 16) {
+ VStack(spacing: Dimensions.Spacing.indulgent) {
Text("Add New Template")
- .font(.headline)
-
+ .font(.Theme.Body.emphasized)
+
TextField("Template Name", text: $newTemplateName)
.textFieldStyle(.roundedBorder)
-
+ .font(.Theme.Body.regular)
+
HStack {
Button("Cancel") {
showingAddSheet = false
newTemplateName = ""
}
-
+
Spacer()
-
+
Button("Add") {
addTemplate()
}
.disabled(newTemplateName.isEmpty)
}
}
+ .padding(Dimensions.Spacing.loose)
.frame(width: 300, height: 120)
}
}.padding(.vertical, Dimensions.Spacing.loose)
.padding(.horizontal, Dimensions.Spacing.indulgent)
}
- private func loadTemplates() {
- if let decoded = try? JSONDecoder().decode([Template].self, from: templatesData) {
- templates = decoded
- } else {
- templates = [
- Template(
- name: "Basic Map",
- content:
- "Component A (90, 20)\nComponent B (70, 40)\nComponent A -> Component B\n\n[Note] (50, 10) This is a sample template"
- )
- ]
- saveTemplates()
- }
- }
+ private func createDefaultTemplates() {
+ let defaultTemplate = Template(
+ name: String(localized: "map_template.default.title"),
+ content: String(localized: "map_template.default.content"),
+ isDefault: true
+ )
+
+ let emptyTemplate = Template(
+ name: String(localized: "map_template.empty.title"),
+ content: "",
+ isDefault: false
+ )
- private func saveTemplates() {
- if let encoded = try? JSONEncoder().encode(templates) {
- templatesData = encoded
+ if templates.wrappedValue.isEmpty {
+ templates.wrappedValue = [defaultTemplate, emptyTemplate]
+ } else {
+ // Add default template if none exists
+ if !templates.wrappedValue.contains(where: { $0.isDefault }) {
+ var currentTemplates = templates.wrappedValue
+ currentTemplates.insert(defaultTemplate, at: 0)
+ templates.wrappedValue = currentTemplates
+ }
}
}
private func addTemplate() {
- let newTemplate = Template(name: newTemplateName, content: "")
- templates.append(newTemplate)
+ let newTemplate = Template(
+ name: newTemplateName.isEmpty
+ ? String(localized: "map_template.empty.title") : newTemplateName,
+ content: ""
+ )
+ var currentTemplates = templates.wrappedValue
+ currentTemplates.append(newTemplate)
+ templates.wrappedValue = currentTemplates
selectedTemplate = newTemplate
- templateText = ""
- saveTemplates()
showingAddSheet = false
newTemplateName = ""
}
- private func removeTemplate() {
- guard let selected = selectedTemplate else { return }
- templates.removeAll { $0.id == selected.id }
- selectedTemplate = nil
- templateText = ""
- saveTemplates()
+ private func removeTemplate(_ template: Template?) {
+ guard let template else { return }
+ var currentTemplates = templates.wrappedValue
+ currentTemplates.removeAll { $0 == template }
+ templates.wrappedValue = currentTemplates
+ selectedTemplate = templates.wrappedValue.first
}
- private func updateSelectedTemplate(_ newContent: String) {
- guard let selected = selectedTemplate,
- let index = templates.firstIndex(where: { $0.id == selected.id })
- else { return }
-
- templates[index].content = newContent
- saveTemplates()
+ private func setDefaultTemplate(_ template: Template) {
+ // Direct assignment to binding - this will automatically save via @AppStorage
+ templates.wrappedValue = templates.wrappedValue.map { t in
+ var newTemplate = t
+ newTemplate.isDefault = (t.id == template.id)
+ return newTemplate
+ }
}
}
diff --git a/Map/Presentation/PreferencesWindow.swift b/Map/Presentation/PreferencesWindow.swift
index da2b75f..2471711 100644
--- a/Map/Presentation/PreferencesWindow.swift
+++ b/Map/Presentation/PreferencesWindow.swift
@@ -68,8 +68,14 @@ struct PreferencesWindow: View {
Text(tab.rawValue)
.font(.Theme.SmallControl.regular)
}
- .frame(width: Dimensions.Preferences.Toolbar.width, height: Dimensions.Preferences.Toolbar.height)
- .background(selectedTab == tab ? Color.Theme.UI.accent : Color.clear)
+ .frame(
+ width: Dimensions.Preferences.Toolbar.width,
+ height: Dimensions.Preferences.Toolbar.height
+ )
+ .padding(.horizontal, Dimensions.Spacing.coziest)
+ .background(
+ selectedTab == tab ? Color.Theme.UI.accent : Color.background.opacity(0.01)
+ )
.foregroundColor(selectedTab == tab ? Color.white : Color.Theme.UI.foreground)
.cornerRadius(Dimensions.Preferences.Toolbar.radius)
}
diff --git a/Map/Presentation/Theme/Dimensions.swift b/Map/Presentation/Theme/Dimensions.swift
index 5597c4e..94ab7c0 100644
--- a/Map/Presentation/Theme/Dimensions.swift
+++ b/Map/Presentation/Theme/Dimensions.swift
@@ -22,7 +22,7 @@ struct Dimensions {
static let body: CGFloat = 13
static let title: CGFloat = 32
static let caption: CGFloat = 11
- static let smallControl: CGFloat = 9
+ static let smallControl: CGFloat = 11
struct Map {
static let note: CGFloat = 12
@@ -43,7 +43,7 @@ struct Dimensions {
static let vertexLabel: CGFloat = 18
}
}
-
+
struct Kerning {
static let body: CGFloat = 0.5
}
@@ -66,25 +66,30 @@ struct Dimensions {
}
// MARK: - Assorted Controls
-
+
struct EvolutionPicker {
static let radius = 8.0
static let controlSize = 8.0
static let controlSpacing = 3.0
}
-
+
struct Preferences {
-
+
struct Window {
static let width: CGFloat = 600.0
static let height: CGFloat = 400.0
}
-
+
struct Toolbar {
static let radius: CGFloat = 8.0
static let size: CGFloat = 16.0
static let width: CGFloat = 60.0
static let height: CGFloat = 40.0
}
+
+ struct Sidebar {
+ static let radius: CGFloat = 8.0
+ static let width: CGFloat = 200.0
+ }
}
}
diff --git a/MapTests/StageTests.swift b/MapTests/StageTests.swift
index 97502a8..f961df4 100644
--- a/MapTests/StageTests.swift
+++ b/MapTests/StageTests.swift
@@ -98,5 +98,4 @@ struct StageTests {
#expect(title == "Behavior")
}
-
}