refactor(settings): ClideSettings — one live-preferences facade (D-101)

Introduce ClideSettings, a single widget-facing facade for the app's live
user preferences, namespaced by concern: ClideSettings.fonts.monoOf(context)
/ .fonts.uiOf(context), ClideSettings.theme.of(context),
ClideSettings.i18n.of(context). "Plumb once, use many."

Fonts are carried by a new root-provided ClideSettingsScope (resolved from the
font settings in root_shell, rebuilt on change); theme and i18n delegate to
their existing live providers (ClideTheme / the I18n service) so there's one
source of truth and their many consumers migrate incrementally rather than in
a big-bang. Reads outside a scope fall back to the bundled font defaults, so a
widget renders without a provider (isolated tests).

Migrate ~93 monospace-font call sites across 33 files from the clideMonoFamily
const to ClideSettings.fonts.monoOf(context) — pure refactor, identical family
when no override is set. 11 context-less helper sites (markdown static spans,
a few top-level/static builders) keep the const for now and are tracked in
T-472. Records D-101; updates the ui-design skill's font-family rule.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-17 20:57:16 +02:00
co-authored by Claude Opus 4.8
parent 8ad5c9ba6e
commit a7ea38acde
44 changed files with 452 additions and 206 deletions
+5 -2
View File
@@ -37,10 +37,13 @@ class ClaudeBanner extends StatelessWidget {
const SizedBox(height: 18),
ClideText('Claude', fontSize: clideFontDialogTitle, color: claudeAccent, fontWeight: FontWeight.w500),
const SizedBox(height: 2),
ClideText(role, fontSize: clideFontSmall, muted: true, fontFamily: clideMonoFamily),
ClideText(role, fontSize: clideFontSmall, muted: true, fontFamily: ClideSettings.fonts.monoOf(context)),
const SizedBox(height: 16),
if (ws != null) ClideText(ws, fontSize: clideFontCaption, muted: true),
if (statusLine != null) ...[const SizedBox(height: 2), ClideText(statusLine!, fontSize: clideFontSmall, muted: true, fontFamily: clideMonoFamily)],
if (statusLine != null) ...[
const SizedBox(height: 2),
ClideText(statusLine!, fontSize: clideFontSmall, muted: true, fontFamily: ClideSettings.fonts.monoOf(context)),
],
const SizedBox(height: 16),
const ClideText('Warming up — your conversation will appear here.', fontSize: clideFontSmall, muted: true),
],
+10 -3
View File
@@ -132,12 +132,13 @@ class _ClaudePaneState extends State<ClaudePane> {
final seg = statusSegmentsAroundMode(_status);
final mode = _status.permissionMode;
Widget text(String t) => ClideText(t, fontSize: clideFontSmall, fontFamily: clideMonoFamily, color: tokens.statusBarForeground, maxLines: 1);
Widget text(String t) =>
ClideText(t, fontSize: clideFontSmall, fontFamily: ClideSettings.fonts.monoOf(context), color: tokens.statusBarForeground, maxLines: 1);
final children = <Widget>[];
void add(Widget w) {
if (children.isNotEmpty) {
children.add(ClideText(' · ', fontSize: clideFontSmall, fontFamily: clideMonoFamily, color: tokens.globalTextMuted, maxLines: 1));
children.add(ClideText(' · ', fontSize: clideFontSmall, fontFamily: ClideSettings.fonts.monoOf(context), color: tokens.globalTextMuted, maxLines: 1));
}
children.add(w);
}
@@ -857,7 +858,13 @@ class _ModeBadge extends StatelessWidget {
return Semantics(
label: 'permission mode: ${permissionModeLabel(mode)}',
excludeSemantics: true,
child: ClideText(permissionModeLabel(mode), fontSize: clideFontSmall, fontFamily: clideMonoFamily, color: permissionModeColor(mode, tokens), maxLines: 1),
child: ClideText(
permissionModeLabel(mode),
fontSize: clideFontSmall,
fontFamily: ClideSettings.fonts.monoOf(context),
color: permissionModeColor(mode, tokens),
maxLines: 1,
),
);
}
}
@@ -241,13 +241,13 @@ class _ConversationCardState extends State<ConversationCard> {
if (widget.collapsible) _caret(tokens),
// Header label size matches ClideCollapserCard (clideFontCaption) so
// neighbouring cards in the conversation stream align (T-344).
ClideText(widget.label, fontSize: clideFontCaption, color: widget.accent, fontFamily: clideMonoFamily),
ClideText(widget.label, fontSize: clideFontCaption, color: widget.accent, fontFamily: ClideSettings.fonts.monoOf(context)),
// While collapsed, show a one-line gist next to the label so the card
// still says what it holds.
if (_collapsed && summary != null) ...[
const SizedBox(width: 10),
Expanded(
child: ClideText(summary, fontSize: clideFontMeta, color: tokens.globalTextMuted, fontFamily: clideMonoFamily, maxLines: 1),
child: ClideText(summary, fontSize: clideFontMeta, color: tokens.globalTextMuted, fontFamily: ClideSettings.fonts.monoOf(context), maxLines: 1),
),
] else
const Spacer(),
@@ -322,7 +322,7 @@ class _ConversationCardState extends State<ConversationCard> {
padding: const EdgeInsets.only(top: 8, bottom: 4),
child: Row(
children: [
ClideText(label, fontSize: clideFontMeta, color: tokens.globalTextMuted, fontFamily: clideMonoFamily),
ClideText(label, fontSize: clideFontMeta, color: tokens.globalTextMuted, fontFamily: ClideSettings.fonts.monoOf(context)),
const SizedBox(width: 8),
Expanded(child: Container(height: 1, color: tokens.panelBorder)),
],
@@ -349,7 +349,7 @@ class _ConversationCardState extends State<ConversationCard> {
onTap: items[i].onTap,
builder: (_, hovered, pressed) => Padding(
padding: const EdgeInsets.only(left: 10),
child: ClideText(items[i].label, fontSize: clideFontMeta, color: tokens.globalTextMuted, fontFamily: clideMonoFamily),
child: ClideText(items[i].label, fontSize: clideFontMeta, color: tokens.globalTextMuted, fontFamily: ClideSettings.fonts.monoOf(context)),
),
),
),
@@ -147,9 +147,14 @@ class _ModelPickerCardState extends State<ModelPickerCard> {
children: [
Row(
children: [
ClideText(widget.title, fontSize: clideFontSmall, fontFamily: clideMonoFamily, color: tokens.statusInfo),
ClideText(widget.title, fontSize: clideFontSmall, fontFamily: ClideSettings.fonts.monoOf(context), color: tokens.statusInfo),
const Spacer(),
ClideText('↑↓ · 1-${widget.models.length} · Enter · Esc', fontSize: clideFontMeta, fontFamily: clideMonoFamily, color: tokens.globalTextMuted),
ClideText(
'↑↓ · 1-${widget.models.length} · Enter · Esc',
fontSize: clideFontMeta,
fontFamily: ClideSettings.fonts.monoOf(context),
color: tokens.globalTextMuted,
),
],
),
const SizedBox(height: 8),
+13 -5
View File
@@ -122,7 +122,7 @@ class _ToolPromptCardState extends State<ToolPromptCard> {
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
ClideText(label, fontSize: clideFontSmall, fontFamily: clideMonoFamily, color: accent),
ClideText(label, fontSize: clideFontSmall, fontFamily: ClideSettings.fonts.monoOf(context), color: accent),
const SizedBox(height: 8),
...children,
],
@@ -362,14 +362,21 @@ class _ToolPromptCardState extends State<ToolPromptCard> {
border: Border.all(color: tokens.statusInfo),
borderRadius: BorderRadius.circular(4),
),
child: ClideText(text, fontSize: clideFontMeta, fontFamily: clideMonoFamily, color: tokens.globalForeground),
child: ClideText(text, fontSize: clideFontMeta, fontFamily: ClideSettings.fonts.monoOf(context), color: tokens.globalForeground),
),
);
} else {
chips.add(ClideText(text, fontSize: clideFontMeta, fontFamily: clideMonoFamily, color: done ? tokens.statusSuccess : tokens.globalTextMuted));
chips.add(
ClideText(
text,
fontSize: clideFontMeta,
fontFamily: ClideSettings.fonts.monoOf(context),
color: done ? tokens.statusSuccess : tokens.globalTextMuted,
),
);
}
}
chips.add(ClideText('Review', fontSize: clideFontMeta, fontFamily: clideMonoFamily, color: tokens.globalTextMuted));
chips.add(ClideText('Review', fontSize: clideFontMeta, fontFamily: ClideSettings.fonts.monoOf(context), color: tokens.globalTextMuted));
chips.add(ClideText('', color: tokens.globalTextMuted, fontSize: 15));
return Wrap(spacing: 10, runSpacing: 6, crossAxisAlignment: WrapCrossAlignment.center, children: chips);
}
@@ -399,7 +406,8 @@ class _ToolPromptCardState extends State<ToolPromptCard> {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (q.header.isNotEmpty) ClideText(q.header.toUpperCase(), fontSize: clideFontMeta, fontFamily: clideMonoFamily, color: tokens.globalTextMuted),
if (q.header.isNotEmpty)
ClideText(q.header.toUpperCase(), fontSize: clideFontMeta, fontFamily: ClideSettings.fonts.monoOf(context), color: tokens.globalTextMuted),
Padding(
padding: const EdgeInsets.only(top: 2, bottom: 6),
child: ClideText(q.question, color: tokens.globalForeground),
+1 -1
View File
@@ -178,7 +178,7 @@ class _TeammateTile extends StatelessWidget {
children: [
Container(width: 3, height: 13, color: accent),
const SizedBox(width: 6),
ClideText(member.name, fontSize: clideFontSmall, color: accent, fontFamily: clideMonoFamily),
ClideText(member.name, fontSize: clideFontSmall, color: accent, fontFamily: ClideSettings.fonts.monoOf(context)),
const SizedBox(width: 8),
Expanded(
child: ClideText(
@@ -148,19 +148,22 @@ class _DecisionDetailViewState extends State<DecisionDetailView> {
),
),
const SizedBox(width: 8),
ClideText(id, fontSize: clideFontSmall, color: typeColor, fontFamily: clideMonoFamily),
ClideText(id, fontSize: clideFontSmall, color: typeColor, fontFamily: ClideSettings.fonts.monoOf(context)),
const Spacer(),
if (domain != null)
Container(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
decoration: BoxDecoration(color: tokens.panelBorder, borderRadius: BorderRadius.circular(3)),
child: ClideText(domain, fontSize: clideFontBadge, color: tokens.globalTextMuted, fontFamily: clideMonoFamily),
child: ClideText(domain, fontSize: clideFontBadge, color: tokens.globalTextMuted, fontFamily: ClideSettings.fonts.monoOf(context)),
),
],
),
const SizedBox(height: 8),
ClideText(title, fontSize: 15, fontWeight: FontWeight.w500),
if (date != null) ...[const SizedBox(height: 6), ClideText(date, muted: true, fontSize: clideFontSmall, fontFamily: clideMonoFamily)],
if (date != null) ...[
const SizedBox(height: 6),
ClideText(date, muted: true, fontSize: clideFontSmall, fontFamily: ClideSettings.fonts.monoOf(context)),
],
if (status != null && status != 'active') ...[const SizedBox(height: 8), _StatusBadge(status: status, tokens: tokens)],
],
),
@@ -168,7 +171,7 @@ class _DecisionDetailViewState extends State<DecisionDetailView> {
if (body != null && body.isNotEmpty) ...[const SizedBox(height: 12), ClideMarkdown(body, onRecordTap: (id) => _navigateToRecord(context, id))],
if (refs.isNotEmpty) ...[
const SizedBox(height: 16),
ClideText('CROSS-REFERENCES', fontSize: clideFontSmall, color: tokens.sidebarSectionHeader, fontFamily: clideMonoFamily),
ClideText('CROSS-REFERENCES', fontSize: clideFontSmall, color: tokens.sidebarSectionHeader, fontFamily: ClideSettings.fonts.monoOf(context)),
const SizedBox(height: 6),
for (final ref in refs) _RefCard(ref: ref, tokens: tokens),
],
@@ -201,7 +204,7 @@ class _RefCard extends StatelessWidget {
),
child: Row(
children: [
ClideText(targetId, fontSize: clideFontSmall, color: tokens.globalFocus, fontFamily: clideMonoFamily),
ClideText(targetId, fontSize: clideFontSmall, color: tokens.globalFocus, fontFamily: ClideSettings.fonts.monoOf(context)),
const SizedBox(width: 8),
ClideText(refType, fontSize: clideFontSmall, color: tokens.globalTextMuted),
],
@@ -227,7 +230,7 @@ class _StatusBadge extends StatelessWidget {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
decoration: BoxDecoration(color: color.withAlpha(0x30), borderRadius: BorderRadius.circular(3)),
child: ClideText(status.toUpperCase(), fontSize: clideFontBadge, color: color, fontFamily: clideMonoFamily),
child: ClideText(status.toUpperCase(), fontSize: clideFontBadge, color: color, fontFamily: ClideSettings.fonts.monoOf(context)),
);
}
}
@@ -309,9 +309,10 @@ class _DecisionCard extends StatelessWidget {
),
),
const SizedBox(width: 6),
ClideText(entry.id, fontSize: clideFontSmall, color: tokens.globalTextMuted, fontFamily: clideMonoFamily),
ClideText(entry.id, fontSize: clideFontSmall, color: tokens.globalTextMuted, fontFamily: ClideSettings.fonts.monoOf(context)),
const Spacer(),
if (entry.domain != null) ClideText(entry.domain!, fontSize: clideFontBadge, color: tokens.globalTextMuted, fontFamily: clideMonoFamily),
if (entry.domain != null)
ClideText(entry.domain!, fontSize: clideFontBadge, color: tokens.globalTextMuted, fontFamily: ClideSettings.fonts.monoOf(context)),
],
),
const SizedBox(height: 4),
@@ -321,7 +322,7 @@ class _DecisionCard extends StatelessWidget {
Container(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
decoration: BoxDecoration(color: tokens.statusSuccess.withAlpha(0x30), borderRadius: BorderRadius.circular(3)),
child: ClideText('resolved', fontSize: clideFontBadge, color: tokens.statusSuccess, fontFamily: clideMonoFamily),
child: ClideText('resolved', fontSize: clideFontBadge, color: tokens.statusSuccess, fontFamily: ClideSettings.fonts.monoOf(context)),
),
],
],
+1 -1
View File
@@ -83,7 +83,7 @@ class _DeepLinkConfirmDialog extends StatelessWidget {
const SizedBox(height: 6),
ClideText('A clide:// link from outside the app is asking to:', muted: true, fontSize: clideFontSmall),
const SizedBox(height: 8),
ClideText(action.describe, fontFamily: clideMonoFamily, fontSize: clideFontSmall, color: t.globalForeground),
ClideText(action.describe, fontFamily: ClideSettings.fonts.monoOf(context), fontSize: clideFontSmall, color: t.globalForeground),
const SizedBox(height: 8),
ClideText('Only allow this if you trust where the link came from.', fontSize: clideFontMeta, color: t.statusWarning),
const SizedBox(height: 14),
+12 -5
View File
@@ -250,7 +250,7 @@ class _HunkView extends StatelessWidget {
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 2),
child: ClideText(header, fontSize: clideFontMono, muted: true, fontFamily: clideMonoFamily),
child: ClideText(header, fontSize: clideFontMono, muted: true, fontFamily: ClideSettings.fonts.monoOf(context)),
),
for (final lineObj in lines) _DiffLineRow(line: (lineObj as Map).cast<String, Object?>()),
],
@@ -294,7 +294,7 @@ class _DiffLineRow extends StatelessWidget {
oldLineNo != null ? '${oldLineNo.toInt()}' : '',
fontSize: clideFontMono,
muted: true,
fontFamily: clideMonoFamily,
fontFamily: ClideSettings.fonts.monoOf(context),
textAlign: TextAlign.right,
),
),
@@ -305,15 +305,22 @@ class _DiffLineRow extends StatelessWidget {
newLineNo != null ? '${newLineNo.toInt()}' : '',
fontSize: clideFontMono,
muted: true,
fontFamily: clideMonoFamily,
fontFamily: ClideSettings.fonts.monoOf(context),
textAlign: TextAlign.right,
),
),
const SizedBox(width: 4),
ClideText(prefix, fontSize: clideFontMono, color: fg, fontFamily: clideMonoFamily),
ClideText(prefix, fontSize: clideFontMono, color: fg, fontFamily: ClideSettings.fonts.monoOf(context)),
const SizedBox(width: 2),
Expanded(
child: ClideText(text, fontSize: clideFontMono, color: fg, fontFamily: clideMonoFamily, maxLines: 1, overflow: TextOverflow.clip),
child: ClideText(
text,
fontSize: clideFontMono,
color: fg,
fontFamily: ClideSettings.fonts.monoOf(context),
maxLines: 1,
overflow: TextOverflow.clip,
),
),
],
),
+6 -1
View File
@@ -371,7 +371,12 @@ class _TextBody extends StatelessWidget {
@override
Widget build(BuildContext context) {
final style = TextStyle(color: foreground, fontSize: clideFontMono, fontFamily: clideMonoFamily, fontFamilyFallback: clideMonoFamilyFallback);
final style = TextStyle(
color: foreground,
fontSize: clideFontMono,
fontFamily: ClideSettings.fonts.monoOf(context),
fontFamilyFallback: clideMonoFamilyFallback,
);
final editable = EditableText(
controller: controller,
focusNode: focus,
@@ -48,7 +48,7 @@ class ExtensionsNotice extends StatelessWidget {
i.string('notice.tracked', namespace: ns, placeholder: 'Tracked in T-8 (Tier 6) · D-16'),
color: tokens.globalTextMuted,
fontSize: clideFontCaption,
fontFamily: clideMonoFamily,
fontFamily: ClideSettings.fonts.monoOf(context),
),
],
);
+7 -2
View File
@@ -164,7 +164,12 @@ class _BranchPickerState extends State<_BranchPicker> {
child: Row(
children: [
Expanded(
child: ClideText('Switch branch', fontSize: clideFontCaption, color: tokens.globalTextMuted, fontFamily: clideMonoFamily),
child: ClideText(
'Switch branch',
fontSize: clideFontCaption,
color: tokens.globalTextMuted,
fontFamily: ClideSettings.fonts.monoOf(context),
),
),
GestureDetector(
onTap: () => widget.onDismiss(),
@@ -229,7 +234,7 @@ class _BranchRow extends StatelessWidget {
Expanded(
child: ClideText(
name,
fontFamily: clideMonoFamily,
fontFamily: ClideSettings.fonts.monoOf(context),
fontSize: clideFontMono,
color: current ? tokens.globalForeground : tokens.listItemForeground,
),
+2 -2
View File
@@ -67,7 +67,7 @@ class _Kv extends StatelessWidget {
children: [
SizedBox(width: 90, child: ClideText(label, fontSize: 13, color: tokens.globalTextMuted)),
Expanded(
child: ClideText(value, fontSize: 13, fontFamily: clideMonoFamily, maxLines: 1, overflow: TextOverflow.ellipsis),
child: ClideText(value, fontSize: 13, fontFamily: ClideSettings.fonts.monoOf(context), maxLines: 1, overflow: TextOverflow.ellipsis),
),
],
),
@@ -106,7 +106,7 @@ class _Licenses extends StatelessWidget {
child: ClideText(
'${d.name} ${d.version} · ${d.license}',
fontSize: 12,
fontFamily: clideMonoFamily,
fontFamily: ClideSettings.fonts.monoOf(context),
color: tokens.globalTextMuted,
maxLines: 1,
overflow: TextOverflow.ellipsis,
+6 -1
View File
@@ -137,7 +137,12 @@ class _OpenFolderDialogState extends State<OpenFolderDialog> {
child: EditableText(
controller: _controller,
focusNode: _focus,
style: TextStyle(color: tokens.globalForeground, fontSize: 14, fontFamily: clideMonoFamily, fontFamilyFallback: clideMonoFamilyFallback),
style: TextStyle(
color: tokens.globalForeground,
fontSize: 14,
fontFamily: ClideSettings.fonts.monoOf(context),
fontFamilyFallback: clideMonoFamilyFallback,
),
cursorColor: tokens.globalForeground,
backgroundCursorColor: tokens.globalTextMuted,
onSubmitted: (_) => unawaited(_submit()),
+6 -1
View File
@@ -162,7 +162,12 @@ class _TopMenuButtonState extends State<_TopMenuButton> {
label: node.title,
enabled: node.enabled,
trailing: node.keybinding != null
? ClideText(node.keybinding!, fontSize: clideFontSmall, fontFamily: clideMonoFamily, color: ClideTheme.of(ctx).surface.globalTextMuted)
? ClideText(
node.keybinding!,
fontSize: clideFontSmall,
fontFamily: ClideSettings.fonts.monoOf(context),
color: ClideTheme.of(ctx).surface.globalTextMuted,
)
: null,
onSelect: () => unawaited(widget.kernel.commands.execute(node.commandId)),
)
+4 -4
View File
@@ -217,11 +217,11 @@ class _LogRow extends StatelessWidget {
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ClideText('$hh:$mm:$ss', fontSize: clideFontMono, color: tokens.globalTextMuted, fontFamily: clideMonoFamily),
ClideText('$hh:$mm:$ss', fontSize: clideFontMono, color: tokens.globalTextMuted, fontFamily: ClideSettings.fonts.monoOf(context)),
const SizedBox(width: 8),
SizedBox(
width: 48,
child: ClideText(record.level.name.toUpperCase(), fontSize: clideFontMono, color: fg, fontFamily: clideMonoFamily),
child: ClideText(record.level.name.toUpperCase(), fontSize: clideFontMono, color: fg, fontFamily: ClideSettings.fonts.monoOf(context)),
),
const SizedBox(width: 8),
SizedBox(
@@ -230,14 +230,14 @@ class _LogRow extends StatelessWidget {
record.source,
fontSize: clideFontMono,
color: tokens.globalTextMuted,
fontFamily: clideMonoFamily,
fontFamily: ClideSettings.fonts.monoOf(context),
maxLines: 1,
overflow: TextOverflow.clip,
),
),
const SizedBox(width: 8),
Expanded(
child: ClideText(record.message, fontSize: clideFontMono, color: fg, fontFamily: clideMonoFamily),
child: ClideText(record.message, fontSize: clideFontMono, color: fg, fontFamily: ClideSettings.fonts.monoOf(context)),
),
],
),
+1 -1
View File
@@ -228,7 +228,7 @@ class _ScoreBar extends StatelessWidget {
),
),
const SizedBox(width: 6),
ClideText('${(score * 100).round()}%', fontSize: clideFontBadge, muted: true, fontFamily: clideMonoFamily),
ClideText('${(score * 100).round()}%', fontSize: clideFontBadge, muted: true, fontFamily: ClideSettings.fonts.monoOf(context)),
],
);
}
+2 -2
View File
@@ -113,7 +113,7 @@ class _ProblemRow extends StatelessWidget {
children: [
Row(
children: [
ClideText(problem.source, fontSize: clideFontMono, color: tokens.statusWarning, fontFamily: clideMonoFamily),
ClideText(problem.source, fontSize: clideFontMono, color: tokens.statusWarning, fontFamily: ClideSettings.fonts.monoOf(context)),
const SizedBox(width: 6),
Expanded(child: ClideText(problem.message, color: tokens.sidebarForeground, maxLines: 2)),
],
@@ -121,7 +121,7 @@ class _ProblemRow extends StatelessWidget {
if (problem.hint != null)
Padding(
padding: const EdgeInsets.only(left: 44, top: 2),
child: ClideText(problem.hint!, fontSize: clideFontMono, muted: true, fontFamily: clideMonoFamily),
child: ClideText(problem.hint!, fontSize: clideFontMono, muted: true, fontFamily: ClideSettings.fonts.monoOf(context)),
),
],
),
@@ -255,7 +255,7 @@ class _Toggle extends StatelessWidget {
),
child: ClideText(
label,
fontFamily: clideMonoFamily,
fontFamily: ClideSettings.fonts.monoOf(context),
fontSize: clideFontCaption,
color: active ? tokens.listItemSelectedForeground : tokens.sidebarForeground,
),
@@ -344,7 +344,7 @@ class _MatchRow extends StatelessWidget {
children: [
SizedBox(
width: 36,
child: ClideText('${match.line}', fontSize: clideFontCaption, fontFamily: clideMonoFamily, color: tokens.globalTextMuted),
child: ClideText('${match.line}', fontSize: clideFontCaption, fontFamily: ClideSettings.fonts.monoOf(context), color: tokens.globalTextMuted),
),
Expanded(child: replacement.isEmpty ? _highlighted() : _preview()),
],
@@ -128,7 +128,12 @@ class _SectionCard extends StatelessWidget {
if (section.label.isNotEmpty)
Padding(
padding: const EdgeInsets.only(left: 2, bottom: 6),
child: ClideText(section.label.toUpperCase(), fontSize: clideFontCaption, color: tokens.sidebarSectionHeader, fontFamily: clideMonoFamily),
child: ClideText(
section.label.toUpperCase(),
fontSize: clideFontCaption,
color: tokens.sidebarSectionHeader,
fontFamily: ClideSettings.fonts.monoOf(context),
),
),
ClideSurface(
// Card surface (surface.md): panelHeader resolves to the `surface`
@@ -440,7 +445,7 @@ class _EditControlState extends State<_EditControl> {
child: EditableText(
controller: _controller,
focusNode: _focus,
style: TextStyle(fontFamily: clideMonoFamily, fontSize: clideFontMono, color: tokens.globalForeground),
style: TextStyle(fontFamily: ClideSettings.fonts.monoOf(context), fontSize: clideFontMono, color: tokens.globalForeground),
cursorColor: tokens.globalFocus,
backgroundCursorColor: tokens.globalTextMuted,
maxLines: 1,
@@ -202,7 +202,7 @@ class _CategoryRail extends StatelessWidget {
i.string('rail.header', namespace: SettingsModal.ns, placeholder: 'Categories'),
fontSize: clideFontCaption,
color: tokens.sidebarSectionHeader,
fontFamily: clideMonoFamily,
fontFamily: ClideSettings.fonts.monoOf(context),
),
),
Expanded(
@@ -75,7 +75,7 @@ class _SettingsViewState extends State<SettingsView> {
i.string('section.appearance', namespace: SettingsView.ns, placeholder: 'Appearance'),
fontSize: clideFontCaption,
color: tokens.sidebarSectionHeader,
fontFamily: clideMonoFamily,
fontFamily: ClideSettings.fonts.monoOf(context),
),
const SizedBox(height: 8),
_HighContrastToggle(
@@ -148,16 +148,17 @@ class _TicketHeader extends StatelessWidget {
),
),
const SizedBox(width: 8),
ClideText(detail.id, fontSize: clideFontSmall, color: typeColor, fontFamily: clideMonoFamily),
ClideText(detail.id, fontSize: clideFontSmall, color: typeColor, fontFamily: ClideSettings.fonts.monoOf(context)),
const Spacer(),
if (detail.priority != null) ClideText(detail.priority!, fontSize: clideFontSmall, color: tokens.globalTextMuted, fontFamily: clideMonoFamily),
if (detail.priority != null)
ClideText(detail.priority!, fontSize: clideFontSmall, color: tokens.globalTextMuted, fontFamily: ClideSettings.fonts.monoOf(context)),
],
),
const SizedBox(height: 8),
ClideText(detail.title, fontSize: 15, fontWeight: FontWeight.w500),
if (detail.assignedTo != null) ...[
const SizedBox(height: 6),
ClideText('assigned: ${detail.assignedTo}', muted: true, fontSize: clideFontSmall, fontFamily: clideMonoFamily),
ClideText('assigned: ${detail.assignedTo}', muted: true, fontSize: clideFontSmall, fontFamily: ClideSettings.fonts.monoOf(context)),
],
],
),
@@ -206,7 +207,7 @@ class _StatusControls extends StatelessWidget {
border: Border.all(color: active ? tokens.statusInfo : tokens.panelBorder),
),
alignment: Alignment.center,
child: ClideText(_shortLabel(s), fontSize: clideFontBadge, color: color, fontFamily: clideMonoFamily),
child: ClideText(_shortLabel(s), fontSize: clideFontBadge, color: color, fontFamily: ClideSettings.fonts.monoOf(context)),
);
},
),
@@ -234,7 +235,7 @@ class _SectionLabel extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ClideText(label, fontSize: clideFontSmall, color: tokens.sidebarSectionHeader, fontFamily: clideMonoFamily);
return ClideText(label, fontSize: clideFontSmall, color: tokens.sidebarSectionHeader, fontFamily: ClideSettings.fonts.monoOf(context));
}
}
@@ -270,7 +271,7 @@ class _CompactCard extends StatelessWidget {
decoration: BoxDecoration(color: typeColor, shape: BoxShape.circle),
),
const SizedBox(width: 6),
ClideText(id, fontSize: clideFontSmall, color: tokens.globalTextMuted, fontFamily: clideMonoFamily),
ClideText(id, fontSize: clideFontSmall, color: tokens.globalTextMuted, fontFamily: ClideSettings.fonts.monoOf(context)),
const SizedBox(width: 8),
Expanded(child: ClideText(title, fontSize: clideFontSmall)),
],
@@ -320,9 +321,10 @@ class _DecisionRefCard extends StatelessWidget {
decoration: BoxDecoration(color: color, shape: BoxShape.circle),
),
const SizedBox(width: 6),
ClideText(id, fontSize: clideFontSmall, color: color, fontFamily: clideMonoFamily),
ClideText(id, fontSize: clideFontSmall, color: color, fontFamily: ClideSettings.fonts.monoOf(context)),
const Spacer(),
if (domain != null) ClideText(domain, fontSize: clideFontBadge, color: tokens.globalTextMuted, fontFamily: clideMonoFamily),
if (domain != null)
ClideText(domain, fontSize: clideFontBadge, color: tokens.globalTextMuted, fontFamily: ClideSettings.fonts.monoOf(context)),
],
),
const SizedBox(height: 3),
+15 -4
View File
@@ -314,7 +314,12 @@ class _TypeChip extends StatelessWidget {
decoration: BoxDecoration(color: dotColor, shape: BoxShape.circle),
),
const SizedBox(width: 6),
ClideText(label, fontSize: clideFontSmall, fontFamily: clideMonoFamily, color: active ? tokens.globalForeground : tokens.globalTextMuted),
ClideText(
label,
fontSize: clideFontSmall,
fontFamily: ClideSettings.fonts.monoOf(context),
color: active ? tokens.globalForeground : tokens.globalTextMuted,
),
],
),
),
@@ -386,7 +391,7 @@ class _TicketCard extends StatelessWidget {
entry.parentId!,
fontSize: clideFontSmall,
color: hovered ? tokens.globalForeground : tokens.globalTextMuted,
fontFamily: clideMonoFamily,
fontFamily: ClideSettings.fonts.monoOf(context),
),
),
),
@@ -402,7 +407,13 @@ class _TicketCard extends StatelessWidget {
),
),
const SizedBox(width: 6),
ClideText(entry.id, fontSize: clideFontSmall, color: tokens.globalForeground, fontFamily: clideMonoFamily, fontWeight: FontWeight.w600),
ClideText(
entry.id,
fontSize: clideFontSmall,
color: tokens.globalForeground,
fontFamily: ClideSettings.fonts.monoOf(context),
fontWeight: FontWeight.w600,
),
],
),
const SizedBox(height: 4),
@@ -480,7 +491,7 @@ class _StatusBadge extends StatelessWidget {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
decoration: BoxDecoration(color: color.withAlpha(0x30), borderRadius: BorderRadius.circular(3)),
child: ClideText(label, fontSize: clideFontBadge, color: color, fontFamily: clideMonoFamily),
child: ClideText(label, fontSize: clideFontBadge, color: color, fontFamily: ClideSettings.fonts.monoOf(context)),
);
}
}
+6 -1
View File
@@ -20,7 +20,12 @@ class VimModeIndicator extends StatelessWidget {
final tokens = ClideTheme.of(context).surface;
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: ClideText('-- ${service.mode.label} --', fontFamily: clideMonoFamily, fontSize: clideFontCaption, color: tokens.statusBarForeground),
child: ClideText(
'-- ${service.mode.label} --',
fontFamily: ClideSettings.fonts.monoOf(context),
fontSize: clideFontCaption,
color: tokens.statusBarForeground,
),
);
},
);
+18 -13
View File
@@ -105,7 +105,7 @@ class _TipsCard extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ClideText('TIPS', fontSize: clideFontSmall, color: tokens.sidebarSectionHeader, fontFamily: clideMonoFamily),
ClideText('TIPS', fontSize: clideFontSmall, color: tokens.sidebarSectionHeader, fontFamily: ClideSettings.fonts.monoOf(context)),
const SizedBox(height: 14),
_tipRow(firstRow),
const SizedBox(height: 8),
@@ -170,7 +170,7 @@ class _StartColumn extends StatelessWidget {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ClideText('START', fontSize: clideFontSmall, color: tokens.sidebarSectionHeader, fontFamily: clideMonoFamily),
ClideText('START', fontSize: clideFontSmall, color: tokens.sidebarSectionHeader, fontFamily: ClideSettings.fonts.monoOf(context)),
const SizedBox(height: 20),
// Only flows that exist get a tile — the old Clone-from-git and
// Start-a-Claude-session rows were inert and advertised shortcuts
@@ -233,7 +233,7 @@ class _ActionRow extends StatelessWidget {
Expanded(
child: ClideText(label, fontSize: clideFontBody, color: tokens.globalForeground),
),
if (shortcut != null) ClideText(shortcut!, fontSize: clideFontMeta, color: tokens.globalTextMuted, fontFamily: clideMonoFamily),
if (shortcut != null) ClideText(shortcut!, fontSize: clideFontMeta, color: tokens.globalTextMuted, fontFamily: ClideSettings.fonts.monoOf(context)),
],
),
),
@@ -255,7 +255,7 @@ class _RecentColumn extends StatelessWidget {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ClideText('RECENT', fontSize: clideFontSmall, color: tokens.sidebarSectionHeader, fontFamily: clideMonoFamily),
ClideText('RECENT', fontSize: clideFontSmall, color: tokens.sidebarSectionHeader, fontFamily: ClideSettings.fonts.monoOf(context)),
const SizedBox(height: 20),
if (recents.isEmpty)
const ClideText('No recent projects.', muted: true, fontSize: clideFontCaption)
@@ -309,7 +309,7 @@ class _RecentRow extends StatelessWidget {
project.relativePath,
muted: true,
fontSize: clideFontMeta,
fontFamily: clideMonoFamily,
fontFamily: ClideSettings.fonts.monoOf(context),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
@@ -323,7 +323,7 @@ class _RecentRow extends StatelessWidget {
project.branch!,
muted: true,
fontSize: clideFontMeta,
fontFamily: clideMonoFamily,
fontFamily: ClideSettings.fonts.monoOf(context),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
@@ -399,17 +399,17 @@ class _StatusLine extends StatelessWidget {
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
ClideText('$clideName $clideVersion', muted: true, fontSize: clideFontSmall, fontFamily: clideMonoFamily),
ClideText('$clideName $clideVersion', muted: true, fontSize: clideFontSmall, fontFamily: ClideSettings.fonts.monoOf(context)),
ClideText(' · ', muted: true, fontSize: clideFontSmall),
if (!tc.resolved)
ClideText('checking…', muted: true, fontSize: clideFontSmall, fontFamily: clideMonoFamily)
ClideText('checking…', muted: true, fontSize: clideFontSmall, fontFamily: ClideSettings.fonts.monoOf(context))
else if (tc.allOk)
ClideText('application ok', fontSize: clideFontSmall, fontFamily: clideMonoFamily, color: tokens.statusSuccess)
ClideText('application ok', fontSize: clideFontSmall, fontFamily: ClideSettings.fonts.monoOf(context), color: tokens.statusSuccess)
else
ClideText(
tc.missing.map((t) => '$t not found').join(' · '),
fontSize: clideFontSmall,
fontFamily: clideMonoFamily,
fontFamily: ClideSettings.fonts.monoOf(context),
color: tokens.statusWarning,
),
ClideText(' · ', muted: true, fontSize: clideFontSmall),
@@ -435,8 +435,13 @@ class _ThemeLink extends StatelessWidget {
builder: (ctx, hovered, _) => Row(
mainAxisSize: MainAxisSize.min,
children: [
ClideText('theme: ', muted: true, fontSize: clideFontSmall, fontFamily: clideMonoFamily),
ClideText(themeName, fontSize: clideFontSmall, fontFamily: clideMonoFamily, color: hovered ? tokens.globalForeground : tokens.globalFocus),
ClideText('theme: ', muted: true, fontSize: clideFontSmall, fontFamily: ClideSettings.fonts.monoOf(context)),
ClideText(
themeName,
fontSize: clideFontSmall,
fontFamily: ClideSettings.fonts.monoOf(context),
color: hovered ? tokens.globalForeground : tokens.globalFocus,
),
],
),
);
@@ -518,7 +523,7 @@ class _OpenProjectDialogState extends State<_OpenProjectDialog> {
style: TextStyle(
color: tokens.globalForeground,
fontSize: clideFontCaption,
fontFamily: clideMonoFamily,
fontFamily: ClideSettings.fonts.monoOf(context),
fontFamilyFallback: clideMonoFamilyFallback,
),
cursorColor: tokens.globalForeground,