diff --git a/Marks/Views/Library/LibraryGridView.swift b/Marks/Views/Library/LibraryGridView.swift index edceb8b..ab216cb 100644 --- a/Marks/Views/Library/LibraryGridView.swift +++ b/Marks/Views/Library/LibraryGridView.swift @@ -20,8 +20,11 @@ struct LibraryGridView: View { var body: some View { ScrollView { LazyVGrid( - columns: Array(repeating: GridItem(.flexible(), spacing: 8), count: 3), - spacing: 8 + // Two columns, not three: at the scaled-up type a third + // column leaves ~9 characters per line and every title + // truncates. The text size sets the column count. + columns: Array(repeating: GridItem(.flexible(), spacing: 10), count: 2), + spacing: 10 ) { ForEach(items) { item in card(item) diff --git a/Marks/Views/Library/LibraryKit.swift b/Marks/Views/Library/LibraryKit.swift index 5b7dc85..9716368 100644 --- a/Marks/Views/Library/LibraryKit.swift +++ b/Marks/Views/Library/LibraryKit.swift @@ -160,9 +160,9 @@ extension LibraryItem { } } - /// Cards give the stamp one 11pt monospaced line, roughly 14 characters. - /// 92 of 300 real domains are longer than that, so drop the subdomain: - /// `toolkit.artlist.io` -> `artlist.io`. The list still shows it in full. + /// Cards give the stamp one monospaced line, roughly 14 characters at the + /// card's width. 92 of 300 real domains are longer than that, so drop the + /// subdomain: `toolkit.artlist.io` -> `artlist.io`. The list shows it full. static func registered(_ host: String) -> String { let parts = host.split(separator: ".") guard parts.count > 2 else { return host } @@ -249,23 +249,23 @@ struct LibraryCard: View { let item: LibraryItem var body: some View { - VStack(alignment: .leading, spacing: 6) { + VStack(alignment: .leading, spacing: 8) { Text(item.cardDisplay) - .font(.system(size: 11, design: .serif)) + .font(.system(size: 16.5, design: .serif)) .foregroundStyle(item.inkOnSwatch) .multilineTextAlignment(.leading) .lineLimit(5) - .minimumScaleFactor(0.85) + .minimumScaleFactor(0.8) Spacer(minLength: 4) Text(item.stamp) - .font(.system(size: 11, design: .monospaced)) + .font(.system(size: 16.5, design: .monospaced)) .foregroundStyle(item.inkOnSwatch) .lineLimit(1) .truncationMode(.middle) } - .padding(9) + .padding(13) .frame(maxWidth: .infinity, alignment: .topLeading) - .aspectRatio(0.70, contentMode: .fit) + .aspectRatio(0.82, contentMode: .fit) .background(RoundedRectangle(cornerRadius: 5).fill(item.swatch)) } } @@ -304,23 +304,23 @@ struct LibraryTagStrip: View { } } label: { Image(systemName: "plus") - .font(.system(size: 12, weight: .light)) + .font(.system(size: 18, weight: .light)) .foregroundStyle(Paper.ink.opacity(0.6)) - .frame(width: 38, height: 30) + .frame(width: 50, height: 42) } Spacer(minLength: 0) } .padding(.horizontal, 18) } } - .frame(height: 30) + .frame(height: 42) } private func tab(_ filter: LibraryFilter) -> some View { let active = filter.id == selection return HStack(spacing: 7) { Text(filter.name) - .font(.system(size: 11, design: .monospaced)) + .font(.system(size: 16.5, design: .monospaced)) .foregroundStyle(active ? Paper.ink : Paper.ink.opacity(0.45)) .lineLimit(1) if filters.count > 1 { @@ -328,14 +328,14 @@ struct LibraryTagStrip: View { withAnimation(.spring(duration: 0.3, bounce: 0)) { close(filter) } } label: { Image(systemName: "xmark") - .font(.system(size: 8, weight: .medium)) + .font(.system(size: 12, weight: .medium)) .foregroundStyle(Paper.ink.opacity(active ? 0.5 : 0.25)) } .buttonStyle(.plain) } } - .padding(.horizontal, 11) - .frame(height: 30) + .padding(.horizontal, 15) + .frame(height: 42) .background(alignment: .bottom) { if active { // Paper fill sits 0.6pt proud so it erases the strip rule diff --git a/Marks/Views/Library/LibraryListRow.swift b/Marks/Views/Library/LibraryListRow.swift index 288b409..81db16e 100644 --- a/Marks/Views/Library/LibraryListRow.swift +++ b/Marks/Views/Library/LibraryListRow.swift @@ -27,7 +27,7 @@ struct LibraryListRow: View { HStack(alignment: .top, spacing: 12) { RoundedRectangle(cornerRadius: 3) .fill(item.swatch) - .frame(width: 26, height: 34) + .frame(width: 34, height: 46) .overlay(alignment: .topLeading) { if bookmark.unread { // Ink, not blue: the palette is the only color the @@ -35,15 +35,15 @@ struct LibraryListRow: View { // the chip it sits on. Circle() .fill(Paper.ink) - .frame(width: 7, height: 7) - .overlay(Circle().stroke(Paper.sheet, lineWidth: 1.5)) - .offset(x: -3, y: -3) + .frame(width: 10, height: 10) + .overlay(Circle().stroke(Paper.sheet, lineWidth: 2)) + .offset(x: -4, y: -4) } } VStack(alignment: .leading, spacing: 5) { Text(item.listDisplay) - .font(.system(size: 14, design: .serif)) + .font(.system(size: 21, design: .serif)) .foregroundStyle(Paper.ink) .lineLimit(2) .fixedSize(horizontal: false, vertical: true) @@ -55,13 +55,13 @@ struct LibraryListRow: View { for: bookmark.dateAdded, relativeTo: Date() )) } - .font(.system(size: 10, design: .monospaced)) + .font(.system(size: 15, design: .monospaced)) .foregroundStyle(Paper.ink.opacity(0.45)) .lineLimit(1) if let excerpt = rowExcerpt { Text(excerpt.text) - .font(.system(size: 12, design: .serif)) + .font(.system(size: 18, design: .serif)) .italic(excerpt.isAI) .foregroundStyle(Paper.ink.opacity(0.6)) .lineLimit(2) @@ -80,14 +80,14 @@ struct LibraryListRow: View { onPodcast() } label: { Image(systemName: podcastCached ? "headphones.circle.fill" : "headphones.circle") - .font(.system(size: 17, weight: .light)) + .font(.system(size: 25.5, weight: .light)) .foregroundStyle(Paper.ink.opacity(podcastCached ? 0.75 : 0.3)) } .buttonStyle(.plain) .sensoryFeedback(.impact(weight: .medium), trigger: podcastTapCount) } } - .padding(.vertical, 12) + .padding(.vertical, 14) .contentShape(Rectangle()) .overlay(alignment: .bottom) { if readingProgress > 0.02 { @@ -115,12 +115,12 @@ struct LibraryListRow: View { HStack(spacing: 5) { ForEach(effectiveTags, id: \.self) { tag in Text(tag) - .font(.system(size: 10, design: .monospaced)) + .font(.system(size: 15, design: .monospaced)) .foregroundStyle(Paper.ink.opacity(0.55)) - .padding(.horizontal, 6) - .padding(.vertical, 2) + .padding(.horizontal, 8) + .padding(.vertical, 3) .overlay( - RoundedRectangle(cornerRadius: 3) + RoundedRectangle(cornerRadius: 4) .stroke(Paper.rule.opacity(0.6), lineWidth: 0.6) ) } diff --git a/Marks/Views/Prototypes/LibraryView.swift b/Marks/Views/Prototypes/LibraryView.swift index b5f03a9..5672675 100644 --- a/Marks/Views/Prototypes/LibraryView.swift +++ b/Marks/Views/Prototypes/LibraryView.swift @@ -71,7 +71,7 @@ struct LibraryView: View { VStack(spacing: 14) { HStack(alignment: .firstTextBaseline) { Text("Library") - .font(.system(size: 34, weight: .regular, design: .serif)) + .font(.system(size: 51, weight: .regular, design: .serif)) .foregroundStyle(Paper.ink) Spacer(minLength: 12) Button { @@ -82,7 +82,7 @@ struct LibraryView: View { searchFocused = searching } label: { Image(systemName: searching ? "xmark" : "magnifyingglass") - .font(.system(size: 15, weight: .light)) + .font(.system(size: 22.5, weight: .light)) .foregroundStyle(Paper.ink) .frame(width: 28, height: 28) } @@ -92,7 +92,7 @@ struct LibraryView: View { if searching { VStack(spacing: 5) { TextField("", text: $query, prompt: searchPrompt) - .font(.system(size: 13, design: .monospaced)) + .font(.system(size: 19.5, design: .monospaced)) .foregroundStyle(Paper.ink) .textInputAutocapitalization(.never) .autocorrectionDisabled() @@ -109,7 +109,7 @@ struct LibraryView: View { private var searchPrompt: Text { Text("search the library") - .font(.system(size: 13, design: .monospaced)) + .font(.system(size: 19.5, design: .monospaced)) .foregroundColor(Paper.ink.opacity(0.35)) } @@ -121,12 +121,12 @@ struct LibraryView: View { withAnimation(.spring(duration: 0.42, bounce: 0.12)) { layout = option } } label: { Image(systemName: option.symbol) - .font(.system(size: 12, weight: .regular)) + .font(.system(size: 18, weight: .regular)) .foregroundStyle(active ? Paper.sheet : Paper.ink.opacity(0.55)) - .frame(width: 34, height: 26) + .frame(width: 46, height: 36) .background { if active { - RoundedRectangle(cornerRadius: 5) + RoundedRectangle(cornerRadius: 7) .fill(Paper.ink) .padding(2) .matchedGeometryEffect(id: "layoutPill", in: blocks) @@ -137,7 +137,7 @@ struct LibraryView: View { } } .overlay( - RoundedRectangle(cornerRadius: 7).stroke(Paper.rule, lineWidth: 0.6) + RoundedRectangle(cornerRadius: 9).stroke(Paper.rule, lineWidth: 0.6) ) } @@ -171,8 +171,8 @@ struct LibraryView: View { private var cardGrid: some View { LazyVGrid( - columns: Array(repeating: GridItem(.flexible(), spacing: 8), count: 3), - spacing: 8 + columns: Array(repeating: GridItem(.flexible(), spacing: 10), count: 2), + spacing: 10 ) { ForEach(Array(visibleItems.enumerated()), id: \.element.id) { index, item in LibraryCard(item: item) @@ -193,15 +193,15 @@ struct LibraryView: View { HStack(spacing: 12) { RoundedRectangle(cornerRadius: 3) .fill(item.swatch) - .frame(width: 26, height: 34) + .frame(width: 34, height: 46) .matchedGeometryEffect(id: item.id, in: blocks) VStack(alignment: .leading, spacing: 3) { Text(item.listDisplay) - .font(.system(size: 13, design: .serif)) + .font(.system(size: 19.5, design: .serif)) .foregroundStyle(Paper.ink) .lineLimit(1) Text(item.source) - .font(.system(size: 10, design: .monospaced)) + .font(.system(size: 15, design: .monospaced)) .foregroundStyle(Paper.ink.opacity(0.45)) .lineLimit(1) } @@ -210,7 +210,7 @@ struct LibraryView: View { // shows as the subtitle — so the right column carries the // primary tag instead of repeating it. Text(item.tags.first ?? item.stamp) - .font(.system(size: 11, design: .monospaced)) + .font(.system(size: 16.5, design: .monospaced)) .foregroundStyle(Paper.ink.opacity(0.55)) .lineLimit(1) }