import 'package:flutter/material.dart';
import '../../core/theme/app_theme.dart';
/// Shared search-field chrome used by discovery lists, module heroes and
/// address-aware discovery surfaces.
///
/// Keeping the prefix and submit action at explicit sizes is important on
/// narrow WebView layouts: InputDecorator's default suffix sizing otherwise
/// lets the hint text render into the action area.
class DiscoverySearchField extends StatelessWidget {
const DiscoverySearchField({
super.key,
required this.controller,
required this.hintText,
required this.onChanged,
required this.onSubmit,
required this.prefixIcon,
required this.actionIcon,
this.prefixColor,
this.actionColor,
this.actionTextColor,
this.actionBackground = false,
this.enabled = true,
this.borderRadius = 14,
});
static const double _iconSlot = 48;
static const double _actionSlot = 52;
final TextEditingController controller;
final String hintText;
final ValueChanged<String> onChanged;
final VoidCallback onSubmit;
final IconData prefixIcon;
final IconData actionIcon;
final Color? prefixColor;
final Color? actionColor;
final Color? actionTextColor;
final bool actionBackground;
final bool enabled;
final double borderRadius;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final resolvedActionColor = actionColor ?? theme.colorScheme.primary;
final resolvedPrefixColor = prefixColor ?? theme.colorScheme.onSurface;
final resolvedActionTextColor = actionTextColor ?? Colors.white;
final radius = BorderRadius.circular(borderRadius);
final actionRadius = BorderRadius.horizontal(
right: Radius.circular(borderRadius),
);
return DecoratedBox(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: radius,
boxShadow: AppTheme.cardShadow,
),
child: Material(
color: Colors.white,
borderRadius: radius,
clipBehavior: Clip.antiAlias,
child: TextField(
controller: controller,
enabled: enabled,
maxLines: 1,
textInputAction: TextInputAction.search,
onChanged: onChanged,
onSubmitted: (_) => onSubmit(),
decoration: InputDecoration(
hintText: hintText,
prefixIcon: SizedBox(
width: _iconSlot,
height: _iconSlot,
child: Center(
child: Icon(prefixIcon, color: resolvedPrefixColor),
),
),
prefixIconConstraints: const BoxConstraints.tightFor(
width: _iconSlot,
height: _iconSlot,
),
suffixIcon: SizedBox(
width: _actionSlot,
height: _iconSlot,
child: Material(
color: actionBackground
? resolvedActionColor
: Colors.transparent,
borderRadius: actionBackground
? actionRadius
: BorderRadius.zero,
child: InkWell(
onTap: enabled ? onSubmit : null,
borderRadius: actionBackground ? actionRadius : null,
child: Center(
child: Icon(
actionIcon,
color: actionBackground
? resolvedActionTextColor
: resolvedPrefixColor,
),
),
),
),
),
suffixIconConstraints: const BoxConstraints.tightFor(
width: _actionSlot,
height: _iconSlot,
),
filled: true,
fillColor: Colors.white,
isDense: false,
contentPadding: const EdgeInsetsDirectional.only(
top: 4,
bottom: 4,
end: 8,
),
border: OutlineInputBorder(
borderRadius: radius,
borderSide: BorderSide.none,
),
enabledBorder: OutlineInputBorder(
borderRadius: radius,
borderSide: BorderSide.none,
),
focusedBorder: OutlineInputBorder(
borderRadius: radius,
borderSide: BorderSide.none,
),
),
),
),
);
}
}
