diff options
Diffstat (limited to 'Map/Presentation/Base Components/EvolutionPicker')
4 files changed, 228 insertions, 0 deletions
diff --git a/Map/Presentation/Base Components/EvolutionPicker/EvolutionPicker.swift b/Map/Presentation/Base Components/EvolutionPicker/EvolutionPicker.swift new file mode 100644 index 0000000..5748e59 --- /dev/null +++ b/Map/Presentation/Base Components/EvolutionPicker/EvolutionPicker.swift @@ -0,0 +1,89 @@ +// Copyright (C) 2024 Rubén Beltrán del Río + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see https://map.tranquil.systems. +import SwiftUI + +struct EvolutionPicker: View { + + @State var isShowingMenu = false + @State var isHovered = false + @FocusState var isFocused: Bool + + @Binding var selectedEvolution: StageType + + var body: some View { + + Button( + action: { + isShowingMenu = !isShowingMenu + }, + label: { + HStack(spacing: Dimensions.Spacing.loose) { + Text(Stage.title(selectedEvolution)) + .font(.Theme.Body.emphasized) + .foregroundColor(isShowingMenu ? .Theme.UI.background : .Theme.UI.foreground) + ZStack { + Image(systemName: "chevron.up") + .resizable() + .scaledToFit() + .frame( + width: Dimensions.EvolutionPicker.controlSize, + height: Dimensions.EvolutionPicker.controlSize + ) + .offset(CGSize(width: 0, height: -Dimensions.EvolutionPicker.controlSpacing)) + .foregroundColor(isShowingMenu ? .Theme.UI.background : .Theme.UI.foreground) + Image(systemName: "chevron.down") + .resizable() + .scaledToFit() + .frame( + width: Dimensions.EvolutionPicker.controlSize, + height: Dimensions.EvolutionPicker.controlSize + ) + .offset(CGSize(width: 0, height: Dimensions.EvolutionPicker.controlSpacing)) + .foregroundColor(isShowingMenu ? .Theme.UI.background : .Theme.UI.foreground) + } + } + .padding(.horizontal, Dimensions.Spacing.regular) + .padding(.vertical, Dimensions.Spacing.cozy) + } + ) + .buttonStyle(.borderless) + .background(isShowingMenu ? Color.Theme.UI.foreground : Color.clear) + .cornerRadius(4.0) + .overlay( + RoundedRectangle(cornerRadius: 4.0) + .stroke( + isShowingMenu + ? Color.Theme.UI.foreground : (isHovered ? Color.Theme.UI.foreground : Color.clear), + lineWidth: 1) + ) + .onHover { hovering in + isHovered = hovering + } + .popover( + isPresented: $isShowingMenu, + content: { + EvolutionPickerMenu(selectedEvolution: $selectedEvolution) + } + ) + .onChange(of: selectedEvolution) { + isShowingMenu = false + } + } +} + +#Preview { + @Previewable @State var selectedEvolution: StageType = .behavior + EvolutionPicker(selectedEvolution: $selectedEvolution) +} diff --git a/Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenu.swift b/Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenu.swift new file mode 100644 index 0000000..3a396aa --- /dev/null +++ b/Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenu.swift @@ -0,0 +1,81 @@ +import SwiftUI + +struct EvolutionPickerMenu: View { + + @Binding var selectedEvolution: StageType + + private func select(_ evolution: StageType) { + selectedEvolution = evolution + } + + var body: some View { + VStack(alignment: .leading, spacing: 1.0) { + Section(header: EvolutionPickerMenuHeader(key: "stage_type.section.types")) { + ForEach(StageType.types) { stage in + EvolutionPickerMenuItem(stage: stage, isSelected: selectedEvolution == stage) + .onTapGesture { + selectedEvolution = stage + } + } + } + Section(header: EvolutionPickerMenuHeader(key: "stage_type.section.characteristics")) { + ForEach(StageType.characteristics) { stage in + EvolutionPickerMenuItem(stage: stage, isSelected: selectedEvolution == stage) + .onTapGesture { + selectedEvolution = stage + } + } + } + Section(header: EvolutionPickerMenuHeader(key: "stage_type.section.general_properties")) { + ForEach(StageType.properties) { stage in + EvolutionPickerMenuItem(stage: stage, isSelected: selectedEvolution == stage) + .onTapGesture { + selectedEvolution = stage + } + } + } + Section(header: EvolutionPickerMenuHeader(key: "stage_type.section.other")) { + ForEach(StageType.custom) { stage in + EvolutionPickerMenuItem(stage: stage, isSelected: selectedEvolution == stage) + .onTapGesture { + selectedEvolution = stage + } + } + } + } + .padding(Dimensions.Spacing.coziest) + .ignoresSafeArea() + + } +} + +#Preview { + EvolutionPickerMenu(selectedEvolution: .constant(.ubiquity)) +} + +/* +Picker(selection: $selectedEvolution) { + Divider() + ForEach(StageType.characteristics) { stage in + Text(Stage.title(stage)) + .font(selectedEvolution == stage ? .Theme.Body.emphasized : .Theme.Body.regular) + .tag(stage) + } + Divider() + ForEach(StageType.properties) { stage in + Text(Stage.title(stage)) + .font(selectedEvolution == stage ? .Theme.Body.emphasized : .Theme.Body.regular) + .tag(stage) + } + Divider() + ForEach(StageType.custom) { stage in + Text(Stage.title(stage)) + .font(selectedEvolution == stage ? .Theme.Body.emphasized : .Theme.Body.regular) + .tag(stage) + } +} label: { + Label("evolution_picker.label", image: "Icons/Evolution") + .font(.Theme.Body.regular) +}.padding(.horizontal, Dimensions.Spacing.regular) + .padding(.vertical, Dimensions.Spacing.cozy) + */ diff --git a/Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenuHeader.swift b/Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenuHeader.swift new file mode 100644 index 0000000..b3eeb97 --- /dev/null +++ b/Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenuHeader.swift @@ -0,0 +1,26 @@ +import SwiftUI + +struct EvolutionPickerMenuHeader: View { + + let key: LocalizedStringKey + + var body: some View { + HStack(alignment: .center, spacing: Dimensions.Spacing.regular) { + Text(key) + .font(.Theme.Caption.emphasized) + .padding(.vertical, Dimensions.Spacing.cozy) + .textCase(.uppercase) + .padding(.leading, Dimensions.Spacing.regular) + .layoutPriority(1) + Spacer() + .frame(height: 1) + .background(Color.Theme.UI.foreground.opacity(0.2)) + } + .padding(.horizontal, Dimensions.Spacing.regular) + .cornerRadius(Dimensions.EvolutionPicker.radius) + } +} + +#Preview { + EvolutionPickerMenuHeader(key: "stage_type.section.types") +} diff --git a/Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenuItem.swift b/Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenuItem.swift new file mode 100644 index 0000000..1731e8d --- /dev/null +++ b/Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenuItem.swift @@ -0,0 +1,32 @@ +import SwiftUI + +struct EvolutionPickerMenuItem: View { + + @State var isHovered: Bool = false + + let stage: StageType + let isSelected: Bool + + var body: some View { + HStack(alignment: .center, spacing: Dimensions.Spacing.coziest) { + Image(systemName: "checkmark") + .opacity(isSelected ? 1.0 : 0.0) + .bold(true) + Text(Stage.title(stage)) + .font(isSelected ? .Theme.Body.emphasized : .Theme.Body.regular) + .padding(Dimensions.Spacing.cozy) + Spacer() + } + .padding(.horizontal, Dimensions.Spacing.regular) + .background(isHovered ? Color.Theme.UI.accent : Color.clear) + .cornerRadius(Dimensions.EvolutionPicker.radius) + .onHover { hovering in + isHovered = hovering + } + } +} + +#Preview { + EvolutionPickerMenuItem(stage: .behavior, isSelected: false) + EvolutionPickerMenuItem(stage: .ubiquity, isSelected: true) +} |