- Logo: network image in white card + tagline - Sidebar: deep navy gradient (#0D1B3E) with blue accent active states - MenuItem: left accent bar indicator, cleaner hover, better contrast - Mode toggle: gradient button matching brand colors - TextSeparator: uppercase label with divider line Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
86 lines
2.5 KiB
Dart
86 lines
2.5 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
const _kAccent = Color(0xFF42A4EF);
|
|
const _kTextActive = Colors.white;
|
|
const _kTextInactive = Color(0xFF8BAFD4);
|
|
const _kIconActive = _kAccent;
|
|
const _kIconInactive = Color(0xFF5A7A9B);
|
|
|
|
class MenuItem extends StatefulWidget {
|
|
final String text;
|
|
final IconData icon;
|
|
final bool isActive;
|
|
final Function onPressed;
|
|
|
|
const MenuItem({
|
|
super.key,
|
|
required this.text,
|
|
required this.icon,
|
|
this.isActive = false,
|
|
required this.onPressed,
|
|
});
|
|
|
|
@override
|
|
State<MenuItem> createState() => _MenuItemState();
|
|
}
|
|
|
|
class _MenuItemState extends State<MenuItem> {
|
|
bool isHovered = false;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final active = widget.isActive;
|
|
final highlight = active || isHovered;
|
|
|
|
return MouseRegion(
|
|
cursor: active ? SystemMouseCursors.basic : SystemMouseCursors.click,
|
|
onEnter: (_) => setState(() => isHovered = true),
|
|
onExit: (_) => setState(() => isHovered = false),
|
|
child: GestureDetector(
|
|
onTap: active ? null : () => widget.onPressed(),
|
|
child: AnimatedContainer(
|
|
duration: const Duration(milliseconds: 200),
|
|
margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 2),
|
|
decoration: BoxDecoration(
|
|
color: highlight
|
|
? const Color(0xFF42A4EF).withOpacity(0.12)
|
|
: Colors.transparent,
|
|
borderRadius: BorderRadius.circular(10),
|
|
),
|
|
child: Row(
|
|
children: [
|
|
AnimatedContainer(
|
|
duration: const Duration(milliseconds: 200),
|
|
width: 3,
|
|
height: 36,
|
|
decoration: BoxDecoration(
|
|
color: active ? _kAccent : Colors.transparent,
|
|
borderRadius: const BorderRadius.only(
|
|
topRight: Radius.circular(3),
|
|
bottomRight: Radius.circular(3),
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(width: 12),
|
|
Icon(
|
|
widget.icon,
|
|
color: active ? _kIconActive : _kIconInactive,
|
|
size: 20,
|
|
),
|
|
const SizedBox(width: 10),
|
|
Text(
|
|
widget.text,
|
|
style: TextStyle(
|
|
color: active ? _kTextActive : _kTextInactive,
|
|
fontSize: 13,
|
|
fontWeight: active ? FontWeight.w600 : FontWeight.w400,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|