Separate code font size

This commit is contained in:
Ian Gulliver
2026-10-21 10:15:26 -07:00
parent 1ab0ebad9f
commit b5f23e20c2
4 changed files with 35 additions and 18 deletions
+1 -1
View File
@@ -50,6 +50,6 @@ When the owner tells the lead "deploy byre", or anything that means the same, th
## UI look ## UI look
- Two fonts, bundled from `mac/fonts/`: Atkinson Hyperlegible Next for everything, and Atkinson Hyperlegible Mono only for text whose columns matter: code (blocks and inline), diffs, file contents, the terminal, raw tool input and output, and shell commands. Both follow the one font size setting. - Two fonts, bundled from `mac/fonts/`: Atkinson Hyperlegible Next for everything, and Atkinson Hyperlegible Mono only for text whose columns matter: code (blocks and inline), diffs, file contents, the terminal, raw tool input and output, and shell commands. Next follows the text size setting and Mono the code size setting.
- High contrast means readable text, not harshness. Body text is at least 7:1 against its background and secondary text at least 4.5:1, on soft backgrounds (off-white, dark slate; never pure black or white). Keep the frame quiet: 1px borders in a subtle tone, no dashed or heavy borders, no inverted blocks for selection, colour used sparingly for state and accent. The palette lives in `mac/Sources/Byre/Palette.swift`; change it there. - High contrast means readable text, not harshness. Body text is at least 7:1 against its background and secondary text at least 4.5:1, on soft backgrounds (off-white, dark slate; never pure black or white). Keep the frame quiet: 1px borders in a subtle tone, no dashed or heavy borders, no inverted blocks for selection, colour used sparingly for state and accent. The palette lives in `mac/Sources/Byre/Palette.swift`; change it there.
- Never show agent cost, turn duration, or turn counts anywhere in the UI. They stay in the event log for the API, not on screen. - Never show agent cost, turn duration, or turn counts anywhere in the UI. They stay in the event log for the API, not on screen.
+12 -7
View File
@@ -11,24 +11,29 @@ final class FontSize {
static let range = 9...20 static let range = 9...20
private(set) var body = PrefsRecord.defaultFontSize private(set) var body = PrefsRecord.defaultFontSize
private(set) var code = PrefsRecord.defaultFontSize
private init() { private init() {
load() load()
} }
func load() { func load() {
body = record()?.fontSize ?? PrefsRecord.defaultFontSize let r = record()
body = r?.fontSize ?? PrefsRecord.defaultFontSize
code = r?.codeFontSize ?? PrefsRecord.defaultFontSize
} }
func set(_ size: Int) { func set(body: Int, code: Int) {
if let r = record() { if let r = record() {
r.fontSize = size r.fontSize = body
r.codeFontSize = code
r.saved = Date() r.saved = Date()
} else { } else {
persistence.insert(PrefsRecord(fontSize: size)) persistence.insert(PrefsRecord(fontSize: body, codeFontSize: code))
} }
saveRecords() saveRecords()
body = size self.body = body
self.code = code
} }
private func record() -> PrefsRecord? { private func record() -> PrefsRecord? {
@@ -52,10 +57,10 @@ enum Fonts {
private static let fonts = Mutex<[String: CTFont]>([:]) private static let fonts = Mutex<[String: CTFont]>([:])
// Call sites give sizes relative to a 13pt body; the user's font size shifts them all. // Call sites give sizes relative to a 13pt body; the user's text or code size shifts them.
@MainActor @MainActor
private static func cached(_ size: CGFloat, _ weight: CGFloat, _ italic: Bool, _ mono: Bool) -> CTFont { private static func cached(_ size: CGFloat, _ weight: CGFloat, _ italic: Bool, _ mono: Bool) -> CTFont {
let size = size + CGFloat(FontSize.shared.body - 13) let size = size + CGFloat((mono ? FontSize.shared.code : FontSize.shared.body) - 13)
let key = "\(size) \(weight) \(italic) \(mono)" let key = "\(size) \(weight) \(italic) \(mono)"
return fonts.withLock { fonts in return fonts.withLock { fonts in
if let f = fonts[key] { if let f = fonts[key] {
+3 -1
View File
@@ -43,10 +43,12 @@ final class PrefsRecord {
static let defaultFontSize = 12 static let defaultFontSize = 12
var fontSize = PrefsRecord.defaultFontSize var fontSize = PrefsRecord.defaultFontSize
var codeFontSize = PrefsRecord.defaultFontSize
var saved = Date.distantPast var saved = Date.distantPast
init(fontSize: Int) { init(fontSize: Int, codeFontSize: Int) {
self.fontSize = fontSize self.fontSize = fontSize
self.codeFontSize = codeFontSize
saved = Date() saved = Date()
} }
} }
+19 -9
View File
@@ -28,10 +28,15 @@ struct SettingsView: View {
.fixedSize(horizontal: false, vertical: true) .fixedSize(horizontal: false, vertical: true)
ServerColorPicker() ServerColorPicker()
heading("Font size") heading("Font size")
Text("The size of body text, on every Mac you use. Other text grows and shrinks with it.") Text("The size of body text and of code, on every Mac you use. Other text grows and shrinks with them.")
.foregroundStyle(Palette.muted) .foregroundStyle(Palette.muted)
.fixedSize(horizontal: false, vertical: true) .fixedSize(horizontal: false, vertical: true)
FontSizeStepper() FontSizeStepper(label: "Text", size: FontSize.shared.body) { n in
FontSize.shared.set(body: n, code: FontSize.shared.code)
}
FontSizeStepper(label: "Code", size: FontSize.shared.code) { n in
FontSize.shared.set(body: FontSize.shared.body, code: n)
}
heading("Notifications") heading("Notifications")
DeviceNotifications() DeviceNotifications()
PrefsBox() PrefsBox()
@@ -98,21 +103,26 @@ private struct ServerColorPicker: View {
} }
private struct FontSizeStepper: View { private struct FontSizeStepper: View {
let label: String
let size: Int
let set: (Int) -> Void
var body: some View { var body: some View {
let fonts = FontSize.shared
HStack(spacing: 8) { HStack(spacing: 8) {
Text(label)
.frame(width: 48, alignment: .leading)
Button("−") { Button("−") {
fonts.set(fonts.body - 1) set(size - 1)
} }
.buttonStyle(WebButtonStyle()) .buttonStyle(WebButtonStyle())
.disabled(fonts.body <= FontSize.range.lowerBound) .disabled(size <= FontSize.range.lowerBound)
Text("\(fonts.body) pt") Text("\(size) pt")
.monospacedDigit() .monospacedDigit()
Button("+") { Button("+") {
fonts.set(fonts.body + 1) set(size + 1)
} }
.buttonStyle(WebButtonStyle()) .buttonStyle(WebButtonStyle())
.disabled(fonts.body >= FontSize.range.upperBound) .disabled(size >= FontSize.range.upperBound)
} }
.padding(.top, 8) .padding(.top, 8)
} }
@@ -123,7 +133,7 @@ private struct SyncState: View {
TimelineView(.periodic(from: .now, by: 30)) { _ in TimelineView(.periodic(from: .now, by: 30)) { _ in
if let sync = Servers.shared.sync { if let sync = Servers.shared.sync {
if sync.ok { if sync.ok {
Text("This Mac shares its servers, window colors, font size, drafts and task visits through iCloud. Last synced \(ago(sync.at)).") Text("This Mac shares its servers, window colors, font sizes, drafts and task visits through iCloud. Last synced \(ago(sync.at)).")
.fixedSize(horizontal: false, vertical: true) .fixedSize(horizontal: false, vertical: true)
} else { } else {
Text("iCloud sync is failing on this Mac, so changes made here aren't reaching your other Macs. Failed \(ago(sync.at)): \(sync.error ?? "")") Text("iCloud sync is failing on this Mac, so changes made here aren't reaching your other Macs. Failed \(ago(sync.at)): \(sync.error ?? "")")