Skip to content

Commit

Permalink
feat: Icon button (#26)
Browse files Browse the repository at this point in the history
* Add icon button

* Update action to run on pull_request_target

---------

Co-authored-by: Osman <[email protected]>
Co-authored-by: Luke <[email protected]>
  • Loading branch information
3 people committed Feb 21, 2024
1 parent 9f0e7f2 commit 88cd90a
Show file tree
Hide file tree
Showing 6 changed files with 351 additions and 132 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
name: CI - Pull Request
on: pull_request
on:
pull_request_target:
types:
- opened

jobs:
up-to-date:
Expand Down
43 changes: 39 additions & 4 deletions example/lib/pages/components/button_example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,21 @@ class _ButtonExampleState extends State<ButtonExample> {
Column(children: buttons(ZetaWidgetBorder.sharp)),
Text('Full Buttons', style: ZetaTextStyles.displayMedium),
Column(children: buttons(ZetaWidgetBorder.full)),
Text('Floating Action Buttons', style: ZetaTextStyles.displayMedium),
Text('Tap buttons to change current FAB: ', style: ZetaTextStyles.bodyMedium),
Wrap(children: fabs.divide(SizedBox.square(dimension: 10)).toList()),
].divide(const SizedBox.square(dimension: ZetaSpacing.m)).toList(),
Text('Icon Buttons', style: ZetaTextStyles.displayLarge),
Text('Rounded Buttons', style: ZetaTextStyles.displayMedium),
Column(children: inputButtons(ZetaWidgetBorder.rounded)),
Text('Sharp Buttons', style: ZetaTextStyles.displayMedium),
Column(children: inputButtons(ZetaWidgetBorder.sharp)),
Text('Floating Action Buttons',
style: ZetaTextStyles.displayMedium),
Text('Tap buttons to change current FAB: ',
style: ZetaTextStyles.bodyMedium),
Wrap(
children:
fabs.divide(SizedBox.square(dimension: 10)).toList()),
]
.divide(const SizedBox.square(dimension: ZetaSpacing.m))
.toList(),
),
),
Expanded(child: const SizedBox()),
Expand Down Expand Up @@ -136,4 +147,28 @@ class _ButtonExampleState extends State<ButtonExample> {
),
).reversed.divide(const SizedBox.square(dimension: ZetaSpacing.m)).toList();
}

List<Widget> inputButtons(ZetaWidgetBorder borderType) {
return List.generate(
ZetaWidgetSize.values.length + 1,
(index) => SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisSize: MainAxisSize.min,
children: List.generate(
ZetaButtonType.values.length,
(index2) => ZetaIconButton(
onPressed: index == 0 ? null : () {},
type: ZetaButtonType.values[index2],
size: ZetaWidgetSize.values[index == 0 ? 0 : index - 1],
borderType: borderType,
icon: ZetaButtonType.values[index2] == ZetaButtonType.negative
? ZetaIcons.delete_round
: ZetaIcons.more_horizontal_round,
),
).divide(const SizedBox.square(dimension: ZetaSpacing.m)).toList(),
),
),
).reversed.divide(const SizedBox.square(dimension: ZetaSpacing.m)).toList();
}
}
133 changes: 6 additions & 127 deletions lib/src/components/buttons/button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,71 +4,6 @@ import 'package:flutter/material.dart';
import '../../../zeta_flutter.dart';

///Button types
enum ZetaButtonType {
/// Background: Primary color; defaults to blue.
/// Border: None.
primary,

/// Background: Secondary color; defaults to yellow.
/// Border: None.
secondary,

/// Background: Positive color; defaults to green.
/// Border: None.
positive,

/// Background: Negative color; defaults to red.
/// Border: None.
negative,

/// Background: None.
/// Border: Primary color; defaults to blue.
outline,

/// Background: None.
/// Border: Subtle color; defaults to cool grey.
outlineSubtle,

/// Background: None.
/// Border: None.
/// Foreground color: Primary; defaults to blue.
text,
}

extension on ZetaButtonType {
ZetaColorSwatch color(ZetaColors colors) {
switch (this) {
case ZetaButtonType.secondary:
return colors.secondary;
case ZetaButtonType.positive:
return colors.positive;
case ZetaButtonType.negative:
return colors.negative;
case ZetaButtonType.outline:
case ZetaButtonType.primary:
return colors.primary;
case ZetaButtonType.outlineSubtle:
case ZetaButtonType.text:
return colors.cool;
}
}

bool get border => this == ZetaButtonType.outline || this == ZetaButtonType.outlineSubtle;
bool get solid => index < 4;
}

extension on ZetaWidgetBorder {
BorderRadius get radius {
switch (this) {
case ZetaWidgetBorder.sharp:
return ZetaRadius.none;
case ZetaWidgetBorder.rounded:
return ZetaRadius.minimal;
case ZetaWidgetBorder.full:
return ZetaRadius.full;
}
}
}
///Zeta Button
class ZetaButton extends StatelessWidget {
Expand Down Expand Up @@ -184,10 +119,11 @@ class ZetaButton extends StatelessWidget {
Widget build(BuildContext context) {
final colors = Zeta.of(context).colors;
return ConstrainedBox(
constraints: BoxConstraints(minHeight: _minConstraints, minWidth: _minConstraints),
constraints:
BoxConstraints(minHeight: _minConstraints, minWidth: _minConstraints),
child: FilledButton(
onPressed: onPressed,
style: _buttonStyle(colors),
style: buttonStyle(colors, borderType, type, null),
child: SelectionContainer.disabled(
child: label.isEmpty
? const SizedBox()
Expand All @@ -200,66 +136,9 @@ class ZetaButton extends StatelessWidget {
);
}

ButtonStyle _buttonStyle(ZetaColors colors) {
return ButtonStyle(
minimumSize: MaterialStateProperty.all(const Size.square(32)),
shape: MaterialStateProperty.all(RoundedRectangleBorder(borderRadius: borderType.radius)),
backgroundColor: MaterialStateProperty.resolveWith<Color?>(
(states) {
if (states.contains(MaterialState.disabled)) {
return colors.surfaceDisabled;
}
if (states.contains(MaterialState.pressed)) {
return type.solid ? type.color(colors).shade70 : colors.primary.shade10;
}
if (states.contains(MaterialState.hovered)) {
return type.solid ? type.color(colors).shade50 : colors.cool.shade20;
}
return type.solid ? type.color(colors) : Colors.transparent;
},
),
foregroundColor: MaterialStateProperty.resolveWith<Color?>(
(states) {
if (states.contains(MaterialState.disabled)) {
return colors.textDisabled;
}
switch (type) {
case ZetaButtonType.outline:
case ZetaButtonType.text:
return colors.primary;
case ZetaButtonType.outlineSubtle:
return colors.textDefault;
case ZetaButtonType.primary:
case ZetaButtonType.secondary:
case ZetaButtonType.positive:
case ZetaButtonType.negative:
return type.color(colors).onColor;
}
},
),
overlayColor: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
return null;
}),
side: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (type.border && states.contains(MaterialState.disabled)) {
return BorderSide(color: colors.cool.shade40);
}
// TODO(thelukewalton): This removes a defualt border when focused, rather than adding a second border when focused.
if (states.contains(MaterialState.focused)) {
return BorderSide(color: colors.blue, width: ZetaSpacing.x0_5);
}
if (type.border) {
return BorderSide(color: type == ZetaButtonType.outline ? colors.primary.border : colors.borderDefault);
}

return null;
}),
elevation: const MaterialStatePropertyAll(0),
padding: MaterialStateProperty.all(EdgeInsets.zero),
);
}

TextStyle get _textStyle => size == ZetaWidgetSize.small ? ZetaTextStyles.labelMedium : ZetaTextStyles.labelLarge;
TextStyle get _textStyle => size == ZetaWidgetSize.small
? ZetaTextStyles.labelMedium
: ZetaTextStyles.labelLarge;

double get _minConstraints {
switch (size) {
Expand Down
155 changes: 155 additions & 0 deletions lib/src/components/buttons/button_style.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import 'package:flutter/material.dart';

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

/// Shared enum for type of buttons.
enum ZetaButtonType {
/// Background: Primary color; defaults to blue.
/// Border: None.
primary,

/// Background: Secondary color; defaults to yellow.
/// Border: None.
secondary,

/// Background: Positive color; defaults to green.
/// Border: None.
positive,

/// Background: Negative color; defaults to red.
/// Border: None.
negative,

/// Background: None.
/// Border: Primary color; defaults to blue.
outline,

/// Background: None.
/// Border: Subtle color; defaults to cool grey.
outlineSubtle,

/// Background: None.
/// Border: None.
/// Foreground color: Primary; defaults to blue.
text,
}

/// Button utility functions for styling
extension ButtonFunctions on ZetaButtonType {
/// Returns color based on [ZetaButtonType]
ZetaColorSwatch color(ZetaColors colors) {
switch (this) {
case ZetaButtonType.secondary:
return colors.secondary;
case ZetaButtonType.positive:
return colors.positive;
case ZetaButtonType.negative:
return colors.negative;
case ZetaButtonType.outline:
case ZetaButtonType.primary:
return colors.primary;
case ZetaButtonType.outlineSubtle:
case ZetaButtonType.text:
return colors.cool;
}
}

/// Returns if button has border
bool get border =>
this == ZetaButtonType.outline || this == ZetaButtonType.outlineSubtle;

///Returns if button is solid
bool get solid => index < 4;
}

extension on ZetaColors {}

///Border utility functions
extension BorderFunctions on ZetaWidgetBorder {
///Returns radius based on [ZetaWidgetBorder]
BorderRadius get radius {
switch (this) {
case ZetaWidgetBorder.sharp:
return ZetaRadius.none;
case ZetaWidgetBorder.rounded:
return ZetaRadius.minimal;
case ZetaWidgetBorder.full:
return ZetaRadius.full;
}
}
}

/// Shared buttonStyle for buttons and icon buttons
ButtonStyle buttonStyle(ZetaColors colors, ZetaWidgetBorder borderType,
ZetaButtonType type, Color? backgroundColor) {
final ZetaColorSwatch color = backgroundColor != null
? ZetaColorSwatch.fromColor(backgroundColor)
: type.color(colors);

final bool isSolid = type.solid || backgroundColor != null;

return ButtonStyle(
minimumSize: MaterialStateProperty.all(const Size.square(32)),
shape: MaterialStateProperty.all(
RoundedRectangleBorder(borderRadius: borderType.radius),
),
backgroundColor: MaterialStateProperty.resolveWith<Color?>(
(states) {
if (states.contains(MaterialState.disabled)) {
return colors.surfaceDisabled;
}
if (states.contains(MaterialState.pressed)) {
return isSolid ? color.shade70 : colors.primary.shade10;
}
if (states.contains(MaterialState.hovered)) {
return isSolid ? color.shade50 : colors.cool.shade20;
}
if (backgroundColor != null) return backgroundColor;
return isSolid ? color : Colors.transparent;
},
),
foregroundColor: MaterialStateProperty.resolveWith<Color?>(
(states) {
if (states.contains(MaterialState.disabled)) {
return colors.textDisabled;
}
switch (type) {
case ZetaButtonType.outline:
case ZetaButtonType.text:
return colors.primary;
case ZetaButtonType.outlineSubtle:
return colors.textDefault;
case ZetaButtonType.primary:
case ZetaButtonType.secondary:
case ZetaButtonType.positive:
case ZetaButtonType.negative:
return color.onColor;
}
},
),
overlayColor:
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
return null;
}),
side: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (type.border && states.contains(MaterialState.disabled)) {
return BorderSide(color: colors.cool.shade40);
}
// TODO(thelukewalton): This removes a defualt border when focused, rather than adding a second border when focused.
if (states.contains(MaterialState.focused)) {
return BorderSide(color: colors.blue, width: ZetaSpacing.x0_5);
}
if (type.border) {
return BorderSide(
color: type == ZetaButtonType.outline
? colors.primary.border
: colors.borderDefault,
);
}

return null;
}),
elevation: const MaterialStatePropertyAll(0),
padding: MaterialStateProperty.all(EdgeInsets.zero),
);
}
Loading

0 comments on commit 88cd90a

Please sign in to comment.