Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

[PBIOS-529] Improve multiline layout #452

Merged
merged 22 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
13805f3
Release
isismsilva Aug 6, 2024
651ef65
Merge branch 'main' of github.com:powerhome/playbook-swift
isismsilva Aug 14, 2024
a119d21
fix typeahead data update
isismsilva Aug 20, 2024
c820768
Merge branch 'main' into PBIOS-317-typeahead-on-connect
isismsilva Aug 26, 2024
741b5c4
Merge branch 'main' into PBIOS-317-typeahead-on-connect
isismsilva Aug 27, 2024
73f4521
fix options type
isismsilva Aug 27, 2024
73cddab
Merge branch 'PBIOS-317-typeahead-on-connect' of github.com:powerhome…
isismsilva Aug 27, 2024
9aa63c1
changed type
isismsilva Aug 30, 2024
d1d236e
Add id to typeahead options type
isismsilva Aug 30, 2024
16c8cd6
no message
isismsilva Aug 30, 2024
2b81f85
fix typeahead filter
isismsilva Sep 23, 2024
096954f
fix filter
isismsilva Sep 23, 2024
b986f21
fix keyboard dismiss
isismsilva Sep 23, 2024
ebc7a09
Merge branch 'PBIOS-317-typeahead-on-connect' into Typeahead-filter-f…
isismsilva Sep 23, 2024
2494737
Merge branch 'main' into Typeahead-filter-fix-1
isismsilva Sep 23, 2024
0c1649b
Merge branch 'Typeahead-filter-fix-1' into Typeahead-filter-fix
isismsilva Sep 25, 2024
fdc3c4a
fix grid spacings
isismsilva Sep 25, 2024
494bd6b
Merge branch 'Typeahead-filter-fix' into PBIOS-529-Improve-multiline-…
isismsilva Sep 26, 2024
5899164
change text input area min width
isismsilva Sep 26, 2024
fe3eec9
turn font public
isismsilva Sep 26, 2024
1181060
removed duplicated code
isismsilva Sep 26, 2024
b4eb69a
Merge branch 'main' into PBIOS-529-Improve-multiline-layout
isismsilva Sep 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions Sources/Playbook/Components/Grid/PBGrid.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public struct PBGrid: Layout {

public init(
alignment: Alignment = .leading,
horizontalSpacing: CGFloat? = 8,
horizontalSpacing: CGFloat? = nil,
verticalSpacing: CGFloat? = nil,
fitContent: Bool = true
) {
Expand Down Expand Up @@ -134,14 +134,12 @@ public extension PBGrid {

for index in rows.indices {
let maxHeightIndex = rows[index].elements
.max { $0.size.height < $1.size.height }!
.max { $0.size.height < $1.size.height }?
.index

let size = sizes[maxHeightIndex]

let size = sizes[maxHeightIndex ?? 0]
var spacing = CGFloat.zero
if let previousMaxHeightIndex {
spacing = verticalSpacing(subviews[previousMaxHeightIndex], subviews[maxHeightIndex])
spacing = verticalSpacing(subviews[previousMaxHeightIndex], subviews[maxHeightIndex ?? 0])
}

rows[index].yOffset = currentY + spacing
Expand Down
102 changes: 53 additions & 49 deletions Sources/Playbook/Components/Typeahead/GridInputField.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public struct GridInputField: View {
@State private var clearButtonIsHovering: Bool = false
@State private var indicatorIsHovering: Bool = false
var isFocused: FocusState<Bool>.Binding

init(
placeholder: String = "Select",
searchText: Binding<String>,
Expand All @@ -39,37 +39,45 @@ public struct GridInputField: View {
self.onItemTap = onItemTap
self.onViewTap = onViewTap
}

public var body: some View {
VStack(alignment: .leading) {
HStack {
HStack {
PBGrid(alignment: .leading, horizontalSpacing: 0) {
ForEach(indices, id: \.self) { index in
if indices.last != index {
gridView(index: index)
}
}
}
.layoutPriority(1)
textfieldWithCustomPlaceholder
.overlay {
Color.white
.opacity(isFocused.wrappedValue ? 0.001 : 0)
.onTapGesture {
if isFocused.wrappedValue {
onViewTap?()
}
PBGrid(
alignment: .leading,
horizontalSpacing: Spacing.xSmall,
verticalSpacing: Spacing.xSmall,
fitContent: false
) {
ForEach(indices, id: \.self) { index in
if indices.last != index {
gridView(index: index)
} else {
textfieldWithCustomPlaceholder
.fixedSize()
.frame(minWidth: 60, alignment: .leading)
.overlay {
Color.white
.opacity(isFocused.wrappedValue ? 0.001 : 0)
.onTapGesture {
if isFocused.wrappedValue {
onViewTap?()
}
}
}
.clipped()
}
}
}
.padding(.horizontal, Spacing.small)
.padding(.vertical, Spacing.xSmall)
.background(Color.white.opacity(0.01))
.onTapGesture {
isFocused.wrappedValue = true
if isFocused.wrappedValue {
onViewTap?()
}
}

dismissIconView
indicatorView
}
Expand Down Expand Up @@ -107,50 +115,46 @@ private extension GridInputField {
.textFieldStyle(.plain)
.pbFont(.body, color: textColor)
}
.frame(maxWidth: .infinity)
.frame(height: Spacing.xLarge)
.padding(.leading, Spacing.small)
}

@ViewBuilder
func gridView(index: Int?) -> some View {

func gridView(index: Int?) -> AnyView? {
switch selection {
case .multiple(let variant, let options):
if let index = index, let option = options?[index] {
variant.view(text: option)
.onTapGesture { onItemTap?(index) }
.padding(.leading, Spacing.xSmall)
.padding(.vertical, Spacing.xSmall)
.fixedSize()
return AnyView(
variant.view(text: option)
.onTapGesture { onItemTap?(index) }
)
} else {
return nil
}
case .single:
EmptyView()
case .single: return nil
}
}

var placeholderText: String {
switch selection {
case .multiple(_, let elements): return elements?.isEmpty ?? true ? placeholder : ""
case .single(let element): return element ?? placeholder
}
}

var placeholderTextColor: Color {
switch selection {
case .multiple(_, _): return .text(.light)
case .single(let element):
return element == nil ? .text(.light) : .text(.default)
}
}

var textColor: Color {
return .text(.default)
}

var borderColor: Color {
isFocused.wrappedValue ? .pbPrimary : .border
}

@ViewBuilder
var dismissIconView: some View {
Group {
Expand All @@ -169,7 +173,7 @@ private extension GridInputField {
clearAction?()
}
}

var dismissIcon: some View {
PBIcon(FontAwesome.times, size: .xSmall)
.foregroundStyle(iconColor(on: clearButtonIsHovering))
Expand All @@ -180,11 +184,11 @@ private extension GridInputField {
isHovering = $0
}
}

var backgroundColor: Color {
(isHovering || isFocused.wrappedValue) ? .background(.light) : .card
}

var indicatorView: some View {
PBIcon(FontAwesome.chevronDown, size: .xSmall)
.padding(Spacing.small)
Expand All @@ -198,7 +202,7 @@ private extension GridInputField {
onViewTap?()
}
}

func iconColor(on hover: Bool) -> Color {
if isFocused.wrappedValue, !hover {
return Color.text(.light)
Expand All @@ -215,10 +219,10 @@ private extension GridInputField {
public extension GridInputField {
enum Selection {
case single(String?), multiple(Selection.Variant, [String]?)

public enum Variant {
case text, pill, other(AnyView)

@ViewBuilder
func view(text: String) -> some View {
switch self {
Expand Down Expand Up @@ -247,19 +251,19 @@ public struct WrappedInputFieldCatalog: View {
selection: .single(nil),
isFocused: $isFocused
)

GridInputField(
searchText: $text,
selection: .multiple(.pill, ["title1", "title2"]),
selection: .multiple(.pill, ["title1", "title2", "title2", "title2", "title2"]),
isFocused: $isFocused
)

GridInputField(
searchText: $text,
selection: .multiple(.other(AnyView(PBPill("oi", variant: .primary))), ["title1", "title2"]),
selection: .multiple(.other(AnyView(PBPill("oi", variant: .primary))), ["title1", "title2", "title2", "title2", "title2", "title2", "title2", "title2"]),
isFocused: $isFocused
)

GridInputField(
searchText: $text,
selection: .multiple(.other(AnyView(PBBadge(text: "title", variant: .primary))), ["title1", "title2"]),
Expand Down
37 changes: 24 additions & 13 deletions Sources/Playbook/Components/Typeahead/PBTypeahead.swift
Original file line number Diff line number Diff line change
Expand Up @@ -157,26 +157,35 @@ private extension PBTypeahead {
}
}
}
.scrollDismissesKeyboard(.immediately)
.frame(maxHeight: dropdownMaxHeight)
.fixedSize(horizontal: false, vertical: true)
}
.frame(maxWidth: .infinity, alignment: .top)
.transition(.opacity)
}

var searchResults: [Option] {
switch selection{
case .multiple:
return searchText.isEmpty && debounce.numberOfCharacters == 0 ? listOptions : listOptions.filter {
$0.0.localizedCaseInsensitiveContains(searchText)
}
case .single:
return searchText.isEmpty && debounce.numberOfCharacters == 0 ? options : options.filter {
$0.0.localizedCaseInsensitiveContains(searchText)
}
}
switch selection{
case .multiple:
return searchText.isEmpty && debounce.numberOfCharacters == 0 ? listOptions : listOptions.filter {
if let text = $0.1?.0 {
text.localizedCaseInsensitiveContains(searchText)
} else {
$0.0.localizedCaseInsensitiveContains(searchText)
}
}
case .single:
return searchText.isEmpty && debounce.numberOfCharacters == 0 ? options : options.filter {
if let text = $0.1?.0 {
text.localizedCaseInsensitiveContains(searchText)
} else {
$0.0.localizedCaseInsensitiveContains(searchText)
}
}
}
}

var optionsSelected: GridInputField.Selection {
let optionsSelected = selectedOptions.map { value in
if let content = value.1 {
Expand All @@ -192,14 +201,16 @@ private extension PBTypeahead {
if let action = clearAction {
clearText
action()
clearText
evertoncunha marked this conversation as resolved.
Show resolved Hide resolved
} else {
clearText
}
}

var clearText: Void {
searchText = ""
selectedOptions.removeAll()
onSelection?([])
listOptions = options
selectedIndex = nil
hoveringIndex = nil
Expand Down