From 2d647400075d926b9801a73caca25a890723a874 Mon Sep 17 00:00:00 2001 From: Jeroen Schweitzer Date: Wed, 6 May 2026 11:10:17 +0200 Subject: [PATCH] welcome screen: add Tips card below START / RECENT row Six common keybindings (Quick open, Command palette, Toggle sidebar, Toggle context, Switch theme, New Claude session) shown as a 3x2 grid card spanning the same 850px content column as the two action columns above. LayoutBuilder gates the card on viewport height (>640px) so on shorter windows the centered START / RECENT columns stay the focus and the tips drop out cleanly. Co-Authored-By: Claude --- .pql/pql-plan.json | 2 +- CHANGELOG.md | 7 ++ lib/builtin/welcome/src/welcome_view.dart | 118 ++++++++++++++++++---- 3 files changed, 104 insertions(+), 23 deletions(-) diff --git a/.pql/pql-plan.json b/.pql/pql-plan.json index 36499a8f..402987b6 100644 --- a/.pql/pql-plan.json +++ b/.pql/pql-plan.json @@ -1,5 +1,5 @@ { - "exported_at": "2026-05-06T09:06:41Z", + "exported_at": "2026-05-06T09:10:17Z", "decisions": [ { "id": "D-1", diff --git a/CHANGELOG.md b/CHANGELOG.md index 1055aa3c..a6e32325 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,13 @@ heading, and (b) bumping `pubspec.yaml` `version:` in the same commit. - Mouse wheel scrolling in Claude pane — converts scroll events to PgUp/PgDown so Claude Code (and other TUI apps) scroll their history naturally. +- Welcome screen Tips card — six common keybindings shown below the + START / RECENT row when the viewport is tall enough. + +### Changed + +- Tagline reads "IDE for Claude Code CLI" everywhere (welcome + subtitle, README, CLAUDE.md, pubspec, web manifest, CLI banner). ### Fixed diff --git a/lib/builtin/welcome/src/welcome_view.dart b/lib/builtin/welcome/src/welcome_view.dart index dd13969a..7e2659db 100644 --- a/lib/builtin/welcome/src/welcome_view.dart +++ b/lib/builtin/welcome/src/welcome_view.dart @@ -12,35 +12,109 @@ class WelcomeView extends StatelessWidget { Widget build(BuildContext context) { final kernel = ClideKernel.of(context); final tokens = ClideTheme.of(context).surface; - return Stack( - children: [ - Center( - child: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 850), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _Header(tokens: tokens), - const SizedBox(height: 56), - Row( + return LayoutBuilder( + builder: (context, c) { + // Tips card sits below the START/RECENT row when there's room + // for it; on shorter viewports the two centered columns win + // and the tips drop out cleanly. + final showTips = c.maxHeight > 640; + return Stack( + children: [ + Center( + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 850), + child: Column( + mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded(child: _StartColumn(tokens: tokens, kernel: kernel)), - const SizedBox(width: 56), - Expanded(child: _RecentColumn(tokens: tokens, kernel: kernel)), + _Header(tokens: tokens), + const SizedBox(height: 56), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded(child: _StartColumn(tokens: tokens, kernel: kernel)), + const SizedBox(width: 56), + Expanded(child: _RecentColumn(tokens: tokens, kernel: kernel)), + ], + ), + if (showTips) ...[ + const SizedBox(height: 48), + _TipsCard(tokens: tokens), + ], ], ), + ), + ), + Positioned( + left: 64, + right: 64, + bottom: 24, + child: _StatusLine(tokens: tokens, kernel: kernel), + ), + ], + ); + }, + ); + } +} + +class _TipsCard extends StatelessWidget { + const _TipsCard({required this.tokens}); + final SurfaceTokens tokens; + + static const _tips = <(String, String)>[ + ('Quick open', '⌘P'), + ('Command palette', '⌘⇧P'), + ('Toggle sidebar', '⌘B'), + ('Toggle context', '⌘J'), + ('Switch theme', '⌘K ⌘T'), + ('New Claude session', '⌘⇧C'), + ]; + + @override + Widget build(BuildContext context) { + // Split tips into two rows of three so the card lays out as a + // 3-column grid matching the START/RECENT proportions above. + final firstRow = _tips.sublist(0, 3); + final secondRow = _tips.sublist(3); + + return SizedBox( + width: double.infinity, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 20), + decoration: BoxDecoration( + color: tokens.panelBackground, + border: Border.all(color: tokens.panelBorder), + borderRadius: BorderRadius.circular(6), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ClideText('TIPS', fontSize: 12, color: tokens.sidebarSectionHeader, fontFamily: clideMonoFamily), + const SizedBox(height: 14), + _tipRow(firstRow), + const SizedBox(height: 8), + _tipRow(secondRow), + ], + ), + ), + ); + } + + Widget _tipRow(List<(String, String)> tips) { + return Row( + children: [ + for (var i = 0; i < tips.length; i++) ...[ + Expanded( + child: Row( + children: [ + Expanded(child: ClideText(tips[i].$1, fontSize: 13, color: tokens.globalTextMuted)), + ClideText(tips[i].$2, fontSize: 12, color: tokens.globalForeground, fontFamily: clideMonoFamily), ], ), ), - ), - Positioned( - left: 64, - right: 64, - bottom: 24, - child: _StatusLine(tokens: tokens, kernel: kernel), - ), + if (i < tips.length - 1) const SizedBox(width: 24), + ], ], ); }