Skip to content

Commit

Permalink
Component tooltip (#31)
Browse files Browse the repository at this point in the history
* create tooltip

* create Widgetbook for ZetaTooltip

* add LayoutBuilder

* [automated commit] lint format and import sort

---------

Co-authored-by: github-actions <[email protected]>
  • Loading branch information
2 people authored and thelukewalton committed Apr 25, 2024
1 parent a5fc795 commit 2783212
Show file tree
Hide file tree
Showing 6 changed files with 320 additions and 0 deletions.
2 changes: 2 additions & 0 deletions example/lib/home.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import 'package:zeta_example/pages/components/switch_example.dart';
import 'package:zeta_example/pages/components/snackbar_example.dart';
import 'package:zeta_example/pages/components/tabs_example.dart';
import 'package:zeta_example/pages/components/pagination_example.dart';
import 'package:zeta_example/pages/components/tooltip_example.dart';
import 'package:zeta_example/pages/theme/color_example.dart';
import 'package:zeta_example/pages/components/password_input_example.dart';
import 'package:zeta_example/pages/components/progress_example.dart';
Expand Down Expand Up @@ -65,6 +66,7 @@ final List<Component> components = [
Component(DateInputExample.name, (context) => const DateInputExample()),
Component(PhoneInputExample.name, (context) => const PhoneInputExample()),
Component(DialogExample.name, (context) => const DialogExample()),
Component(TooltipExample.name, (context) => const TooltipExample()),
Component(NavigationRailExample.name, (context) => const NavigationRailExample()),
];

Expand Down
71 changes: 71 additions & 0 deletions example/lib/pages/components/tooltip_example.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import 'package:flutter/material.dart';
import 'package:zeta_example/widgets.dart';
import 'package:zeta_flutter/zeta_flutter.dart';

class TooltipExample extends StatelessWidget {
static const String name = 'Tooltip';

const TooltipExample({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return ExampleScaffold(
name: 'Tooltip',
child: SizedBox(
width: double.infinity,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('Rounded'),
const SizedBox(height: ZetaSpacing.l),
ZetaTooltip(
child: Text('Label'),
),
const SizedBox(height: ZetaSpacing.l),
ZetaTooltip(
child: Text('Label'),
arrowDirection: ZetaTooltipArrowDirection.right,
),
const SizedBox(height: ZetaSpacing.l),
ZetaTooltip(
child: Text('Label'),
arrowDirection: ZetaTooltipArrowDirection.up,
),
const SizedBox(height: ZetaSpacing.l),
ZetaTooltip(
child: Text('Label'),
arrowDirection: ZetaTooltipArrowDirection.left,
),
Divider(height: ZetaSpacing.xxl),
Text('Sharp'),
const SizedBox(height: ZetaSpacing.l),
ZetaTooltip(
child: Text('Label'),
rounded: false,
),
const SizedBox(height: ZetaSpacing.l),
ZetaTooltip(
child: Text('Label'),
arrowDirection: ZetaTooltipArrowDirection.right,
rounded: false,
),
const SizedBox(height: ZetaSpacing.l),
ZetaTooltip(
child: Text('Label'),
arrowDirection: ZetaTooltipArrowDirection.up,
rounded: false,
),
const SizedBox(height: ZetaSpacing.l),
ZetaTooltip(
child: Text('Label'),
arrowDirection: ZetaTooltipArrowDirection.left,
rounded: false,
),
],
),
),
);
}
}
2 changes: 2 additions & 0 deletions example/widgetbook/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import 'pages/components/stepper_widgetbook.dart';
import 'pages/components/switch_widgetbook.dart';
import 'pages/components/snack_bar_widgetbook.dart';
import 'pages/components/tabs_widgetbook.dart';
import 'pages/components/tooltip_widgetbook.dart';
import 'pages/theme/color_widgetbook.dart';
import 'pages/theme/radius_widgetbook.dart';
import 'pages/theme/spacing_widgetbook.dart';
Expand Down Expand Up @@ -128,6 +129,7 @@ class HotReload extends StatelessWidget {
),
WidgetbookUseCase(name: 'Dialog', builder: (context) => dialogUseCase(context)),
WidgetbookUseCase(name: 'Navigation Rail', builder: (context) => navigationRailUseCase(context)),
WidgetbookUseCase(name: 'Tooltip', builder: (context) => tooltipUseCase(context)),
]..sort((a, b) => a.name.compareTo(b.name)),
),
WidgetbookCategory(
Expand Down
32 changes: 32 additions & 0 deletions example/widgetbook/pages/components/tooltip_widgetbook.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import 'package:flutter/material.dart';
import 'package:widgetbook/widgetbook.dart';
import 'package:zeta_flutter/zeta_flutter.dart';

import '../../test/test_components.dart';

Widget tooltipUseCase(BuildContext context) {
final text = context.knobs.string(
label: 'Tooltip text',
initialValue: 'Label',
);
final direction = context.knobs.list<ZetaTooltipArrowDirection>(
label: 'Arrow direction',
options: ZetaTooltipArrowDirection.values,
labelBuilder: (direction) => direction.name,
);
final rounded = context.knobs.boolean(label: 'Rounded', initialValue: true);
return WidgetbookTestWidget(
widget: StatefulBuilder(
builder: (context, setState) {
return Padding(
padding: const EdgeInsets.all(ZetaSpacing.l),
child: ZetaTooltip(
child: Text(text),
rounded: rounded,
arrowDirection: direction,
),
);
},
),
);
}
212 changes: 212 additions & 0 deletions lib/src/components/tooltip/tooltip.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

import '../../../zeta_flutter.dart';

/// The direction of [ZetaTooltip]'s arrow
enum ZetaTooltipArrowDirection {
/// [up]
up,

/// [down]
down,

/// [left]
left,

/// [right]
right,
}

/// [ZetaTooltip]
class ZetaTooltip extends StatelessWidget {
/// Constructor for [ZetaTooltip].
const ZetaTooltip({
super.key,
required this.child,
this.rounded = true,
this.padding,
this.color,
this.textStyle,
this.arrowDirection = ZetaTooltipArrowDirection.down,
this.maxWidth,
});

/// The content of the tooltip.
final Widget child;

/// Determines if the tooltip should have rounded or sharp corners.
/// Default is `true` (rounded).
final bool rounded;

/// The padding inside the [ZetaTooltip].
/// Default is:
/// ```
/// const EdgeInsets.symmetric(
/// horizontal: ZetaSpacing.xs,
/// vertical: ZetaSpacing.xxs,
/// )
/// ```
final EdgeInsets? padding;

/// The color of the tooltip.
/// Default is `zeta.colors.textDefault`.
final Color? color;

/// The text style of the tooltip.
/// Default is:
/// ```
/// ZetaTextStyles.bodyXSmall.copyWith(
/// color: zeta.colors.textInverse,
/// fontWeight: FontWeight.w500,
/// ),
/// ```
final TextStyle? textStyle;

/// The direction of the tooltip's arrow.
/// Default is `ZetaTooltipArrowDirection.down`.
final ZetaTooltipArrowDirection arrowDirection;

/// The maximum width of the tooltip.
final double? maxWidth;

@override
Widget build(BuildContext context) {
final zeta = Zeta.of(context);
final color = this.color ?? zeta.colors.textDefault;

return LayoutBuilder(
builder: (context, constraints) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
if (arrowDirection == ZetaTooltipArrowDirection.up)
Center(
child: CustomPaint(
painter: _FilledArrow(
color: color,
direction: arrowDirection,
),
size: const Size(8, 4),
),
),
Row(
mainAxisSize: MainAxisSize.min,
children: [
if (arrowDirection == ZetaTooltipArrowDirection.left)
Center(
child: CustomPaint(
painter: _FilledArrow(
color: color,
direction: arrowDirection,
),
size: const Size(4, 8),
),
),
ConstrainedBox(
constraints: BoxConstraints(
maxWidth: maxWidth ?? constraints.maxWidth,
),
child: DecoratedBox(
decoration: BoxDecoration(
color: color,
borderRadius: rounded ? ZetaRadius.minimal : null,
),
child: Padding(
padding: padding ??
const EdgeInsets.symmetric(
horizontal: ZetaSpacing.xs,
vertical: ZetaSpacing.xxs,
),
child: DefaultTextStyle(
style: textStyle ??
ZetaTextStyles.bodyXSmall.copyWith(
color: zeta.colors.textInverse,
fontWeight: FontWeight.w500,
),
child: child,
),
),
),
),
if (arrowDirection == ZetaTooltipArrowDirection.right)
Center(
child: CustomPaint(
painter: _FilledArrow(
color: color,
direction: arrowDirection,
),
size: const Size(4, 8),
),
),
],
),
if (arrowDirection == ZetaTooltipArrowDirection.down)
Center(
child: CustomPaint(
painter: _FilledArrow(
color: color,
direction: arrowDirection,
),
size: const Size(8, 4),
),
),
],
);
},
);
}

@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
..add(DiagnosticsProperty<bool>('rounded', rounded))
..add(DiagnosticsProperty<EdgeInsets?>('padding', padding))
..add(ColorProperty('color', color))
..add(DiagnosticsProperty<TextStyle?>('textStyle', textStyle))
..add(EnumProperty<ZetaTooltipArrowDirection>('arrowDirection', arrowDirection))
..add(DoubleProperty('maxWidth', maxWidth));
}
}

class _FilledArrow extends CustomPainter {
_FilledArrow({
required this.direction,
this.color,
});

final Color? color;
final ZetaTooltipArrowDirection direction;

@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..style = PaintingStyle.fill
..color = color ?? Colors.transparent;
final path = switch (direction) {
ZetaTooltipArrowDirection.up => Path()
..moveTo(size.width / 2, 0)
..lineTo(0, size.height)
..lineTo(size.width, size.height)
..lineTo(size.width / 2, 0),
ZetaTooltipArrowDirection.left => Path()
..moveTo(size.width, 0)
..lineTo(0, size.height / 2)
..lineTo(size.width, size.height)
..lineTo(size.width, 0),
ZetaTooltipArrowDirection.down => Path()
..lineTo(size.width, 0)
..lineTo(size.width / 2, size.height)
..lineTo(0, 0),
ZetaTooltipArrowDirection.right => Path()
..lineTo(size.width, size.height / 2)
..lineTo(0, size.height)
..lineTo(0, 0),
};
canvas.drawPath(path, paint);
}

@override
bool shouldRepaint(CustomPainter oldDelegate) => false;
}
1 change: 1 addition & 0 deletions lib/zeta_flutter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export 'src/components/stepper/stepper.dart';
export 'src/components/switch/zeta_switch.dart';
export 'src/components/tabs/tab.dart';
export 'src/components/tabs/tab_bar.dart';
export 'src/components/tooltip/tooltip.dart';
export 'src/theme/color_extensions.dart';
export 'src/theme/color_scheme.dart';
export 'src/theme/color_swatch.dart';
Expand Down

0 comments on commit 2783212

Please sign in to comment.