diff --git a/lib/main.dart b/lib/main.dart index 2dcb566..e1d0450 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -27,7 +27,7 @@ import 'widgets/widgets.dart'; /// Studio's own build version. Bump on every UI commit so the /// running app self-identifies — visible in the sidebar header /// and quick-glance proof that you're seeing the current build. -const String kStudioVersion = '0.51.2'; +const String kStudioVersion = '0.51.3'; Future main() async { WidgetsFlutterBinding.ensureInitialized(); @@ -479,29 +479,59 @@ class _SidebarState extends State<_Sidebar> { padding: const EdgeInsets.symmetric(vertical: FaiSpace.xl), child: ClipRect( child: Column( + // Left-align every column child so brand mark + top + // indicators sit at the same X-pixel as the icons + // below. With the default `center`, the brand mark + // re-positioned itself horizontally on every expand + // animation (centered in 72 vs centered in 220), + // which the user perceived as the whole nav rail + // shifting even though the destination icons stayed + // put. Anchoring everything to the start eliminates + // the perceived shift. + crossAxisAlignment: CrossAxisAlignment.start, children: [ - // Brand mark — always visible. - FaiDeltaMark(color: theme.colorScheme.primary, mode: mode), + // Brand mark — always visible. Pad it to match the + // icon's left offset (ListView padding + AC padding + // = FaiSpace.md + FaiSpace.md), so the triangle's + // left edge aligns with the destination icons' + // left edges. + Padding( + padding: const EdgeInsets.only( + left: FaiSpace.md + FaiSpace.md, + ), + child: + FaiDeltaMark(color: theme.colorScheme.primary, mode: mode), + ), if (expanded) ...[ const SizedBox(height: FaiSpace.md), - Text( - 'F∆I Studio', - style: theme.textTheme.titleMedium?.copyWith( - fontWeight: FontWeight.w600, + const Padding( + padding: EdgeInsets.only(left: FaiSpace.md + FaiSpace.md), + child: Text( + 'F∆I Studio', + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600), ), ), const SizedBox(height: 2), - Text( - 'v$kStudioVersion', - style: FaiTheme.mono( - size: 10, - color: theme.colorScheme.primary, + Padding( + padding: const EdgeInsets.only( + left: FaiSpace.md + FaiSpace.md, + ), + child: Text( + 'v$kStudioVersion', + style: FaiTheme.mono( + size: 10, + color: theme.colorScheme.primary, + ), ), ), const SizedBox(height: FaiSpace.md), - // Connection pill — full version when expanded. + // Connection pill — left-aligned to the same + // x-anchor as the icons. Padding( - padding: const EdgeInsets.symmetric(horizontal: FaiSpace.lg), + padding: const EdgeInsets.only( + left: FaiSpace.md + FaiSpace.md, + right: FaiSpace.md, + ), child: _ConnectionPill( connected: widget.connected, label: widget.endpointLabel, @@ -523,7 +553,10 @@ class _SidebarState extends State<_Sidebar> { if (widget.activeChannel != null && widget.activeChannel!.isNotEmpty) ...[ const SizedBox(height: FaiSpace.sm), Padding( - padding: const EdgeInsets.symmetric(horizontal: FaiSpace.lg), + padding: const EdgeInsets.only( + left: FaiSpace.md + FaiSpace.md, + right: FaiSpace.md, + ), child: _ChannelPill(channel: widget.activeChannel!), ), ], @@ -532,29 +565,50 @@ class _SidebarState extends State<_Sidebar> { // most glance-able status indicators (version, // connection dot, channel letter) so the rail // still reads as F∆I Studio at-a-glance without - // hovering to expand. + // hovering to expand. All left-padded by the + // same offset as the destination icons ( + // ListView.padding + AC.padding = 12 + 12) + // so the column reads as one stable left edge. const SizedBox(height: FaiSpace.sm), - Text( - 'v$kStudioVersion'.replaceFirst(RegExp(r'-.*'), ''), - style: FaiTheme.mono( - size: 9, - color: theme.colorScheme.primary, + Padding( + padding: const EdgeInsets.only( + left: FaiSpace.md + FaiSpace.md, + ), + child: Text( + 'v$kStudioVersion'.replaceFirst(RegExp(r'-.*'), ''), + style: FaiTheme.mono( + size: 9, + color: theme.colorScheme.primary, + ), ), ), const SizedBox(height: FaiSpace.md), - Tooltip( - message: widget.connected == true - ? 'Connected · ${widget.endpointLabel}' - : widget.connected == false - ? 'Disconnected · ${widget.endpointLabel}' - : 'Connecting · ${widget.endpointLabel}', - child: _CollapsedConnectionDot(connected: widget.connected), + Padding( + padding: const EdgeInsets.only( + left: FaiSpace.md + FaiSpace.md, + ), + child: Tooltip( + message: widget.connected == true + ? 'Connected · ${widget.endpointLabel}' + : widget.connected == false + ? 'Disconnected · ${widget.endpointLabel}' + : 'Connecting · ${widget.endpointLabel}', + child: + _CollapsedConnectionDot(connected: widget.connected), + ), ), if (widget.activeChannel != null && widget.activeChannel!.isNotEmpty) ...[ const SizedBox(height: FaiSpace.sm), - Tooltip( - message: widget.activeChannel!, - child: _CollapsedChannelChip(channel: widget.activeChannel!), + Padding( + padding: const EdgeInsets.only( + left: FaiSpace.md + FaiSpace.md, + ), + child: Tooltip( + message: widget.activeChannel!, + child: _CollapsedChannelChip( + channel: widget.activeChannel!, + ), + ), ), ], ], diff --git a/pubspec.lock b/pubspec.lock index 4e5aec4..c58cabd 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -125,10 +125,10 @@ packages: description: path: "." ref: main - resolved-ref: "8b918f8f2afe5babe663897aa20483708a980c4b" + resolved-ref: "7655e0dc32fa3093b36c094a1fbad87625199227" url: "https://git.flemming.ai/fai/studio-flow-editor" source: git - version: "0.1.1" + version: "0.1.2" fake_async: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 34d1ada..85de955 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: fai_studio description: "F∆I Studio — desktop GUI for the F∆I hub" publish_to: 'none' -version: 0.51.2 +version: 0.51.3 environment: sdk: ^3.11.0-200.1.beta