Files
clide/lib/widgets/src/clide_spine.dart
T
jpmschweitzerandClaude Opus 4.8 18cd945380 refactor(theme): route consumer reads through ClideSettings.theme (T-473)
Migrate ClideTheme.of(context) reads across the widget, feature, and shell
layers to the unified ClideSettings.theme.of(context) facade (D-101), so
theme/i18n/fonts/settings share one widget-facing entry. The facade delegates
straight to ClideTheme, so behaviour is unchanged — goldens are unmoved.

The low-level theme provider keeps its direct ClideTheme.of: the facade is
built on it, and the two kernel sites (ClideTheme's own definition + the
panels drag-resize widget) stay direct to avoid a widgets→kernel import cycle.
Dead controller.dart/kernel.dart imports left by the sweep removed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 21:47:15 +02:00

68 lines
2.1 KiB
Dart

import 'package:clide/widgets/src/clide_settings.dart';
import 'dart:math' as math;
import 'package:clide/widgets/src/clide_tappable.dart';
import 'package:flutter/widgets.dart';
class ClideSpine extends StatelessWidget {
const ClideSpine({super.key, required this.label, required this.onExpand, this.side = SpineSide.left, this.badgeCount = 0});
final String label;
final VoidCallback onExpand;
final SpineSide side;
final int badgeCount;
static const double width = 12;
@override
Widget build(BuildContext context) {
final tokens = ClideSettings.theme.of(context).surface;
final borderSide = BorderSide(color: tokens.dividerColor);
return Semantics(
button: true,
label: '$label — click to expand',
child: ClideTappable(
onTap: onExpand,
builder: (context, hovered, _) => Container(
width: ClideSpine.width,
decoration: BoxDecoration(
color: hovered ? tokens.sidebarItemHover : tokens.chromeBackground,
border: Border(left: side == SpineSide.right ? borderSide : BorderSide.none, right: side == SpineSide.left ? borderSide : BorderSide.none),
),
child: Stack(
children: [
Center(
child: Transform.rotate(
angle: side == SpineSide.left ? -math.pi / 2 : math.pi / 2,
child: Text(
label,
style: TextStyle(fontSize: 9, color: tokens.globalTextMuted, letterSpacing: 0.5),
maxLines: 1,
overflow: TextOverflow.clip,
),
),
),
if (badgeCount > 0)
Positioned(
top: 4,
left: 0,
right: 0,
child: Center(
child: Container(
width: 6,
height: 6,
decoration: BoxDecoration(color: tokens.statusInfo, shape: BoxShape.circle),
),
),
),
],
),
),
),
);
}
}
enum SpineSide { left, right }