Files
clide/app/lib/kernel/src/panels/drag_resize.dart
T
jpmschweitzerandClaude b13483e2d5 scaffold Flutter app — kernel, extensions, widgets, Tier 0 built-ins
First real content under app/. Lays the whole Tier 0 foundation in one
commit because the pieces depend on each other circularly (kernel →
extension → widgets → built-ins all reference types from the layer
below); splitting would leave intermediate commits that don't compile.

Key shapes:

  * bare WidgetsApp root — no Material, no Cupertino, no Scaffold.
    ClideTheme InheritedWidget is the only source of tokens.
  * ClideKernel InheritedWidget aggregates 18 services (settings,
    project, extensions, theme, panels, events, ipc, commands +
    palette + keybindings, clipboard, files, notify, dialog, tray,
    secrets, os, net, focus, log, i18n). ExtensionContext exposes
    them through a stable interface.
  * ClideExtension + sealed ContributionPoint hierarchy (Tab,
    StatusItem, Toolbar, Command, TrayItem, LayoutPreset). One
    manifest ships N contributions into kernel slots.
  * Three-tier theme pipeline: palette (named colors) → semantic
    roles → ~60 surface tokens. Defaults at each layer so legacy
    palette-only themes produce a complete SurfaceTokens.
  * A11y baked in from day one — every interactive primitive wraps
    in Semantics(label:, hint:, button:); ensureSemantics() at boot;
    theme/contrast.dart helper exposes token pairs for the WCAG
    gate in the a11y test suite.
  * i18n ported from fframe's L10n pattern (text-driven, namespaced
    JSON catalogs, caller-supplied placeholders) with a proper
    locale fallback chain (exact → language → default → placeholder)
    fframe lacks.
  * Four Tier-0 built-ins live (default-layout, welcome, ipc-status,
    theme-picker) plus 17 id-reserving stubs so later tiers fill in
    without rename churn.

.gitignore extended to cover app/ sub-package artefacts and the
Playwright harness scratch dirs.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-21 15:39:41 +02:00

76 lines
2.3 KiB
Dart

import 'package:clide_app/kernel/src/panels/arrangement.dart';
import 'package:clide_app/kernel/src/panels/slot_id.dart';
import 'package:clide_app/kernel/src/theme/controller.dart';
import 'package:flutter/widgets.dart';
/// A 4-px draggable splitter that adjusts the size of [slot] in the
/// given [arrangement]. Slot hosts wrap this around their edges to make
/// the three-column layout resizable.
class DragResizeHandle extends StatefulWidget {
const DragResizeHandle({
super.key,
required this.arrangement,
required this.slot,
required this.axis,
this.thickness = 4.0,
});
final LayoutArrangement arrangement;
final SlotId slot;
final Axis axis;
final double thickness;
@override
State<DragResizeHandle> createState() => _DragResizeHandleState();
}
class _DragResizeHandleState extends State<DragResizeHandle> {
bool _hovered = false;
double? _dragStartSize;
Offset? _dragStartPointer;
@override
Widget build(BuildContext context) {
final tokens = ClideTheme.of(context).surface;
final color = _hovered ? tokens.panelActiveBorder : tokens.panelBorder;
return MouseRegion(
cursor: widget.axis == Axis.horizontal
? SystemMouseCursors.resizeColumn
: SystemMouseCursors.resizeRow,
onEnter: (_) => setState(() => _hovered = true),
onExit: (_) => setState(() => _hovered = false),
child: Listener(
onPointerDown: _onDown,
onPointerMove: _onMove,
onPointerUp: _onUp,
child: Container(
width: widget.axis == Axis.horizontal ? widget.thickness : null,
height: widget.axis == Axis.vertical ? widget.thickness : null,
color: color,
),
),
);
}
void _onDown(PointerDownEvent e) {
_dragStartSize = widget.arrangement.sizeOf(widget.slot);
_dragStartPointer = e.position;
}
void _onMove(PointerMoveEvent e) {
final start = _dragStartSize;
final startPt = _dragStartPointer;
if (start == null || startPt == null) return;
final delta = widget.axis == Axis.horizontal
? e.position.dx - startPt.dx
: e.position.dy - startPt.dy;
widget.arrangement.setSize(widget.slot, start + delta);
}
void _onUp(PointerUpEvent _) {
_dragStartSize = null;
_dragStartPointer = null;
}
}