Update Scribe mobile custom prompt bar UI

This commit is contained in:
Théo Poizat
2026-02-25 09:54:21 +01:00
committed by Dat H. Pham
parent 1e43ac510b
commit b36b89cd04
3 changed files with 112 additions and 92 deletions
@@ -16,6 +16,18 @@ abstract final class AIScribeColors {
// Overlays // Overlays
static final Color dialogBarrier = Colors.black.withValues(alpha: 0.12); static final Color dialogBarrier = Colors.black.withValues(alpha: 0.12);
// Gradients
static const LinearGradient barGradient = LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
Color.fromRGBO(0, 183, 255, 0.90),
Color.fromRGBO(224, 109, 209, 0.90),
Color.fromRGBO(232, 167, 138, 0.90),
],
stops: [0.0, 0.75, 1.0],
);
} }
abstract final class AIScribeShadows { abstract final class AIScribeShadows {
@@ -131,6 +143,7 @@ abstract final class AIScribeSizes {
static const double aiAssistantIconRadius = 8; static const double aiAssistantIconRadius = 8;
static const double contentCardRadius = 16; static const double contentCardRadius = 16;
static const double improveButtonBorderRadius = 4; static const double improveButtonBorderRadius = 4;
static const double bottomBarRadius = 28;
// Width / height // Width / height
static const double menuItemHeight = 40; static const double menuItemHeight = 40;
@@ -1,4 +1,3 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/resources/image_paths.dart'; import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/views/button/tmail_button_widget.dart'; import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -154,33 +153,16 @@ class _AiScribeMobileActionsBottomSheetState
); );
} }
Widget _buildBottomBar(BuildContext context) { Widget _buildBottomBarContent(BuildContext context) {
if (!widget.showCustomPromptBar) { if (!widget.showCustomPromptBar) {
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
return Column( return AIScribeBar(
mainAxisSize: MainAxisSize.min,
children: [
const Divider(
height: 1,
thickness: 1,
color: AppColor.colorDividerComposer,
),
Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom + 8.0,
left: 16.0,
right: 16.0,
top: 8.0,
),
child: AIScribeBar(
onCustomPrompt: _onCustomPromptSubmit, onCustomPrompt: _onCustomPromptSubmit,
imagePaths: widget.imagePaths, imagePaths: widget.imagePaths,
boxShadow: const [], borderRadius: AIScribeSizes.bottomBarRadius,
), hintStyle: AIScribeTextStyles.searchBar,
),
],
); );
} }
@@ -203,6 +185,9 @@ class _AiScribeMobileActionsBottomSheetState
final hasContent = widget.content?.isNotEmpty ?? false; final hasContent = widget.content?.isNotEmpty ?? false;
final bottomBarPadding = MediaQuery.of(context).viewInsets.bottom + 16.0;
final bottomBarInset = bottomBarPadding + (widget.showCustomPromptBar ? AIScribeSizes.searchBarMaxHeight : 0.0);
return PointerInterceptor( return PointerInterceptor(
child: Container( child: Container(
height: double.infinity, height: double.infinity,
@@ -210,6 +195,10 @@ class _AiScribeMobileActionsBottomSheetState
color: AIScribeColors.background, color: AIScribeColors.background,
), ),
child: SafeArea( child: SafeArea(
child: Stack(
children: [
Padding(
padding: EdgeInsets.only(bottom: bottomBarInset),
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
@@ -235,7 +224,15 @@ class _AiScribeMobileActionsBottomSheetState
], ],
), ),
), ),
_buildBottomBar(context), ],
),
),
Positioned(
bottom: bottomBarPadding,
left: 16.0,
right: 16.0,
child: _buildBottomBarContent(context),
),
], ],
), ),
), ),
@@ -9,13 +9,15 @@ typedef OnCustomPromptCallback = void Function(String customPrompt);
class AIScribeBar extends StatefulWidget { class AIScribeBar extends StatefulWidget {
final OnCustomPromptCallback onCustomPrompt; final OnCustomPromptCallback onCustomPrompt;
final ImagePaths imagePaths; final ImagePaths imagePaths;
final List<BoxShadow>? boxShadow; final double? borderRadius;
final TextStyle? hintStyle;
const AIScribeBar({ const AIScribeBar({
super.key, super.key,
required this.onCustomPrompt, required this.onCustomPrompt,
required this.imagePaths, required this.imagePaths,
this.boxShadow, this.borderRadius,
this.hintStyle,
}); });
@override @override
@@ -65,15 +67,21 @@ class _AIScribeBarState extends State<AIScribeBar> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final borderRadius = BorderRadius.circular(widget.borderRadius ?? AIScribeSizes.searchBarRadius);
return Container( return Container(
padding: const EdgeInsets.all(2),
decoration: BoxDecoration(
borderRadius: borderRadius,
gradient: AIScribeColors.barGradient,
),
child: ClipRRect(
borderRadius: borderRadius,
child: Container(
width: AIScribeSizes.searchBarWidth, width: AIScribeSizes.searchBarWidth,
padding: AIScribeSizes.searchBarPadding, padding: AIScribeSizes.searchBarPadding,
decoration: BoxDecoration( decoration: const BoxDecoration(
borderRadius: const BorderRadius.all(
Radius.circular(AIScribeSizes.searchBarRadius),
),
color: AIScribeColors.background, color: AIScribeColors.background,
boxShadow: widget.boxShadow ?? AIScribeShadows.modal,
), ),
constraints: const BoxConstraints( constraints: const BoxConstraints(
maxHeight: AIScribeSizes.searchBarMaxHeight, maxHeight: AIScribeSizes.searchBarMaxHeight,
@@ -90,7 +98,7 @@ class _AIScribeBarState extends State<AIScribeBar> {
focusNode: _textFieldFocusNode, focusNode: _textFieldFocusNode,
decoration: InputDecoration( decoration: InputDecoration(
hintText: ScribeLocalizations.of(context).customPromptAction, hintText: ScribeLocalizations.of(context).customPromptAction,
hintStyle: AIScribeTextStyles.searchBarHint, hintStyle: widget.hintStyle ?? AIScribeTextStyles.searchBarHint,
border: InputBorder.none, border: InputBorder.none,
contentPadding: const EdgeInsets.symmetric(vertical: 8), contentPadding: const EdgeInsets.symmetric(vertical: 8),
isDense: true, isDense: true,
@@ -120,6 +128,8 @@ class _AIScribeBarState extends State<AIScribeBar> {
), ),
], ],
), ),
),
),
); );
} }