Adapt layout for wide screens and tablets

- Switch navigation breakpoint from orientation to width (≥600dp):
  NavigationRail shown on tablets in portrait and phones in landscape
- Chat bubble max-width capped at 480dp (prevents 640dp+ bubbles on tablets)
- Chat input maxLines reduced to 2 when width ≥600dp
- Task edit form centered and constrained to 600dp max-width on tablets

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-01 12:27:36 -05:00
parent 98ad9a2557
commit 2d4c9a9f70
3 changed files with 60 additions and 6 deletions
+45
View File
@@ -144,6 +144,51 @@ class _Shell extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final location = GoRouterState.of(context).matchedLocation;
final index = _tabIndex(location);
// Use NavigationRail whenever the screen is wide enough — covers both
// phone landscape and tablets in either orientation (600 dp breakpoint).
final isWide = MediaQuery.of(context).size.width >= 600;
if (isWide) {
return Scaffold(
body: SafeArea(
child: Column(
children: [
const _QuickCaptureBar(),
Expanded(
child: Row(
children: [
NavigationRail(
selectedIndex: index,
onDestinationSelected: (i) => context.go(_tabs[i]),
labelType: NavigationRailLabelType.all,
destinations: const [
NavigationRailDestination(
icon: Icon(Icons.note_outlined),
selectedIcon: Icon(Icons.note),
label: Text('Notes'),
),
NavigationRailDestination(
icon: Icon(Icons.check_box_outlined),
selectedIcon: Icon(Icons.check_box),
label: Text('Tasks'),
),
NavigationRailDestination(
icon: Icon(Icons.chat_bubble_outline),
selectedIcon: Icon(Icons.chat_bubble),
label: Text('Chat'),
),
],
),
const VerticalDivider(width: 1),
Expanded(child: child),
],
),
),
],
),
),
);
}
return Scaffold(
body: Column(
+5 -2
View File
@@ -1,3 +1,5 @@
import 'dart:math' show min;
import 'package:flutter/material.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
@@ -122,7 +124,8 @@ class _ChatScreenState extends ConsumerState<ChatScreen> {
contentPadding: EdgeInsets.symmetric(
horizontal: 12, vertical: 10),
),
maxLines: 4,
maxLines:
MediaQuery.of(context).size.width >= 600 ? 2 : 4,
minLines: 1,
textInputAction: TextInputAction.newline,
enabled: !isStreaming,
@@ -163,7 +166,7 @@ class _MessageBubble extends StatelessWidget {
alignment: isUser ? Alignment.centerRight : Alignment.centerLeft,
child: Container(
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width * 0.8,
maxWidth: min(MediaQuery.of(context).size.width * 0.8, 480),
),
margin: const EdgeInsets.symmetric(vertical: 4),
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
+10 -4
View File
@@ -147,10 +147,14 @@ class _TaskEditScreenState extends ConsumerState<TaskEditScreen> {
),
body: snapshot.connectionState == ConnectionState.waiting
? const Center(child: CircularProgressIndicator())
: Form(
key: _formKey,
child: ListView(
padding: const EdgeInsets.all(16),
: Align(
alignment: Alignment.topCenter,
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 600),
child: Form(
key: _formKey,
child: ListView(
padding: const EdgeInsets.all(16),
children: [
TextFormField(
controller: _titleController,
@@ -215,6 +219,8 @@ class _TaskEditScreenState extends ConsumerState<TaskEditScreen> {
],
),
),
),
),
);
},
);