diff --git a/Sources/TokamakCore/Modifiers/FlexFrameLayout.swift b/Sources/TokamakCore/Modifiers/FlexFrameLayout.swift index 7858e290..11719694 100644 --- a/Sources/TokamakCore/Modifiers/FlexFrameLayout.swift +++ b/Sources/TokamakCore/Modifiers/FlexFrameLayout.swift @@ -26,11 +26,11 @@ public struct _FlexFrameLayout: ViewModifier { // These are special cases in SwiftUI, where the child // will request the entire width/height of the parent. public var fillWidth: Bool { - minWidth == 0 && maxWidth == .infinity + (minWidth == 0 || minWidth == nil) && maxWidth == .infinity } public var fillHeight: Bool { - minHeight == 0 && maxHeight == .infinity + (minHeight == 0 || minHeight == nil) && maxHeight == .infinity } init( diff --git a/Sources/TokamakCore/Views/Containers/List/List.swift b/Sources/TokamakCore/Views/Containers/List/List.swift index 2c1de03f..b69e8057 100644 --- a/Sources/TokamakCore/Views/Containers/List/List.swift +++ b/Sources/TokamakCore/Views/Containers/List/List.swift @@ -81,12 +81,14 @@ public struct List: View @_spi(TokamakCore) public var body: some View { if let style = style as? ListStyleDeferredToRenderer { - style.listBody(ScrollView { - HStack { Spacer() } - listStack - .environment(\._outlineGroupStyle, _ListOutlineGroupStyle()) - }) - .frame(minHeight: 0, maxHeight: .infinity) + ScrollView { + style.listBody(Group { + HStack { Spacer() } + listStack + .environment(\._outlineGroupStyle, _ListOutlineGroupStyle()) + }) + } + .frame(maxHeight: .infinity, alignment: .topLeading) } else { ScrollView { HStack { Spacer() } diff --git a/Sources/TokamakCore/Views/Containers/Section.swift b/Sources/TokamakCore/Views/Containers/Section.swift index 2b8c6d27..e192ccff 100644 --- a/Sources/TokamakCore/Views/Containers/Section.swift +++ b/Sources/TokamakCore/Views/Containers/Section.swift @@ -86,7 +86,7 @@ extension Section: View, SectionView where Parent: View, Content: View, Footer: sectionContent(style) footerView(style) } - .frame(minWidth: 0, maxWidth: .infinity) + .frame(maxWidth: .infinity, alignment: .leading) ) } } diff --git a/Sources/TokamakStaticHTML/Modifiers/LayoutModifiers.swift b/Sources/TokamakStaticHTML/Modifiers/LayoutModifiers.swift index 7e385c21..433d24c4 100644 --- a/Sources/TokamakStaticHTML/Modifiers/LayoutModifiers.swift +++ b/Sources/TokamakStaticHTML/Modifiers/LayoutModifiers.swift @@ -33,7 +33,28 @@ private extension DOMViewModifier { } } +private extension VerticalAlignment { + var flexAlignment: String { + switch self { + case .top: return "flex-start" + case .center: return "center" + case .bottom: return "flex-end" + } + } +} + +private extension HorizontalAlignment { + var flexAlignment: String { + switch self { + case .leading: return "flex-start" + case .center: return "center" + case .trailing: return "flex-end" + } + } +} + extension _FrameLayout: DOMViewModifier { + public var isOrderDependent: Bool { true } public var attributes: [HTMLAttribute: String] { ["style": """ \(unwrapToStyle(\.width, property: "width")) @@ -43,11 +64,15 @@ extension _FrameLayout: DOMViewModifier { white-space: nowrap; flex-grow: 0; flex-shrink: 0; + display: flex; + align-items: \(alignment.vertical.flexAlignment); + justify-content: \(alignment.horizontal.flexAlignment); """] } } extension _FlexFrameLayout: DOMViewModifier { + public var isOrderDependent: Bool { true } public var attributes: [HTMLAttribute: String] { ["style": """ \(unwrapToStyle(\.minWidth, property: "min-width")) @@ -61,6 +86,9 @@ extension _FlexFrameLayout: DOMViewModifier { white-space: nowrap; flex-grow: 0; flex-shrink: 0; + display: flex; + align-items: \(alignment.vertical.flexAlignment); + justify-content: \(alignment.horizontal.flexAlignment); """] } } diff --git a/Sources/TokamakStaticHTML/Views/Containers/List.swift b/Sources/TokamakStaticHTML/Views/Containers/List.swift index 4b49f507..0039c72e 100644 --- a/Sources/TokamakStaticHTML/Views/Containers/List.swift +++ b/Sources/TokamakStaticHTML/Views/Containers/List.swift @@ -133,7 +133,7 @@ extension InsetGroupedListStyle: ListStyleDeferredToRenderer { .font(.caption) .padding([.top, .leading]) .padding(.leading) - .frame(minWidth: 0, maxWidth: .infinity) + .frame(maxWidth: .infinity, alignment: .leading) ) } @@ -144,7 +144,7 @@ extension InsetGroupedListStyle: ListStyleDeferredToRenderer { .background(Color.listGroupBackground) .cornerRadius(10) .padding([.horizontal, .top]) - .frame(minWidth: 0, maxWidth: .infinity) + .frame(maxWidth: .infinity, alignment: .leading) ) } @@ -180,7 +180,7 @@ extension SidebarListStyle: ListStyleDeferredToRenderer { } public func listRow(_ row: Row) -> AnyView where Row: View { - AnyView(row.frame(minWidth: 0, maxWidth: .infinity)) + AnyView(row.frame(maxWidth: .infinity, alignment: .leading)) } public func listBody(_ content: ListBody) -> AnyView where ListBody: View { diff --git a/Tests/TokamakStaticHTMLTests/RenderingTests.swift b/Tests/TokamakStaticHTMLTests/RenderingTests.swift index c1a9150e..13b98e02 100644 --- a/Tests/TokamakStaticHTMLTests/RenderingTests.swift +++ b/Tests/TokamakStaticHTMLTests/RenderingTests.swift @@ -244,6 +244,16 @@ final class RenderingTests: XCTestCase { timeout: defaultSnapshotTimeout ) } + + func testFrames() { + assertSnapshot( + matching: Color.red + .frame(width: 20, height: 20) + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottomTrailing), + as: .image(size: .init(width: 50, height: 50)), + timeout: defaultSnapshotTimeout + ) + } } #endif diff --git a/Tests/TokamakStaticHTMLTests/__Snapshots__/RenderingTests/testFrames.1.png b/Tests/TokamakStaticHTMLTests/__Snapshots__/RenderingTests/testFrames.1.png new file mode 100644 index 00000000..526f901b Binary files /dev/null and b/Tests/TokamakStaticHTMLTests/__Snapshots__/RenderingTests/testFrames.1.png differ diff --git a/Tests/TokamakStaticHTMLTests/__Snapshots__/RenderingTests/testOpacity.1.png b/Tests/TokamakStaticHTMLTests/__Snapshots__/RenderingTests/testOpacity.1.png index 66384046..1e3bb306 100644 Binary files a/Tests/TokamakStaticHTMLTests/__Snapshots__/RenderingTests/testOpacity.1.png and b/Tests/TokamakStaticHTMLTests/__Snapshots__/RenderingTests/testOpacity.1.png differ