From cdbec4aaf8701b2e072c083a3e6e1af583f43b95 Mon Sep 17 00:00:00 2001 From: Krishna Kumar Date: Sun, 26 Jul 2026 01:54:51 -0500 Subject: [PATCH] Scale library type up 50% MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every font size in the library design multiplied by 1.5 — card title and stamp, list title, meta, excerpt and tags, filter tabs, and the prototype's header. Geometry had to follow, or the larger type would have broken the layout it sits in: - The card grid drops from three columns to two. At 16.5pt in a 95pt column a card gets about nine characters per line and every title truncates; the text size is what sets the column count. - Filter tabs grow 30pt -> 42pt tall, the card gains padding and a slightly squarer aspect, and the list's color chip, unread dot and tag chips scale with the text they sit beside. Verified in both layouts against the live server. Suite passes. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01JgLHztZGaEHvS3KNeGQmRM --- Marks/Views/Library/LibraryGridView.swift | 7 +++-- Marks/Views/Library/LibraryKit.swift | 32 +++++++++++------------ Marks/Views/Library/LibraryListRow.swift | 26 +++++++++--------- Marks/Views/Prototypes/LibraryView.swift | 28 ++++++++++---------- 4 files changed, 48 insertions(+), 45 deletions(-) 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) }