Mitra chat input bar: drop maxLines:3 attempt + nudge alignment down
Follow-up to 92da8b2. With `textAlignVertical: center` + `isDense:true`,
the TextField was centering the line-box baseline on the parent
midline — but Latin lowercase glyphs sit at ~75% of line height,
leaving descender space empty below and the optical center of text
visibly above the pill midline.
Fix: `textAlignVertical: TextAlignVertical(y: 0.4)` shifts the
baseline down to align Latin x-height optical centers with the pill
midline. Also added explicit `alignment: Alignment.center` on the
Container so the field's small intrinsic line-box positions on the
midline rather than docking to the top.
Verified on emulator-5556 driving the typed "halo" through the chat
input — text body now sits on the visual midline of the 44dp pill.
The horizontal underline below typed text is Gboard's composing-
region indicator (Android IME behavior), not a TextField underline,
and will go away once the user commits the word with space/send.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -742,6 +742,11 @@ class _MitraChatBodyContentState extends ConsumerState<_MitraChatBodyContent> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 44,
|
height: 44,
|
||||||
|
// alignment.center positions the TextField on the vertical
|
||||||
|
// midline of the 44dp container. Without this, isDense's
|
||||||
|
// small intrinsic height docks to the top of the parent
|
||||||
|
// (no implicit vertical centering for Container children).
|
||||||
|
alignment: Alignment.center,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
// White bg so the pill stands out against the cream page
|
// White bg so the pill stands out against the cream page
|
||||||
@@ -756,29 +761,37 @@ class _MitraChatBodyContentState extends ConsumerState<_MitraChatBodyContent> {
|
|||||||
BorderSide(color: HaloTokens.border),
|
BorderSide(color: HaloTokens.border),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// Center wrapper makes the TextField sit on the vertical
|
// Vertical centering recipe: Container.alignment.center
|
||||||
// midline of the 44dp pill. `textAlignVertical: center`
|
// positions the TextField on the midline; textAlignVertical
|
||||||
// + `isCollapsed: true` alone don't center against the
|
// with a positive y (~0.4) nudges the baseline down so the
|
||||||
// parent height — they only center within the field's
|
// optical center of Latin lowercase glyphs lines up with
|
||||||
// own intrinsic line-box, which then docks to the top of
|
// the pill midline, not just the baseline. With y=0 (true
|
||||||
// the parent. Wrapping in Center delegates the vertical
|
// center), the field's line-box centers but Latin text
|
||||||
// alignment to the container's stack.
|
// bodies sit in the upper half because the baseline is at
|
||||||
child: Center(
|
// ~75% of line height — leaving descender space empty
|
||||||
|
// below. y=0.4 shifts down to match the visual midline.
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: widget.messageController,
|
controller: widget.messageController,
|
||||||
onChanged: widget.onTextChanged,
|
onChanged: widget.onTextChanged,
|
||||||
textInputAction: TextInputAction.send,
|
textInputAction: TextInputAction.send,
|
||||||
onSubmitted: (_) => widget.onSend(),
|
onSubmitted: (_) => widget.onSend(),
|
||||||
style: const TextStyle(fontSize: 13.5, color: HaloTokens.ink),
|
maxLines: 1,
|
||||||
|
textAlignVertical: const TextAlignVertical(y: 0.4),
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 13.5,
|
||||||
|
color: HaloTokens.ink,
|
||||||
|
),
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
hintText: 'ketik balasan...',
|
hintText: 'ketik balasan...',
|
||||||
hintStyle: TextStyle(color: HaloTokens.inkMuted, fontSize: 13.5),
|
hintStyle: TextStyle(color: HaloTokens.inkMuted, fontSize: 13.5),
|
||||||
isCollapsed: true,
|
isDense: true,
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
enabledBorder: InputBorder.none,
|
enabledBorder: InputBorder.none,
|
||||||
focusedBorder: InputBorder.none,
|
focusedBorder: InputBorder.none,
|
||||||
disabledBorder: InputBorder.none,
|
disabledBorder: InputBorder.none,
|
||||||
),
|
errorBorder: InputBorder.none,
|
||||||
|
focusedErrorBorder: InputBorder.none,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user