add chrome token set for frame surfaces

New tokens: chromeBackground, chromeForeground, chromeBorder —
shared root for hat bar, sidebar, context panel, status bar,
spines, and drag handles. All resolve to bgSunken/textDim/border
in the palette by default. Themes can override individually to
diverge surfaces. Replaces direct sidebarBackground/statusBar
references in chrome contexts. Updated theme-ui skill.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-23 08:52:44 +02:00
co-authored by Claude Opus 4.6
parent 1494d6a414
commit 86ad659121
6 changed files with 43 additions and 19 deletions
+9 -9
View File
@@ -177,7 +177,7 @@ class RootLayout extends StatelessWidget {
if (statusVisible)
Container(
height: statusHeight,
decoration: BoxDecoration(border: Border(top: BorderSide(color: ClideTheme.of(ctx).surface.dividerColor))),
decoration: BoxDecoration(border: Border(top: BorderSide(color: ClideTheme.of(ctx).surface.chromeBorder))),
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
@@ -222,8 +222,8 @@ class _HatBar extends StatelessWidget {
child: Container(
height: hatHeight,
decoration: BoxDecoration(
color: tokens.sidebarBackground,
border: Border(bottom: BorderSide(color: tokens.dividerColor, width: 1)),
color: tokens.chromeBackground,
border: Border(bottom: BorderSide(color: tokens.chromeBorder, width: 1)),
),
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Row(
@@ -238,7 +238,7 @@ class _HatBar extends StatelessWidget {
return ClideText(
name != null ? 'clide > $name' : 'clide',
fontSize: 12,
color: tokens.globalTextMuted,
color: tokens.chromeForeground,
fontFamily: clideMonoFamily,
);
},
@@ -343,7 +343,7 @@ class _WinBtnState extends State<_WinBtn> {
width: 36, height: hatHeight,
color: _hover ? hoverBg : null,
alignment: Alignment.center,
child: ClideIcon(widget.icon, size: 14, color: _hover && widget.isClose ? const Color(0xFFFFFFFF) : widget.tokens.globalTextMuted),
child: ClideIcon(widget.icon, size: 14, color: _hover && widget.isClose ? const Color(0xFFFFFFFF) : widget.tokens.chromeForeground),
),
),
);
@@ -442,7 +442,7 @@ class _SidebarSlot extends StatelessWidget {
Widget build(BuildContext context) {
final tokens = ClideTheme.of(context).surface;
return Container(
color: tokens.sidebarBackground,
color: tokens.chromeBackground,
alignment: Alignment.topLeft,
padding: const EdgeInsets.fromLTRB(2, 2, 0, 0),
child: active.build(context),
@@ -579,10 +579,10 @@ class _BottomRail extends StatelessWidget {
listenable: kernel.panels,
builder: (ctx, _) {
final tabs = kernel.panels.tabsFor(slot);
if (tabs.isEmpty) return Container(color: tokens.statusBarBackground);
if (tabs.isEmpty) return Container(color: tokens.chromeBackground);
final activeId = kernel.panels.activeTabIn(slot) ?? tabs.first.id;
return Container(
color: tokens.statusBarBackground,
color: tokens.chromeBackground,
child: ClideIconRail(
items: [
for (final t in tabs)
@@ -636,7 +636,7 @@ class StatusbarHost extends StatelessWidget {
final left = items.where((i) => i.priority < 100).toList();
final right = items.where((i) => i.priority >= 100).toList();
return Container(
color: tokens.statusBarBackground,
color: tokens.chromeBackground,
padding: const EdgeInsets.symmetric(horizontal: 8),
alignment: Alignment.center,
child: Row(
+1 -1
View File
@@ -49,7 +49,7 @@ class _DragResizeHandleState extends State<DragResizeHandle> {
child: Container(
width: widget.axis == Axis.horizontal ? widget.thickness : null,
height: widget.axis == Axis.vertical ? widget.thickness : null,
color: widget.slot == Slots.sidebar ? tokens.sidebarBackground : tokens.panelBackground,
color: tokens.chromeBackground,
child: Align(
alignment: widget.slot == Slots.sidebar ? Alignment.centerRight : Alignment.centerLeft,
child: Container(
+7
View File
@@ -50,6 +50,9 @@ class ThemeResolver {
globalBorder: surface[TokenKeys.globalBorder]!,
globalFocus: surface[TokenKeys.globalFocus]!,
globalTextMuted: surface[TokenKeys.globalTextMuted]!,
chromeBackground: surface[TokenKeys.chromeBackground]!,
chromeForeground: surface[TokenKeys.chromeForeground]!,
chromeBorder: surface[TokenKeys.chromeBorder]!,
panelBackground: surface[TokenKeys.panelBackground]!,
panelBorder: surface[TokenKeys.panelBorder]!,
panelActiveBorder: surface[TokenKeys.panelActiveBorder]!,
@@ -196,6 +199,10 @@ const Map<String, List<String>> _defaultSurfaceMap = {
TokenKeys.globalBorder: ['border', 'semantic.surface'],
TokenKeys.globalFocus: ['accent', 'semantic.focus'],
TokenKeys.globalTextMuted: ['textDim', 'semantic.text_muted'],
// chrome — frame surfaces (hat bar, sidebar, status bar, spines)
TokenKeys.chromeBackground: ['bgSunken', 'semantic.mainchrome'],
TokenKeys.chromeForeground: ['textDim', 'semantic.text_muted'],
TokenKeys.chromeBorder: ['border', 'semantic.surface'],
// panel
TokenKeys.panelBackground: ['bgSunken', 'semantic.mainchrome'],
TokenKeys.panelBorder: ['border', 'semantic.surface'],
+16
View File
@@ -17,6 +17,10 @@ class SurfaceTokens {
required this.globalBorder,
required this.globalFocus,
required this.globalTextMuted,
// chrome (hat bar, sidebar, status bar, spines — frame surfaces)
required this.chromeBackground,
required this.chromeForeground,
required this.chromeBorder,
// panel
required this.panelBackground,
required this.panelBorder,
@@ -94,6 +98,10 @@ class SurfaceTokens {
final Color globalFocus;
final Color globalTextMuted;
final Color chromeBackground;
final Color chromeForeground;
final Color chromeBorder;
final Color panelBackground;
final Color panelBorder;
final Color panelActiveBorder;
@@ -179,6 +187,11 @@ abstract class TokenKeys {
static const globalFocus = 'global.focus';
static const globalTextMuted = 'global.textMuted';
// chrome
static const chromeBackground = 'chrome.background';
static const chromeForeground = 'chrome.foreground';
static const chromeBorder = 'chrome.border';
// panel
static const panelBackground = 'panel.background';
static const panelBorder = 'panel.border';
@@ -266,6 +279,9 @@ abstract class TokenKeys {
globalBorder,
globalFocus,
globalTextMuted,
chromeBackground,
chromeForeground,
chromeBorder,
panelBackground,
panelBorder,
panelActiveBorder,
+1 -1
View File
@@ -45,7 +45,7 @@ class _ClideSpineState extends State<ClideSpine> {
child: Container(
width: ClideSpine.width,
decoration: BoxDecoration(
color: _hovered ? tokens.sidebarItemHover : tokens.sidebarBackground,
color: _hovered ? tokens.sidebarItemHover : tokens.chromeBackground,
border: Border(
left: widget.side == SpineSide.right ? borderSide : BorderSide.none,
right: widget.side == SpineSide.left ? borderSide : BorderSide.none,