From ee1cba967349ba82356323ea7364e908fa3668a0 Mon Sep 17 00:00:00 2001 From: Leo Farias Date: Mon, 8 Jan 2024 10:30:49 -0500 Subject: [PATCH] Further clean up --- coverage/lcov.info | 273 +++++++++--------- lib/exports.dart | 2 +- lib/src/core/decorator.dart | 19 +- .../decorators/widget_decorator_widget.dart | 6 +- lib/src/decorators/widget_decorators.dart | 23 +- lib/src/factory/mix_provider_data.dart | 12 +- lib/src/factory/style_mix.dart | 17 +- lib/src/specs/icon/icon_util.dart | 12 +- .../pressable/gesture_state.notifier.dart | 38 +-- lib/src/widgets/pressable/gesture_util.dart | 40 --- lib/src/widgets/pressable/gesture_widget.dart | 16 +- .../widgets/pressable/widget_state_util.dart | 61 ++++ test/helpers/testing_utils.dart | 10 +- test/src/factory/style_mix_test.dart | 41 --- .../gesture_state.notifier_test.dart | 32 +- .../pressable/gesture_widget_test.dart | 8 +- ..._test.dart => widget_state_util_test.dart} | 10 +- website/@/lib/helpers.ts | 5 - website/@/lib/utils.ts | 6 - website/app/globals.css | 76 ----- .../components/{CTA.js => CallToAction.tsx} | 0 website/global.css | 6 - website/next-env.d.ts | 1 - website/next.config.js | 2 +- website/pages/_app.js | 9 - website/pages/_app.tsx | 36 +++ website/pages/_document.tsx | 19 ++ website/pages/_meta.json | 3 +- website/pages/docs/concepts/_meta.json | 6 +- website/pages/docs/concepts/decorators.mdx | 233 ++++++++++++++- ...mixable-widgets.mdx => styled-widgets.mdx} | 52 ++-- website/pages/docs/concepts/styling.mdx | 96 +++--- website/pages/docs/concepts/variants.mdx | 107 +++---- website/pages/docs/introduction/_meta.json | 2 +- .../docs/introduction/getting-started.mdx | 33 ++- .../introduction.mdx} | 5 +- website/pages/index.mdx | 14 +- website/postcss.config.js | 3 +- website/public/assets/light.svg | 9 - website/public/assets/mix-icon-dark.svg | 8 + website/public/assets/mix-icon.png | Bin 1766 -> 0 bytes website/public/assets/mix-icon.svg | 42 +-- website/style.css | 24 ++ website/styles.css | 25 -- website/tailwind.config.js | 77 +---- website/{theme.config.js => theme.config.tsx} | 44 +-- website/tsconfig.json | 12 +- 47 files changed, 821 insertions(+), 754 deletions(-) delete mode 100644 lib/src/widgets/pressable/gesture_util.dart create mode 100644 lib/src/widgets/pressable/widget_state_util.dart rename test/src/widgets/pressable/{gesture_util_test.dart => widget_state_util_test.dart} (95%) delete mode 100644 website/@/lib/helpers.ts delete mode 100644 website/@/lib/utils.ts delete mode 100644 website/app/globals.css rename website/components/{CTA.js => CallToAction.tsx} (100%) delete mode 100644 website/global.css delete mode 100644 website/pages/_app.js create mode 100644 website/pages/_app.tsx create mode 100644 website/pages/_document.tsx rename website/pages/docs/concepts/{mixable-widgets.mdx => styled-widgets.mdx} (65%) rename website/pages/docs/{introduction/installation.mdx => overview/introduction.mdx} (79%) delete mode 100644 website/public/assets/light.svg create mode 100644 website/public/assets/mix-icon-dark.svg delete mode 100644 website/public/assets/mix-icon.png create mode 100644 website/style.css delete mode 100644 website/styles.css rename website/{theme.config.js => theme.config.tsx} (83%) diff --git a/coverage/lcov.info b/coverage/lcov.info index 663f073ad..f6f3e2c83 100644 --- a/coverage/lcov.info +++ b/coverage/lcov.info @@ -2164,68 +2164,67 @@ DA:126,45 DA:139,1 DA:140,1 DA:142,3 -DA:153,1 -DA:157,0 -DA:158,0 -DA:164,18 -DA:167,5 -DA:170,2 -DA:175,3 -DA:205,1 -DA:206,2 +DA:145,0 +DA:146,0 +DA:152,18 +DA:155,5 +DA:158,2 +DA:163,3 +DA:193,1 +DA:194,2 +DA:205,0 +DA:206,0 +DA:211,5 +DA:215,5 +DA:216,0 DA:217,0 -DA:218,0 -DA:223,5 -DA:227,5 -DA:228,0 -DA:229,0 -DA:239,6 -DA:242,15 -DA:243,15 -DA:245,5 +DA:227,6 +DA:230,15 +DA:231,15 +DA:233,5 +DA:262,1 +DA:264,1 +DA:269,1 +DA:270,1 DA:274,1 -DA:276,1 +DA:279,3 +DA:280,1 DA:281,1 -DA:282,1 -DA:286,1 -DA:291,3 +DA:283,1 +DA:288,2 +DA:291,2 DA:292,1 -DA:293,1 -DA:295,1 -DA:300,2 -DA:303,2 -DA:304,1 -DA:306,1 -DA:311,1 -DA:312,1 -DA:313,1 +DA:294,1 +DA:299,1 +DA:300,1 +DA:301,1 +DA:305,1 +DA:311,5 +DA:314,1 DA:317,1 -DA:323,5 -DA:326,1 -DA:329,1 -DA:355,1 -DA:359,1 -DA:363,3 -DA:364,2 -DA:365,1 -DA:368,2 -DA:372,4 -DA:374,1 -DA:400,1 -DA:401,1 -DA:403,2 -DA:404,1 -DA:405,2 -DA:409,1 -DA:412,6 -DA:413,18 -DA:426,1 -DA:429,0 -DA:431,0 -DA:432,0 -DA:434,0 -LF:89 -LH:74 +DA:343,1 +DA:347,1 +DA:351,3 +DA:352,2 +DA:353,1 +DA:356,2 +DA:360,4 +DA:362,1 +DA:388,1 +DA:389,1 +DA:391,2 +DA:392,1 +DA:393,2 +DA:397,1 +DA:400,6 +DA:401,18 +DA:414,1 +DA:417,0 +DA:419,0 +DA:420,0 +DA:422,0 +LF:88 +LH:73 end_of_record SF:lib/src/factory/style_mix_ext.dart DA:12,1 @@ -2339,61 +2338,61 @@ LF:42 LH:35 end_of_record SF:lib/src/specs/container/box_util.dart -DA:65,0 -DA:68,3 -DA:84,0 -DA:100,0 +DA:68,0 +DA:71,3 +DA:86,0 +DA:101,0 DA:118,0 -DA:136,0 -DA:154,0 -DA:165,0 -DA:235,0 -DA:305,0 -DA:349,0 -DA:370,0 -DA:399,0 -DA:402,78 -DA:404,5 -DA:405,5 -DA:406,10 -DA:410,3 -DA:411,9 -DA:414,3 -DA:415,7 -DA:418,3 -DA:419,7 -DA:423,9 -DA:425,0 -DA:427,1 -DA:428,1 -DA:430,1 -DA:431,1 -DA:432,0 -DA:436,1 -DA:437,3 -DA:440,3 -DA:441,9 -DA:445,1 -DA:446,1 -DA:447,3 -DA:451,0 -DA:453,0 -DA:456,0 -DA:458,0 -DA:460,0 -DA:462,0 -DA:464,1 -DA:465,3 -DA:467,1 -DA:468,3 -DA:470,5 -DA:481,5 -DA:497,1 -DA:499,1 -DA:500,1 -DA:501,2 -DA:505,1 -DA:506,2 +DA:135,0 +DA:152,0 +DA:163,0 +DA:187,0 +DA:211,0 +DA:236,0 +DA:253,0 +DA:282,0 +DA:285,78 +DA:287,5 +DA:288,5 +DA:289,10 +DA:293,3 +DA:294,9 +DA:297,3 +DA:298,7 +DA:301,3 +DA:302,7 +DA:306,9 +DA:308,0 +DA:310,1 +DA:311,1 +DA:313,1 +DA:314,1 +DA:315,0 +DA:319,1 +DA:320,3 +DA:323,3 +DA:324,9 +DA:328,1 +DA:329,1 +DA:330,3 +DA:334,0 +DA:336,0 +DA:339,0 +DA:341,0 +DA:343,0 +DA:345,0 +DA:347,1 +DA:348,3 +DA:350,1 +DA:351,3 +DA:353,5 +DA:364,5 +DA:380,1 +DA:382,1 +DA:383,1 +DA:384,2 +DA:388,1 +DA:389,2 LF:55 LH:35 end_of_record @@ -2628,13 +2627,13 @@ LF:12 LH:10 end_of_record SF:lib/src/specs/icon/icon_util.dart -DA:9,77 -DA:11,0 -DA:12,0 -DA:15,1 -DA:16,3 +DA:17,77 DA:19,0 DA:20,0 +DA:23,1 +DA:24,3 +DA:27,0 +DA:28,0 LF:7 LH:3 end_of_record @@ -3480,27 +3479,6 @@ DA:71,3 LF:16 LH:12 end_of_record -SF:lib/src/widgets/pressable/gesture_util.dart -DA:7,3 -DA:8,3 -DA:10,3 -DA:11,6 -DA:13,3 -DA:15,4 -DA:18,3 -DA:20,4 -DA:25,2 -DA:28,1 -DA:29,1 -DA:30,3 -DA:31,4 -DA:35,2 -DA:36,2 -DA:37,6 -DA:38,8 -LF:17 -LH:17 -end_of_record SF:lib/src/widgets/pressable/gesture_widget.dart DA:8,0 DA:32,0 @@ -3574,6 +3552,27 @@ DA:175,2 LF:69 LH:36 end_of_record +SF:lib/src/widgets/pressable/widget_state_util.dart +DA:10,3 +DA:13,3 +DA:16,3 +DA:19,6 +DA:22,3 +DA:24,4 +DA:30,3 +DA:32,4 +DA:40,2 +DA:46,1 +DA:47,1 +DA:48,3 +DA:49,4 +DA:56,2 +DA:57,2 +DA:58,6 +DA:59,8 +LF:17 +LH:17 +end_of_record SF:lib/src/helpers/string_ext.dart DA:25,36 DA:27,24 diff --git a/lib/exports.dart b/lib/exports.dart index 28a46559c..cfe703e7b 100644 --- a/lib/exports.dart +++ b/lib/exports.dart @@ -82,5 +82,5 @@ export 'src/variants/variant.dart'; export 'src/widgets/gap_widget.dart'; export 'src/widgets/pressable/gesture_state.dart'; export 'src/widgets/pressable/gesture_state.notifier.dart'; -export 'src/widgets/pressable/gesture_util.dart'; export 'src/widgets/pressable/gesture_widget.dart'; +export 'src/widgets/pressable/widget_state_util.dart'; diff --git a/lib/src/core/decorator.dart b/lib/src/core/decorator.dart index 623e56860..2289c6fc6 100644 --- a/lib/src/core/decorator.dart +++ b/lib/src/core/decorator.dart @@ -3,17 +3,12 @@ import 'package:flutter/material.dart'; import '../factory/mix_provider_data.dart'; import 'attribute.dart'; -abstract class Decorator extends StyleAttribute { - const Decorator(); -} - -abstract class WidgetDecorator> - extends Decorator { +abstract class Decorator> extends StyleAttribute { final Key? key; - const WidgetDecorator({this.key}); + const Decorator({this.key}); /// Linearly interpolate with another [Decorator] object. - WidgetDecorator lerp(covariant WidgetDecorator? other, double t); + Decorator lerp(covariant Decorator? other, double t); @override Object get type => Self; @@ -21,12 +16,12 @@ abstract class WidgetDecorator> Widget build(MixData mix, Widget child); } -abstract class BoxWidgetDecorator> - extends WidgetDecorator { - const BoxWidgetDecorator({super.key}); +abstract class WidgetDecorator> + extends Decorator { + const WidgetDecorator({super.key}); } abstract class FlexWidgetDecorator> - extends WidgetDecorator { + extends Decorator { const FlexWidgetDecorator({super.key}); } diff --git a/lib/src/decorators/widget_decorator_widget.dart b/lib/src/decorators/widget_decorator_widget.dart index ed840342c..0a63723e0 100644 --- a/lib/src/decorators/widget_decorator_widget.dart +++ b/lib/src/decorators/widget_decorator_widget.dart @@ -45,12 +45,12 @@ class RenderWidgetDecorators extends StatelessWidget { Widget build(BuildContext context) { Widget current = child; - final decorators = mix.decoratorsOf(); + final decorators = mix.whereType(); if (decorators.isEmpty) return current; - Map decoratorMap = - AttributeMap(decorators).toMap(); + Map decoratorMap = + AttributeMap(decorators).toMap(); final listOfDecorators = { ...orderOfDecorators, diff --git a/lib/src/decorators/widget_decorators.dart b/lib/src/decorators/widget_decorators.dart index 2f150dee2..62f6a4b34 100644 --- a/lib/src/decorators/widget_decorators.dart +++ b/lib/src/decorators/widget_decorators.dart @@ -9,7 +9,7 @@ import '../core/attribute.dart'; import '../core/decorator.dart'; import '../helpers/lerp_helpers.dart'; -class AspectRatioDecorator extends BoxWidgetDecorator { +class AspectRatioDecorator extends WidgetDecorator { final double aspectRatio; const AspectRatioDecorator(this.aspectRatio, {super.key}); @@ -28,7 +28,7 @@ class AspectRatioDecorator extends BoxWidgetDecorator { AspectRatio(key: key, aspectRatio: aspectRatio, child: child); } -class VisibilityDecorator extends BoxWidgetDecorator { +class VisibilityDecorator extends WidgetDecorator { final bool visible; const VisibilityDecorator(this.visible, {super.key}); @@ -81,7 +81,7 @@ class FlexibleDecorator extends FlexWidgetDecorator } } -class OpacityDecorator extends BoxWidgetDecorator { +class OpacityDecorator extends WidgetDecorator { /// The [opacity] argument must not be null and must be between 0.0 and 1.0 (inclusive). final double opacity; const OpacityDecorator(this.opacity, {super.key}); @@ -100,7 +100,7 @@ class OpacityDecorator extends BoxWidgetDecorator { Widget build(mix, child) => Opacity(key: key, opacity: opacity, child: child); } -class RotateDecorator extends BoxWidgetDecorator { +class RotateDecorator extends WidgetDecorator { final int quarterTurns; const RotateDecorator(this.quarterTurns, {super.key}); @@ -113,11 +113,12 @@ class RotateDecorator extends BoxWidgetDecorator { get props => [quarterTurns]; @override - Widget build(mix, child) => - RotatedBox(key: key, quarterTurns: quarterTurns, child: child); + Widget build(mix, child) { + return RotatedBox(key: key, quarterTurns: quarterTurns, child: child); + } } -class ScaleDecorator extends BoxWidgetDecorator { +class ScaleDecorator extends WidgetDecorator { final double scale; const ScaleDecorator(this.scale, {super.key}); @@ -130,13 +131,14 @@ class ScaleDecorator extends BoxWidgetDecorator { get props => [scale]; @override - Widget build(mix, child) => - Transform.scale(key: key, scale: scale, child: child); + Widget build(mix, child) { + return Transform.scale(key: key, scale: scale, child: child); + } } enum ClipType { path, oval, rect, rRect, triangle } -class ClipDecorator extends BoxWidgetDecorator +class ClipDecorator extends WidgetDecorator with Mergeable { final ClipType clipType; final Clip? clipBehavior; @@ -279,6 +281,7 @@ class ClipTypeUtility } } +/// A utility class for creating [ClipDecorator]s. class ClipDecoratorUtility extends MixUtility { const ClipDecoratorUtility(super.builder); diff --git a/lib/src/factory/mix_provider_data.dart b/lib/src/factory/mix_provider_data.dart index 27a18b44d..d308b4eee 100644 --- a/lib/src/factory/mix_provider_data.dart +++ b/lib/src/factory/mix_provider_data.dart @@ -3,10 +3,9 @@ import 'package:flutter/material.dart'; import '../attributes/variant_attribute.dart'; import '../core/attribute.dart'; import '../core/attributes_map.dart'; -import '../core/decorator.dart'; import '../helpers/compare_mixin.dart'; import '../theme/mix_theme.dart'; -import '../widgets/pressable/gesture_util.dart'; +import '../widgets/pressable/widget_state_util.dart'; import 'style_mix.dart'; /// This class is used for encapsulating all [MixData] related operations. @@ -55,11 +54,6 @@ class MixData with Comparable { return _mergeAttributes(attributes) ?? attributes.last; } - /// Finds all Decorators of type [A]. - Iterable decoratorsOf() { - return _attributes.whereType(); - } - Iterable whereType() { return _attributes.whereType(); } @@ -105,7 +99,7 @@ List applyContextToVisualAttributes( List gestureVariantTypes = []; for (ContextVariantAttribute attr in contextVariants) { - if (attr.variant is GestureVariant) { + if (attr.variant is WidgetStateVariant) { gestureVariantTypes.add(attr); } else { contextVariantTypes.add(attr); @@ -113,7 +107,7 @@ List applyContextToVisualAttributes( } for (MultiVariantAttribute attr in multiVariants) { - if (attr.variant.variants.any((variant) => variant is GestureVariant)) { + if (attr.variant.variants.any((variant) => variant is WidgetStateVariant)) { gestureVariantTypes.add(attr); } else { contextVariantTypes.add(attr); diff --git a/lib/src/factory/style_mix.dart b/lib/src/factory/style_mix.dart index 143e3efbf..f6248f89b 100644 --- a/lib/src/factory/style_mix.dart +++ b/lib/src/factory/style_mix.dart @@ -142,18 +142,6 @@ class Style with Comparable { : mixes.reduce((combinedStyle, mix) => combinedStyle.merge(mix)); } - /// Selects a mix based on a [condition]. - /// - /// Returns [fallback] if the [condition] is true, otherwise returns [style]. - /// - /// Example: - /// ```dart - /// final style = Style.chooser(condition, style, fallbackStyle); - /// ``` - static Style chooser(bool condition, Style style, [Style? fallback]) { - return condition ? style : fallback ?? const Style.empty(); - } - Style _addAttributes(List attributes) { return merge(Style.create(attributes)); } @@ -202,9 +190,8 @@ class Style with Comparable { /// /// Note: /// The attributes from the selected variant (`attr4` and `attr5`) are not applied to the `Style` instance until the `variant` method is called. - SpreadFunctionParams get variant { - return SpreadFunctionParams(variantList); - } + SpreadFunctionParams get variant => + SpreadFunctionParams(variantList); /// Allows to create a new `Style` by using this mix as a base and adding additional attributes. /// diff --git a/lib/src/specs/icon/icon_util.dart b/lib/src/specs/icon/icon_util.dart index fe93da8c6..5bb489511 100644 --- a/lib/src/specs/icon/icon_util.dart +++ b/lib/src/specs/icon/icon_util.dart @@ -5,6 +5,14 @@ import 'icon_attribute.dart'; const icon = IconUtility(); +/// Utility class for building [IconSpecAttribute]s +/// +/// Example: +/// +/// ```dart +/// final icon = IconUtility(); +/// +/// final iconSpec = icon.size(24); class IconUtility extends SpecUtility { const IconUtility(); @@ -16,7 +24,7 @@ class IconUtility extends SpecUtility { return ColorUtility((color) => IconSpecAttribute(color: color)); } - IconSpecAttribute size(double size) { - return _only(size: size); + DoubleUtility get size { + return DoubleUtility((size) => _only(size: size)); } } diff --git a/lib/src/widgets/pressable/gesture_state.notifier.dart b/lib/src/widgets/pressable/gesture_state.notifier.dart index 63c90ebe8..8cd25b498 100644 --- a/lib/src/widgets/pressable/gesture_state.notifier.dart +++ b/lib/src/widgets/pressable/gesture_state.notifier.dart @@ -3,32 +3,32 @@ import 'package:flutter/widgets.dart'; import '../../helpers/compare_mixin.dart'; @immutable -class GestureData with Comparable { +class WidgetStateData with Comparable { final bool focus; final bool hover; - final GestureStatus status; - final GestureState state; + final WidgetStatus status; + final WidgetState state; - const GestureData({ + const WidgetStateData({ required this.focus, required this.status, required this.state, required this.hover, }); - const GestureData.none() + const WidgetStateData.none() : focus = false, hover = false, - status = GestureStatus.disabled, - state = GestureState.none; + status = WidgetStatus.disabled, + state = WidgetState.none; - GestureData copyWith({ + WidgetStateData copyWith({ bool? focus, bool? hover, - GestureStatus? status, - GestureState? state, + WidgetStatus? status, + WidgetState? state, }) { - return GestureData( + return WidgetStateData( focus: focus ?? this.focus, status: status ?? this.status, state: state ?? this.state, @@ -40,34 +40,34 @@ class GestureData with Comparable { get props => [focus, status, state, hover]; } -enum GestureStatus { +enum WidgetStatus { enabled, disabled, } -enum GestureState { +enum WidgetState { none, pressed, longPressed, } -class GestureStateNotifier extends InheritedWidget { - const GestureStateNotifier({ +class WidgetStateNotifier extends InheritedWidget { + const WidgetStateNotifier({ super.key, required super.child, required this.data, }); - static GestureData? of(BuildContext context) { + static WidgetStateData? of(BuildContext context) { return context - .dependOnInheritedWidgetOfExactType() + .dependOnInheritedWidgetOfExactType() ?.data; } - final GestureData data; + final WidgetStateData data; @override - bool updateShouldNotify(GestureStateNotifier oldWidget) { + bool updateShouldNotify(WidgetStateNotifier oldWidget) { return oldWidget.data != data; } } diff --git a/lib/src/widgets/pressable/gesture_util.dart b/lib/src/widgets/pressable/gesture_util.dart deleted file mode 100644 index 83a776b22..000000000 --- a/lib/src/widgets/pressable/gesture_util.dart +++ /dev/null @@ -1,40 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../../helpers/string_ext.dart'; -import '../../variants/variant.dart'; -import 'gesture_state.notifier.dart'; - -final onPress = _onState(GestureState.pressed); -final onLongPress = _onState(GestureState.longPressed); -// final onHover = _onState(GestureState.hover); -final onDisabled = _onStatus(GestureStatus.disabled); -final onEnabled = _onStatus(GestureStatus.enabled); - -final onFocus = ContextVariant( - 'on-focus', - (context) => GestureStateNotifier.of(context)?.focus == true, -); - -final onHover = ContextVariant( - 'on-hover', - (context) => GestureStateNotifier.of(context)?.hover == true, -); - -@immutable -class GestureVariant extends ContextVariant { - const GestureVariant(super.name, super.when); -} - -GestureVariant _onState(GestureState state) { - return GestureVariant( - 'on-${state.name.paramCase}', - (context) => GestureStateNotifier.of(context)?.state == state, - ); -} - -GestureVariant _onStatus(GestureStatus status) { - return GestureVariant( - 'on-${status.name.paramCase}', - (context) => GestureStateNotifier.of(context)?.status == status, - ); -} diff --git a/lib/src/widgets/pressable/gesture_widget.dart b/lib/src/widgets/pressable/gesture_widget.dart index 2708a24d1..213df562a 100644 --- a/lib/src/widgets/pressable/gesture_widget.dart +++ b/lib/src/widgets/pressable/gesture_widget.dart @@ -92,14 +92,14 @@ class PressableWidgetState extends State { return FocusNode(debugLabel: '${widget.runtimeType}'); } - GestureState get _currentGesture { + WidgetState get _currentGesture { // Long pressed has priority over pressed // Due to delay of removing the _press state - if (_longpressed) return GestureState.longPressed; + if (_longpressed) return WidgetState.longPressed; - if (_pressed) return GestureState.pressed; + if (_pressed) return WidgetState.pressed; - return GestureState.none; + return WidgetState.none; } @override @@ -138,9 +138,9 @@ class PressableWidgetState extends State { Widget build(BuildContext context) { final currentGesture = _currentGesture; final currentStatus = - widget.disabled ? GestureStatus.disabled : GestureStatus.enabled; + widget.disabled ? WidgetStatus.disabled : WidgetStatus.enabled; - final onEnabled = currentStatus == GestureStatus.enabled; + final onEnabled = currentStatus == WidgetStatus.enabled; return MergeSemantics( child: Semantics( @@ -165,8 +165,8 @@ class PressableWidgetState extends State { onShowFocusHighlight: (v) => updateState(() => _focus = v), onShowHoverHighlight: (v) => updateState(() => _hover = v), onFocusChange: widget.onFocusChange, - child: GestureStateNotifier( - data: GestureData( + child: WidgetStateNotifier( + data: WidgetStateData( focus: _focus, status: currentStatus, state: currentGesture, diff --git a/lib/src/widgets/pressable/widget_state_util.dart b/lib/src/widgets/pressable/widget_state_util.dart new file mode 100644 index 000000000..8ed2049eb --- /dev/null +++ b/lib/src/widgets/pressable/widget_state_util.dart @@ -0,0 +1,61 @@ +import 'package:flutter/material.dart'; + +import '../../helpers/string_ext.dart'; +import '../../variants/variant.dart'; +import 'gesture_state.notifier.dart'; + +/// Global context variants for handling common widget states and gestures. + +/// Applies styles when the widget is pressed. +final onPress = _onState(WidgetState.pressed); + +/// Applies styles when the widget is long pressed. +final onLongPress = _onState(WidgetState.longPressed); + +/// Applies styles when the widget is disabled. +final onDisabled = _onStatus(WidgetStatus.disabled); + +/// Applies styles when the widget is enabled. +final onEnabled = _onStatus(WidgetStatus.enabled); + +/// Applies styles when the widget has focus. +final onFocus = ContextVariant( + 'on-focus', + (context) => WidgetStateNotifier.of(context)?.focus == true, + + /// Applies the variant only when the GestureStateNotifier's focus property is true. +); + +/// Applies styles when the widget is being hovered over. +final onHover = ContextVariant( + 'on-hover', + (context) => WidgetStateNotifier.of(context)?.hover == true, + + /// Applies the variant only when the GestureStateNotifier's hover property is true. +); + +/// Helper class for creating widget state-based context variants. +@immutable +class WidgetStateVariant extends ContextVariant { + const WidgetStateVariant(super.name, super.when); +} + +/// Creates a [WidgetStateVariant] based on the specified [state]. +/// +/// This function constructs a WidgetStateVariant with a name based on the provided state and a condition that checks if the GestureStateNotifier in the context matches the given state. +WidgetStateVariant _onState(WidgetState state) { + return WidgetStateVariant( + 'on-${state.name.paramCase}', + (context) => WidgetStateNotifier.of(context)?.state == state, + ); +} + +/// Creates a [WidgetStateVariant] based on the specified [status]. +/// +/// Similar to `_onState`, this function creates a WidgetStateVariant with a condition that checks if the GestureStateNotifier in the context matches the provided status. +WidgetStateVariant _onStatus(WidgetStatus status) { + return WidgetStateVariant( + 'on-${status.name.paramCase}', + (context) => WidgetStateNotifier.of(context)?.status == status, + ); +} diff --git a/test/helpers/testing_utils.dart b/test/helpers/testing_utils.dart index cc84047a0..ab940be9d 100644 --- a/test/helpers/testing_utils.dart +++ b/test/helpers/testing_utils.dart @@ -130,15 +130,15 @@ extension WidgetTesterExt on WidgetTester { Future pumpWithPressable( Widget widget, { - GestureData data = const GestureData.none(), - GestureState state = GestureState.none, - GestureStatus status = GestureStatus.enabled, + WidgetStateData data = const WidgetStateData.none(), + WidgetState state = WidgetState.none, + WidgetStatus status = WidgetStatus.enabled, bool focus = false, bool hover = false, }) async { await pumpWidget( MaterialApp( - home: GestureStateNotifier( + home: WidgetStateNotifier( data: data.copyWith( state: state, status: status, @@ -279,7 +279,7 @@ class UtilityTestDtoAttribute, V> } } -class CustomWidgetDecorator extends BoxWidgetDecorator { +class CustomWidgetDecorator extends WidgetDecorator { const CustomWidgetDecorator({super.key}); @override Widget build(mix, child) { diff --git a/test/src/factory/style_mix_test.dart b/test/src/factory/style_mix_test.dart index 936c883e7..5c0bfff49 100644 --- a/test/src/factory/style_mix_test.dart +++ b/test/src/factory/style_mix_test.dart @@ -126,47 +126,6 @@ void main() { }); }); - group('Style.chooser() ', () { - test('Condition is True', () { - const trueAttribute = MockIntScalarAttribute(1); - const falseAttribute = MockDoubleScalarAttribute(2.0); - - final trueStyle = Style(trueAttribute); - final falseStyle = Style(falseAttribute); - - final mix = Style.chooser(true, trueStyle, falseStyle); - - expect(mix.styles.length, 1); - expect(mix.styles.values[0], trueAttribute); - }); - - test('Condition is False', () { - const trueAttribute = MockIntScalarAttribute(1); - const falseAttribute = MockDoubleScalarAttribute(2.0); - - final trueStyle = Style(trueAttribute); - final falseStyle = Style(falseAttribute); - - final mix = Style.chooser(false, trueStyle, falseStyle); - - expect(mix.styles.length, 1); - expect(mix.styles.values[0], falseAttribute); - }); - - test('Both ifTrue and ifFalse Are Same', () { - const sameAttribute = MockBooleanScalarAttribute(true); - - final sameStyle = Style(sameAttribute); - final otherStyle = Style(const MockBooleanScalarAttribute(false)); - - final style = Style.chooser(true, sameStyle, otherStyle); - - expect(style.styles.length, 1); - expect(style.styles.values[0], sameAttribute); - expect(sameStyle, style); - }); - }); - group('Style.selectVariant', () { const attr1 = MockDoubleScalarAttribute(1.0); const attr2 = MockIntScalarAttribute(2); diff --git a/test/src/widgets/pressable/gesture_state.notifier_test.dart b/test/src/widgets/pressable/gesture_state.notifier_test.dart index 13d9c7996..8ef2df679 100644 --- a/test/src/widgets/pressable/gesture_state.notifier_test.dart +++ b/test/src/widgets/pressable/gesture_state.notifier_test.dart @@ -6,62 +6,62 @@ import '../../../helpers/testing_utils.dart'; void main() { group('PressableNotifier', () { - const gestureData = GestureData( - state: GestureState.pressed, - status: GestureStatus.enabled, + const gestureData = WidgetStateData( + state: WidgetState.pressed, + status: WidgetStatus.enabled, focus: true, hover: false, ); test('constructor', () { - final notifier = GestureStateNotifier( + final notifier = WidgetStateNotifier( data: gestureData, child: Container(), ); - expect(notifier.data.state, GestureState.pressed); + expect(notifier.data.state, WidgetState.pressed); expect(notifier.data.focus, true); expect(notifier.child, isA()); }); test('of', () { - final notifier = GestureStateNotifier( + final notifier = WidgetStateNotifier( data: gestureData, child: Container(), ); - final otherNotifier = GestureStateNotifier( - data: const GestureData( + final otherNotifier = WidgetStateNotifier( + data: const WidgetStateData( focus: false, - state: GestureState.none, - status: GestureStatus.disabled, + state: WidgetState.none, + status: WidgetStatus.disabled, hover: false, ), child: Container(), ); - final sameNotifier = GestureStateNotifier( + final sameNotifier = WidgetStateNotifier( data: gestureData, child: Container(), ); expect(notifier.updateShouldNotify(otherNotifier), true); expect(notifier.updateShouldNotify(sameNotifier), false); - expect(GestureStateNotifier.of(MockBuildContext()), null); + expect(WidgetStateNotifier.of(MockBuildContext()), null); }); testWidgets('can get it from context', (tester) async { await tester.pumpWithPressable( Container(), - state: GestureState.pressed, + state: WidgetState.pressed, focus: true, ); final context = tester.element(find.byType(Container)); - final notifier = GestureStateNotifier.of(context); + final notifier = WidgetStateNotifier.of(context); - expect(notifier, isA()); - expect(notifier!.state, GestureState.pressed); + expect(notifier, isA()); + expect(notifier!.state, WidgetState.pressed); expect(notifier.focus, true); }); }); diff --git a/test/src/widgets/pressable/gesture_widget_test.dart b/test/src/widgets/pressable/gesture_widget_test.dart index a8c11e132..998ecb1b5 100644 --- a/test/src/widgets/pressable/gesture_widget_test.dart +++ b/test/src/widgets/pressable/gesture_widget_test.dart @@ -35,12 +35,12 @@ void main() { final firstContext = tester.element(find.byKey(firstKey)); final secondContext = tester.element(find.byKey(secondKey)); - final firstNotifier = GestureStateNotifier.of(firstContext); - final secondNotifier = GestureStateNotifier.of(secondContext); + final firstNotifier = WidgetStateNotifier.of(firstContext); + final secondNotifier = WidgetStateNotifier.of(secondContext); expect(onEnabledAttr.when(firstContext), true); - expect(firstNotifier!.status, GestureStatus.enabled); + expect(firstNotifier!.status, WidgetStatus.enabled); expect(onEnabledAttr.when(secondContext), false); - expect(secondNotifier!.status, GestureStatus.disabled); + expect(secondNotifier!.status, WidgetStatus.disabled); }); } diff --git a/test/src/widgets/pressable/gesture_util_test.dart b/test/src/widgets/pressable/widget_state_util_test.dart similarity index 95% rename from test/src/widgets/pressable/gesture_util_test.dart rename to test/src/widgets/pressable/widget_state_util_test.dart index 78191c744..82a0e071c 100644 --- a/test/src/widgets/pressable/gesture_util_test.dart +++ b/test/src/widgets/pressable/widget_state_util_test.dart @@ -13,7 +13,7 @@ void main() { testWidgets('press state', (tester) async { await tester.pumpWithPressable( Container(), - state: GestureState.pressed, + state: WidgetState.pressed, focus: true, ); @@ -30,7 +30,7 @@ void main() { testWidgets('long press state', (tester) async { await tester.pumpWithPressable( Container(), - state: GestureState.longPressed, + state: WidgetState.longPressed, focus: true, ); @@ -67,7 +67,7 @@ void main() { testWidgets('disabled state', (tester) async { await tester.pumpWithPressable( Container(), - status: GestureStatus.disabled, + status: WidgetStatus.disabled, focus: true, ); @@ -88,7 +88,7 @@ void main() { testWidgets('enabled state', (tester) async { await tester.pumpWithPressable( Container(), - state: GestureState.pressed, + state: WidgetState.pressed, focus: true, ); @@ -109,7 +109,7 @@ void main() { testWidgets('focus state', (tester) async { await tester.pumpWithPressable( Container(), - state: GestureState.pressed, + state: WidgetState.pressed, focus: true, ); diff --git a/website/@/lib/helpers.ts b/website/@/lib/helpers.ts deleted file mode 100644 index 9e3e831fb..000000000 --- a/website/@/lib/helpers.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const canUseDOM = !!( - typeof window !== "undefined" && - window.document && - window.document.createElement -); diff --git a/website/@/lib/utils.ts b/website/@/lib/utils.ts deleted file mode 100644 index d084ccade..000000000 --- a/website/@/lib/utils.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { type ClassValue, clsx } from "clsx" -import { twMerge } from "tailwind-merge" - -export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)) -} diff --git a/website/app/globals.css b/website/app/globals.css deleted file mode 100644 index 6a7572500..000000000 --- a/website/app/globals.css +++ /dev/null @@ -1,76 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - -@layer base { - :root { - --background: 0 0% 100%; - --foreground: 222.2 84% 4.9%; - - --card: 0 0% 100%; - --card-foreground: 222.2 84% 4.9%; - - --popover: 0 0% 100%; - --popover-foreground: 222.2 84% 4.9%; - - --primary: 222.2 47.4% 11.2%; - --primary-foreground: 210 40% 98%; - - --secondary: 210 40% 96.1%; - --secondary-foreground: 222.2 47.4% 11.2%; - - --muted: 210 40% 96.1%; - --muted-foreground: 215.4 16.3% 46.9%; - - --accent: 210 40% 96.1%; - --accent-foreground: 222.2 47.4% 11.2%; - - --destructive: 0 84.2% 60.2%; - --destructive-foreground: 210 40% 98%; - - --border: 214.3 31.8% 91.4%; - --input: 214.3 31.8% 91.4%; - --ring: 222.2 84% 4.9%; - - --radius: 0.5rem; - } - - .dark { - --background: 222.2 84% 4.9%; - --foreground: 210 40% 98%; - - --card: 222.2 84% 4.9%; - --card-foreground: 210 40% 98%; - - --popover: 222.2 84% 4.9%; - --popover-foreground: 210 40% 98%; - - --primary: 210 40% 98%; - --primary-foreground: 222.2 47.4% 11.2%; - - --secondary: 217.2 32.6% 17.5%; - --secondary-foreground: 210 40% 98%; - - --muted: 217.2 32.6% 17.5%; - --muted-foreground: 215 20.2% 65.1%; - - --accent: 217.2 32.6% 17.5%; - --accent-foreground: 210 40% 98%; - - --destructive: 0 62.8% 30.6%; - --destructive-foreground: 210 40% 98%; - - --border: 217.2 32.6% 17.5%; - --input: 217.2 32.6% 17.5%; - --ring: 212.7 26.8% 83.9%; - } -} - -@layer base { - * { - @apply border-border; - } - body { - @apply bg-background text-foreground; - } -} \ No newline at end of file diff --git a/website/components/CTA.js b/website/components/CallToAction.tsx similarity index 100% rename from website/components/CTA.js rename to website/components/CallToAction.tsx diff --git a/website/global.css b/website/global.css deleted file mode 100644 index 28cbc0501..000000000 --- a/website/global.css +++ /dev/null @@ -1,6 +0,0 @@ -@import "tailwindcss/base"; -@import "tailwindcss/components"; -@import "tailwindcss/utilities"; - -@import "nextra-theme-docs/style.css"; -@import "./styles.css"; diff --git a/website/next-env.d.ts b/website/next-env.d.ts index fd36f9494..4f11a03dc 100644 --- a/website/next-env.d.ts +++ b/website/next-env.d.ts @@ -1,6 +1,5 @@ /// /// -/// // NOTE: This file should not be edited // see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/website/next.config.js b/website/next.config.js index 3bb3c316e..d61ac5c50 100644 --- a/website/next.config.js +++ b/website/next.config.js @@ -2,7 +2,7 @@ const withNextra = require("nextra")({ theme: "nextra-theme-docs", - themeConfig: "./theme.config.js", + themeConfig: "./theme.config.tsx", mdxOptions: { remarkPlugins: [] }, }); diff --git a/website/pages/_app.js b/website/pages/_app.js deleted file mode 100644 index 9fe02d36b..000000000 --- a/website/pages/_app.js +++ /dev/null @@ -1,9 +0,0 @@ -import React from "react"; -import "../global.css"; - -export default function MyApp({ Component, pageProps }) { - // Use the layout defined at the page level, if available - const getLayout = Component.getLayout || ((page) => page); - - return getLayout(); -} diff --git a/website/pages/_app.tsx b/website/pages/_app.tsx new file mode 100644 index 000000000..652c32660 --- /dev/null +++ b/website/pages/_app.tsx @@ -0,0 +1,36 @@ +import { Fira_Code, Inter } from "next/font/google"; +import "../style.css"; + +const inter = Inter({ + subsets: ["latin"], + variable: "--font-inter", + display: "swap", +}); + +const firaCode = Fira_Code({ + subsets: ["latin"], + variable: "--font-fira-code", + display: "swap", +}); + +export default function MyApp({ Component, pageProps }) { + // Use the layout defined at the page level, if available + const getLayout = Component.getLayout || ((page) => page); + + return getLayout( +
+ + +
+ ); +} diff --git a/website/pages/_document.tsx b/website/pages/_document.tsx new file mode 100644 index 000000000..6c2699da4 --- /dev/null +++ b/website/pages/_document.tsx @@ -0,0 +1,19 @@ +import Document, { Head, Html, Main, NextScript } from "next/document"; + +// data-theme="dark" + +class CustomDocument extends Document { + render() { + return ( + + + +
+ + + + ); + } +} + +export default CustomDocument; diff --git a/website/pages/_meta.json b/website/pages/_meta.json index 9f87b2500..e100049e9 100644 --- a/website/pages/_meta.json +++ b/website/pages/_meta.json @@ -1,8 +1,7 @@ { "index": { "title": "Introduction", - "type": "page", - "hidden": true + "type": "page" }, "docs": { "title": "Documentation", diff --git a/website/pages/docs/concepts/_meta.json b/website/pages/docs/concepts/_meta.json index 248a21013..063a188c8 100644 --- a/website/pages/docs/concepts/_meta.json +++ b/website/pages/docs/concepts/_meta.json @@ -1,7 +1,7 @@ { "styling": "Styling", - "variants": "Variants", "utilities": "Utilities Fundamentals", - "mixable-widgets": "Mixable widgets", - "decorators": "Decorators" + "variants": "Variants", + "decorators": "Decorators", + "styled-widgets": "Styled Widgets" } diff --git a/website/pages/docs/concepts/decorators.mdx b/website/pages/docs/concepts/decorators.mdx index 6b4f4d956..8ad60aa52 100644 --- a/website/pages/docs/concepts/decorators.mdx +++ b/website/pages/docs/concepts/decorators.mdx @@ -1,36 +1,237 @@ # Decorators -Decorators allow to extend Mix functionality by providing an easy way to define it's Widget composition tree. This allows to keep the a lean core, and give complete control over layout, attribute, and widgets not supported by our `MixableWidgets`. +Decorators in Mix extend functionality by defining the widget composition tree structure, providing support for core widgets, external widgets, and third-party widgets without compromising the simplicity of core Mix. -As an example we will provide the implementation for our `scale` attribute. The Container does not provide a scale property, so the implementation is done by wrapping a `Container` with the `Transform` widget. +## Understanding the Mechanics + +Take the `scale` attribute, for instance. The Container widget doesn't inherently possess the ability to scale. But, by employing a Transform widget as a decorator, we can introduce this effect. ```dart Transform.scale( scale: 0.5, child: Container( - child: const Text('Half sized box'), + child: const Text("Half sized box"), ), ) ``` -Since `Box` is a `Container` it also does not have a `scale` property. However by using a `Decorator` we can accomlish the same effect. +### Creating a decorator + +We can achieve the same effect by creating a custom `**WidgetDecorator**`. + +Creating a decorator is like creating a `**StatelessWidget**`. Extend `**WidgetDecorator**`. Define the properties you want to modify and the widget you want to decorate. + +```dart {2, 15-19} +class ScaleDecorator extends WidgetDecorator { + final double scale; + const ScaleDecorator(this.scale, {super.key}); + + @override + ScaleDecorator lerp(ScaleDecorator? other, double t) { + return ScaleDecorator(lerpDouble(scale, other?.scale, t) ?? scale); + } + + @override + get props => [scale]; + + @override + Widget build(mix, child) { + return Transform.scale( + key: key, + scale: scale, + child: child, + ); + } +} +``` + +### Crafting a decorator utility + +To simplify decorator usage, you can design a utility function that automatically creates the decorator for you. ```dart -Box(style: Style(scale(0.5))); +ScaleDecorator scale(double scale, {Key? key}) => ScaleDecorator(scale, key: key); +``` + +### Using a decorator + +```dart {2} +final style = Style( + scale(0.5), +); + +Box( + style: style, + child: const Text('Half sized box'), +); ``` -## Decorators Catalog +## Built-in decorators + +Mix comes with a set of built-in decorators that can be used out of the box. + +### Scale Decorator + +Decorates a `Box` with a `Transform.scale` widget + +```dart +final style = Style( + scale(0.5), +); -- `aspectRatio`: Aspect ratio -- `opacity`: Opacity -- `rotate`: Rotate in quarter turns -- `scale`: Scale +// Equivalent to +Transform.scale( + scale: 0.5, + child: Box( + child: const Text('Half sized box'), + ), +); +``` + +### Opacity + +Decorates a `Box` with an `Opacity` widget + +```dart +final style = Style( + opacity(0.5), +); + +// Equivalent to +Opacity( + opacity: 0.5, + child: Box( + child: const Text('Half transparent box'), + ), +); +``` + +### Rotate + +Decorates a `Box` with a `Transform.rotate` widget. The parameter is quarter turns. + +```dart +final style = Style( + rotate(1), +); + +// Equivalent to +RotatedBox( + quarterTurns: 1, + child: Box( + child: const Text('Rotated box'), + ), +); +``` -### Flex +**Helper methods** -Apply flex value to a widget that can be used inside of `FlexBox` +- `rotate(1)`: 90 degrees +- `rotate.d90()`: 90 degrees +- `rotate(2)`: 180 degrees +- `rotate.d180()`: 180 degrees +- `rotate(3)`: 270 degrees +- `rotate.d270()`: 270 degrees -- `flex`: Flex value -- `flexFit`: Flex fit -- `expanded`: Expanded -- `flexible`: Flexible +### Aspect Ratio + +Decorates a `Box` with an `AspectRatio` widget + +```dart +final style = Style( + aspectRatio(6/9), +); + +// Equivalent to +AspectRatio( + aspectRatio: 6/9, + child: Box( + child: const Text('Aspect ratio box'), + ), +); +``` + +### Clip + +Decorates a `Box` with different types of `Clip` widgets + +```dart +final style = Style( + clip.oval(), +); + +Box( + style: style, + child: const Text('Oval box'), +); + +// Equivalent to +ClipOval( + child: Box( + child: const Text('Oval box'), + ), +); +``` + +**Helper methods** + +- `clip.oval()`: Wraps with a **ClipOval** widget +- `clip.rrect()`: Wraps with a **ClipRRect** widget +- `clip.rect()`: Wraps with a **ClipRect** widget +- `clip.path()`: Wraps with a **ClipPath** widget +- `clip.triangle()`: Wraps with a **ClipPath** widget that clips to a triangle + +### Visibility + +Decorates a `Box` with a `Visibility` widget + +```dart +final style = Style( + visibility(false), +); + +// Equivalent to +Visibility( + visible: false, + child: Box( + child: const Text('Invisible box'), + ), +); +``` + +**Helper methods** + +- `visibility.on()`: Wraps the **Box** with an **Visibility** widget that is visible +- `visibility.off()`: Wraps the **`**Box**`** with an **`**Visibility**`** widget that is invisible + +### Flexible + +Decorates a `Flex` Styled widget like `FlexBox`, `HBox`, `VBox`, with a `Flexible` widget + +```dart +final style = Style( + flexible(flex:1, fit: FlexFit.tight), +); +``` + +- `flexible(flex:1, fit: FlexFit.tight)`: Wraps the `Flex` Styled widget with a `Flexible` widget + +**Helper methods** + +- `flexible.expanded()`: Equivalent to **Expanded** widget, or `flexible(fit: FlexFit.tight)` +- `flexible.loose()`: Equivalent to **Flexible** widget, or `flexible(fit: FlexFit.loose)` +- `flexible.tight()`: Equivalent to `flexible(fit: FlexFit.tight)` + +This is equivalent to wrapping the `Flex` Styled widget with a `Flexible` widget. + +```dart +Flexible( + flex: 1, + fit: FlexFit.tight, + child: FlexBox( + children: [ + const Text('Flexible box'), + ], + ), +); +``` diff --git a/website/pages/docs/concepts/mixable-widgets.mdx b/website/pages/docs/concepts/styled-widgets.mdx similarity index 65% rename from website/pages/docs/concepts/mixable-widgets.mdx rename to website/pages/docs/concepts/styled-widgets.mdx index 5db3f6bf2..80fd432b4 100644 --- a/website/pages/docs/concepts/mixable-widgets.mdx +++ b/website/pages/docs/concepts/styled-widgets.mdx @@ -5,35 +5,43 @@ title: "Mixable widgets" import Code from "../../../components/Code.js"; -## Mixable Widgets +## Styled Widgets -`package:mix/mix.dart` defines a set of widget primitives that can use _Mix_ `Attributes` and allow them to be rendered with those `Attributes`. +These are widget primitives that can use _Mix_ `Attributes` and be rendered with those `Attributes`. -At first glance it might seem these widgets are doing a lot — in reality, they are simply wrapping basic _Flutter_ widgets and allowing their visual properties to be defined through a _Mix._ +Initially, these widgets may seem complex. However, they primarily wrap basic _Flutter_ widgets and allow their visual properties to be defined through a _Mix._ -The fundamental widget primitive defined in _Mix_ is a `Box`. A `Box` can contain other widgets and a set of `BoxAttributes` to define it's visual properties. +The foundational widget primitive in _Mix_ is a `Box`. It can contain other widgets and a set of `BoxAttributes` to specify its visual properties. -> An easy misconception would be to think that `Box` is **like** a `Container`, but that would be incorrect: `Box` **is** a `Container`. +> It's important to note that a `Box` is not like a `Container`, but rather, it is a `Container`. This means that the code: That means that this: ```dart -Box(style: Style(height(100))); +Box( + style: Style( + height(100), + ), +); ``` -will become the following: +will translate to: ```dart Container(height: 100); ``` -You can think of `Utilities` as shortcuts to defining visual properties. Thus: +Consider `Utilities` as shortcuts for defining visual properties. For instance: ```dart -Box(style: Style(borderRadius(100))); +Box( + style: Style( + border.radius(100), + ), +); ``` -will become the following: +will be rendered as: ```dart Container( @@ -43,22 +51,22 @@ Container( ) ``` -## Mixable catalog +## Catalog of Styled Widgets -Built-in mixable widgets that you can use right-away in your app. +Build-in styled widgets are: ### Box -`Box` is, basically, a `Container`. A mixable that will usually be the base widget to create most of your layouts. +`Box` is, basically, a `Container`. A widget that will usually be the base widget to create most of your layouts. ```dart Box( style: Style( height(100), width(300), - borderRadius(15), - backgroundColor(Colors.amber), - alignment(Alignment.center), + border.radius(15), + backgroundColor.amber(), + alignment.center(), elevation(4) ), ), @@ -85,7 +93,7 @@ FlexBox( ```dart Hbox( - style: Style(gap(6)), + style: Style(gap(6),), children: [ Image.fromAsset('assets/image.png'), VBox( @@ -98,12 +106,12 @@ Hbox( ), ``` -### IconMix +### StyledIcon It's capable of displaying icons and inherit data from parent mixes ```dart -IconMix( +StyledIcon( style: Style( iconSize(30), iconColor(Colors.grey), @@ -114,7 +122,7 @@ IconMix( ### Pressable -A `Pressable` is a mixable widget that can provide the following information for its descendants: +A `Pressable` is a styled widget that can provide the following information for its descendants: - hovering - pressing @@ -156,12 +164,12 @@ Pressable( ), ``` -### TextMix +### StyledText It's capable of rendering text and inherit data from parent mixes ```dart -TextMix( +StyledText( 'Mix is AWESOME!' style: Style( text.style( diff --git a/website/pages/docs/concepts/styling.mdx b/website/pages/docs/concepts/styling.mdx index 021734c75..b36d1e1c3 100644 --- a/website/pages/docs/concepts/styling.mdx +++ b/website/pages/docs/concepts/styling.mdx @@ -7,47 +7,44 @@ import { Callout } from "nextra-theme-docs"; # Styling with Mix -Mix introduces a functional and intuitive approach to styling in Flutter, empowering developers to create UIs that are both visually appealing and maintainable. By embracing the functional style syntax, Mix allows you to define styles in a more declarative and expressive manner, fostering clarity and consistency in your code. +Mix introduces an efficient, user-friendly approach to managing the visual semantics of widgets. By leveraging the functional style syntax, Mix not only enhances the aesthetic appeal of your interfaces but also promotes code maintainability. This methodology is crafted for clarity and consistency, pivotal in streamlining your project’s styling process. -This functional approach enables direct and readable style declarations, resulting in a smoother and more streamlined styling process. Moreover, Mix excels in facilitating style overrides, providing a versatile and flexible way to customize and adapt styles across different widgets. +Emphasizing readable and concise style declarations, Mix significantly simplifies the development workflow. It stands out for its adeptness in handling style overrides, offering remarkable flexibility to customize and adapt styles across diverse widgets with ease. -By leveraging Mix's functional syntax, you can craft elegant widgets efficiently, ensuring a cohesive and dynamic user experience. +## Comprehensive Overview -## Overview +At the core of Mix's styling capabilities is the `Style` class, a robust toolkit for style management and application. It encapsulates a suite of styling attributes and variants, providing a versatile and efficient approach to widget styling. This section delves into the essential features and practical applications of the `Style` class. -The Style class in Mix serves as a foundational utility for managing and applying styles. It encapsulates a collection of styling attributes and variants, offering a powerful and flexible way to define and manipulate styles for widgets. This concept page will guide you through the key features and usage of Style. - -- **Purpose**: Style is designed to manage, and reuse collections of styling attributes and variants, making it easier to apply consistent and reusable styles across your Flutter app. -- **Composition**: It combines multiple styling attributes, such as colors, fonts, sizes, and more, into a single entity that can be applied to widgets. -- **Variants**: Besides standard styling attributes, Style also supports variants, allowing for more dynamic and context-sensitive styling. +- **Functionality**: The `Style` class is engineered for efficient handling and reuse of styling attributes and variants. Its design simplifies the application of uniform and reusable styles throughout your Flutter application. +- **Mechanism**: It integrates various styling aspects, including colors, fonts, dimensions, and more, into a unified construct, streamlining the application of styles to widgets. +- **Advanced Capabilities**: Beyond conventional styling attributes, `Style` also supports dynamic variants, enabling context-responsive and adaptable styling solutions. - The order of the attributes is important, and keep in mind when composing and - overriding them. Styling attributes are merged from left (top) to right - (bottom) so the attributes on the right will override the attributes on the - left. + Important Note: Remember that the sequence of attributes is crucial in their + composition and overriding. Styling attributes merge sequentially, with + subsequent attributes taking precedence. -### Creating a Style +### **Crafting Your Unique Style** -You can create a Mix by calling it's class and passing positional attributes like so +Creating a Mix style is a seamless process. Start by constructing a `Style` object and incorporate your desired attributes: ```dart final style = Style( height(100), width(100), backgroundColor.purple(), - border.radius(10), + borderRadius(10), ); ``` -### **Style Composition** +### **Composing Styles** -Composing styles is a powerful technique in Mix that allows you to combine and merge Style instances to achieve layered and comprehensive styling. This approach promotes modularity, reusability, flexibility, and maintainability in your code. +Create styles by combining and merging multiple Style instances. This technique, called style composition, allows you to build complex styles while ensuring modularity, reusability, flexibility, and maintainability in your codebase. The secret lies in calling the Mix class and passing attributes as arguments. -#### **Mixing Styles** +#### **Mixing Attributes** -To mix styles, simply use the `mix()` method on a Style instance. For example: +Simply use the `mix()` method on a Style instance. For example: ```dart final baseStyle = Style( @@ -63,11 +60,11 @@ final newStyle = baseStyle.mix( ); ``` -In this example, the `newStyle` inherits all attributes from the `baseStyle`, except for the `border.width` and `border.color` attributes, which are overridden by the new values. +In this example, the `newStyle` inherits all attributes from the `baseStyle`, and add `border.width` and `border.color` attributes to it. -#### **Overriding Styles** +#### **Overriding Attributes** -You can also override specific attributes of a style by passing new values to the `mix()` method. For instance: +**Taking Control** You can also override specific attributes of a style by passing new values to the `mix()` method. For instance: ```dart final newStyle = baseStyle.mix( @@ -77,11 +74,37 @@ final newStyle = baseStyle.mix( In this example, the `newStyle` will inherit all attributes from the `baseStyle`, except for the `backgroundColor` attribute, which will be overridden by the new value. -#### **Using the `apply()` Utility** +#### **Combining Styles** + +You can also combine multiple styles into a single one. + +```dart +final newStyle = Style.combine([ + baseStyle, + otherStyle, +]); +``` + +#### Merging Styles + +Use the `merge()` method on a Style instance. For example: + +```dart +final otherStyle = Style( + border.width(2), + border.color.black(), +); + +final newStyle = baseStyle.merge(otherStyle); +``` + +In this example, the `newStyle` will inherit all attributes from both the `baseStyle` and the `otherStyle`, with the `otherStyle` taking priority over the `baseStyle` in case of conflicts. + +#### Applying Styles -Alternatively, you can apply a style as an attribute using the `apply()` utility. This approach gives you more control over the order of the attributes. +To apply styles individually, use `apply()`. This gives you control over their order. -For example, the following code achieves the same result as the previous example, but using `apply`: +In this example, the `backgroundColor` attribute of the `baseStyle` is overridden by the `backgroundColor` attribute of the `newStyle`: ```dart final newStyle = Style( @@ -99,28 +122,9 @@ final newStyle = Style( ); ``` -**Benefits of Composing Styles** +### **Benefits of Composition** - **Modularity**: Break down complex styles into manageable chunks, which can be combined or merged as needed. - **Reusability**: Encourage the reuse of common style elements, reducing redundancy and maintaining consistency across the UI. - **Flexibility**: Dynamically adjust styles based on different conditions or user interactions. - **Maintainability**: Simplify the maintenance of styles, as changes can be made to individual mixes rather than entire stylesheets. - -### **Style.chooser()** - -The `Style.chooser()` method allows you to use a Mix based on a condition. For example: - -```dart -final errorStyle = Style(backgroundColor.red()); -final successStyle = Style(backgroundColor.green()); - -final mix = Style.chooser( - condition: hasError, - ifTrue: errorStyle, - ifFalse: successStyle, -); -``` - -In this example, the `mix` will be set to the `errorStyle` if the `hasError` condition is true, and to the `successStyle` if the condition is false. - -This approach can be useful for creating dynamic styles that adapt to different conditions or user interactions. diff --git a/website/pages/docs/concepts/variants.mdx b/website/pages/docs/concepts/variants.mdx index fb81a93d5..ead23294a 100644 --- a/website/pages/docs/concepts/variants.mdx +++ b/website/pages/docs/concepts/variants.mdx @@ -5,22 +5,19 @@ title: "Variants" import { Callout } from "nextra-theme-docs"; -# Style Variants +# Variants -Variants are powerful tools in Mix, designed to streamline the styling process in Flutter applications. They allow for the grouping and conditional application of styling attributes, enhancing efficiency and adaptability in UI design. +Variants in Mix are tools that simplify variations of a widget styling. They can group style for specific use cases, or to create responsive variants that are applied automatically based on the context. ## Overview -The `Variant` API is designed to be simple and intuitive. There are two types of variants. +Variants play a crucial role in building custom widgets. Often, we encounter styles that appear quite similar, with only a handful of minor yet influential differences. -- **Named variants** are applied manually, and can be used to create custom variants. -- **Context variants** are applied automatically, and can be used to create responsive variants. +Take a button, for instance. It could embody a primary or secondary variant, or maybe even change its style based on the screen's brightness. These subtle transformations, while seemingly small, can significantly shape UI, illustrating the power of Variants. -Variants usage can be broken down in two main parts. The definition of a `Variant`, and the application of the variant within a `Style`. +## Simple Variants -## Named Variants - -Named variants are important when you want to have a very clear control of when a variant can be used, and want to control the over the variant usage and type. +Simple variants define custom styling variations intended for specific use cases. You can manually apply them to Style instances to exercise fine-grained control. ### Defining a Variant @@ -86,7 +83,7 @@ final outlinedStyle = Style( ## Context Variants -Context variants are variants that are applied automatically based on the BuildContext. They are useful when you want to create responsive variants that are applied automatically based on the context. +Context variants are automatically applied based on the `BuildContext`. They are useful for creating responsive variants. ### Defining a Context Variant @@ -108,8 +105,7 @@ final onDark = ContextVariant( To use a context variant in a style, you can call it as a function on a `Style` passing the attributes. -```dart {7-10} - +```dart {6-9} final style = Style( padding(20), border.radius(10), @@ -122,12 +118,10 @@ final style = Style( ); ``` -### Applying a Context Variant - -`ContextVariants` are applied automatically based on the `BuildContext`. Once it is called on a style it will be equivalent to have defined the following: +When the `onDark` variant is applied, it will override the `backgroundColor` and `text.style.color` attributes. When this happens the style will be equivalent to the following: ```dart highlight="2-4" -final onDarkStyle = Style( +final style = Style( padding(20), border.radius(10), backgroundColor.white(), @@ -139,7 +133,9 @@ final onDarkStyle = Style( The operators `|` and `&` can be used to add conditions to your mix: -- `|`: whether one of the variants apply +### OR Operator + +The `|` operator is used in case you want to apply the variant when any of the variants apply. ```dart highlight="3-7" final style = Style( @@ -147,68 +143,77 @@ final style = Style( (onSmall | onMedium)( // Whether it's small OR medium width(300), height(400), - backgroundColor(Colors.white), + backgroundColor.white(), ), ); ``` -- `&`: when all of the variants apply +### AND Operator + +The `&` operator is used in case you want to apply the variant when all of the variants apply. ```dart highlight="3-6" final mix = Style( - padding(20.0), - (onHover & onPress)( // When it's hovering AND pressing - text.style(color: Colors.black), - bold(), + padding(20), + // When it's hovering AND pressing + (onHover & onPress)( + text.style.color.black(), + text.style.bold(), ), ); ``` -The `onNot` operator can also be called to execute the variant content only when the given -variant is not called. For example: +### Not Condition + +While not a traditional negation operator, `onNot` allows you to compose a variant that is applied when the `ContextVariant` apply condition returns false. + +```dart {1, 4-6} +final onDisabled = onNot(onEnabled); -```dart highlight="2-4" final style = Style( - onNot(disabled)( + onDisabled( scale(1.2), ), ); ``` -## Variants catalog - -Mix already has some `Reactive Variants` defined which can be used to create responsive -Widgets. +## Built-in Context Variants -### Pressable +Mix provides a set of pre-defined context variants for adaptive styling: -These are `Variants` that will change based on different _gestures_ and state of the -`Pressable` Widget. +### Orientation -- `onHover()`: Applies attributes on hover. -- `onFocus()`: Applies attributes on focus. -- `onPress()`: Applies attributes when pressing. -- `onDisabled()`: Applies attributes when disabled. +- **`onPortrait()`:** Applies styles when the device is in portrait orientation. +- **`onLandscape()`:** Applies styles when the device is in landscape orientation. ### Breakpoints -- `onSmall()`: Applies attributes when the screen is at least `small` breakpoint. -- `onMedium()`: Applies attributes when the screen is at least `medium` breakpoint. -- `onLarge()`: Applies attributes when the screen is at least `large` breakpoint. +- **`onSmall()`:** Applies styles when the screen is at least the "small" breakpoint. +- **`onXSmall()`:** Applies styles when the screen is at least the "extra small" breakpoint. +- **`onMedium()`:** Applies styles when the screen is at least the "medium" breakpoint. +- **`onLarge()`:** Applies styles when the screen is at least the "large" breakpoint. -Breakpoints for these sizes can be configured in the `MixTheme`: +### Custom Breakpoints -### Orientation +- **`onBreakpoint({minWidth, maxWidth})`:** Create custom context variants for specific screen size ranges. + +### Directionality + +- **`onRTL()`:** Applies styles when the text direction is right-to-left (RTL). +- **`onLTR()`:** Applies styles when the text direction is left-to-right (LTR). -- `onPortrait()`: Applies attributes when the screen is in portrait orientation. -- `onLandscape()`: Applies attributes when the screen is in landscape orientation. +### Brightness -### Dark Mode +- **`onDark()`:** Applies styles when the theme is in dark mode. +- **`onLight()`:** Applies styles when the theme is in light mode. -- `onDark()`: Applies attributes when the theme is in dark mode. -- `onLight()`: Applies attributes when the theme is in light mode. +### Widget State -### State Holding +For the following variants, the widget must be wrapped in a `Pressable` widget or use the `GestureBox` widget. -- `onActive()`: Applies attributes when the widget state is marked as active -- `onInactive()`: Applies attributes when the widget state is marked as inactive +- **`onHover()`:** Applies styles when the widget is hovered. +- **`onPress()`:** Applies styles when the widget is pressed. +- **`onLongPress()`:** Applies styles when the widget is long pressed. +- **`onFocus()`:** Applies styles when the widget is focused. +- **`onDisabled()`:** Applies styles when the widget is disabled. +- **`onEnabled()`:** Applies styles when the widget is enabled. diff --git a/website/pages/docs/introduction/_meta.json b/website/pages/docs/introduction/_meta.json index f3c236e03..1dc6cc52d 100644 --- a/website/pages/docs/introduction/_meta.json +++ b/website/pages/docs/introduction/_meta.json @@ -1,4 +1,4 @@ { - "installation": "Installation", + "index": "Introduction", "getting-started": "Getting started" } diff --git a/website/pages/docs/introduction/getting-started.mdx b/website/pages/docs/introduction/getting-started.mdx index 98bad9eba..d4592747b 100644 --- a/website/pages/docs/introduction/getting-started.mdx +++ b/website/pages/docs/introduction/getting-started.mdx @@ -1,8 +1,27 @@ --- -id: getting-started -title: "Getting started" +id: introduction +title: "Introduction" --- +## The what and why of Mix + +Motivation +Flutter favors composition over inheritance when building widgets. This choice keeps Flutter API extremely easy to interact with and powerful. +However, in our experience, both inheritance and composition are essential when defining presentation attributes. Themes are an excellent example of inheritance but are not extended across all visual properties. +Maintaining a design system is much harder than building it. +When building a design system, it can be challenging to develop and maintain a consistent UI that shares the same design language for widget variations or across different widgets within the design system. +Goals +Provide simple API to compose design and layout attributes for widgets. That can easily be extended, overridden, and combined; we call this a Mix. +Visual attributes should be defined outside of a BuildContext by a composable API shared across the design system. +Style consistently with a global context +Allow to respond to changing requirements quickly +Create adaptive designs and layouts with ease +Principles +Abstract Flutter API, and not modify its behavior. +Development efficiency is gained by the ease of use, consistency, and reusability, not coding speed. +Composability should be a priority. Mixes, Attributes, Widgets, etc. +Designer friendly (use simple standard semantics when possible). + ## Comparison Mix provides a lot of different benefits on how you can define and organize your design tokens, and no documentation would be complete without a syntax comparison between **Mix vs. Without Mix**. @@ -22,15 +41,15 @@ class CustomMixWidget extends StatelessWidget { margin.top(10), margin.bottom(5), elevation(10), - borderRadius(10), - backgroundColor(MaterialTokens.colorScheme.primary), - text.style($button), + border.radius(10), + backgroundColor($md.colors.primary()), + text.style.of($button), text.style(color: $onPrimary), onHover( elevation(2), padding(20), - backgroundColor($secondary), - text.style(color: $onSecondary), + backgroundColor($md.colors.secondary()), + text.style.color($md.colors.onSecondary()), ), ); return Box( diff --git a/website/pages/docs/introduction/installation.mdx b/website/pages/docs/overview/introduction.mdx similarity index 79% rename from website/pages/docs/introduction/installation.mdx rename to website/pages/docs/overview/introduction.mdx index 30771a06f..e1b46d8c1 100644 --- a/website/pages/docs/introduction/installation.mdx +++ b/website/pages/docs/overview/introduction.mdx @@ -1,6 +1,5 @@ --- -id: installation -title: 'Installation' +title: "Introduction" --- Run the following command in the root of your project: @@ -13,4 +12,4 @@ Import it everywhere you use it: ```dart import 'package:mix/mix.dart'; -``` \ No newline at end of file +``` diff --git a/website/pages/index.mdx b/website/pages/index.mdx index 7b8972b80..075f4fd50 100644 --- a/website/pages/index.mdx +++ b/website/pages/index.mdx @@ -2,21 +2,17 @@ title: Mix - Effortlessly build Flutter design systems. --- -import {Callout} from "nextra-theme-docs"; -import CTA from "../components/CTA"; -import Image from 'next/image'; +import { Callout } from "nextra-theme-docs"; +import CallToAction from "../components/CallToAction"; +import Image from "next/image";

- +

Build Flutter design systems expressively and effortlessly. **Mix** offers primitive building blocks to help developers and designers create beautiful and consistent UI. - + Currently used internally to build design systems in Flutter. However, it is diff --git a/website/postcss.config.js b/website/postcss.config.js index 6187972e1..c7399ce3d 100644 --- a/website/postcss.config.js +++ b/website/postcss.config.js @@ -1,9 +1,8 @@ // If you want to use other PostCSS plugins, see the following: // https://tailwindcss.com/docs/using-with-preprocessors +/** @type {import('postcss').Postcss} */ module.exports = { plugins: { - "postcss-import": {}, - "tailwindcss/nesting": {}, tailwindcss: {}, autoprefixer: {}, }, diff --git a/website/public/assets/light.svg b/website/public/assets/light.svg deleted file mode 100644 index 115b84d8e..000000000 --- a/website/public/assets/light.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/website/public/assets/mix-icon-dark.svg b/website/public/assets/mix-icon-dark.svg new file mode 100644 index 000000000..5166856e6 --- /dev/null +++ b/website/public/assets/mix-icon-dark.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/website/public/assets/mix-icon.png b/website/public/assets/mix-icon.png deleted file mode 100644 index e742341c07cc67ad81f74560c23f4434fd569ef7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1766 zcmVr=o7bO_xz=V@}IXR`9n5#>S!0LYekMOGMDL zJ+kK=?wU_MwfPSKqfN-nXa_fK^?Lu%2XB1K%#M@*$h2(DHJ_`z6(s$1&6#!zFxsA_ z;zYr+iJtY-$%$WK+AK3o2MFCSdzOeoswS24A;8N-pbM5fOe@sVbO)>3&%o9sKqylv zbBN;YHKdY`h_R&3UeJ>Lb}-L?$9h6e4qpQ)1D?otGC_R9~6pMLA{&5s7GC8eLd zaPW99xg1zL!dN7ye< z|L*w(rSbw`vS~!|xKA$y`-GXroji`N>m+pF%xlnPz$Y^?k6pMFfMjO>%*hW%o;7T> z=Do%#x2sf;Bdl`ht@6xiv;P$Y>%?sv0qw-_$aUV^%`H~^xMmAmCQrl>*4K5wtpGY= zVYN~2^sJd}l3$Pidt}=dm<^!A7ca$^-40m&jzCcnRYx=#H)Lp-ut9!9sYUOI#)!8B})90-r9^9GFMSYv7j}| zu(lU>u&n#+857ORfwJ>Y>F66Dt-Sos_=p)vmnUv&%aU0Z9eu>#;h1{<|dP-8YoNy@c5)o*xZ#_yo=v#T^{^7UZZQOY2 zQhq9)?-F20`swslS8o5t%fY{Xjdt;?gVxqQ-+AIVZ+4rRZCsqPqwe~=ldk#GNehbK zO^V@|A5(d+_T>3yb}g_PW_hFZ)(HmZ-V)rpQh9#PTVz>8VRVY&>Cene->qLNaT?er z1+OY)_x(zkn`&iN#zVE4&1;7UpNZe||%<7enL z`fYY)G - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + diff --git a/website/style.css b/website/style.css new file mode 100644 index 000000000..27fa60213 --- /dev/null +++ b/website/style.css @@ -0,0 +1,24 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +body { + background: linear-gradient( + to bottom, + rgba(255, 255, 255, 0) 0%, + rgba(255, 255, 255, 1) 300px + ), + fixed 0 0 / 20px 20px radial-gradient(#d1d1d1 1px, transparent 0), + fixed 10px 10px / 20px 20px radial-gradient(#d1d1d1 1px, transparent 0); +} + +.dark body { + background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, #111 300px), + fixed 0 0 / 20px 20px radial-gradient(#7700ff 1px, transparent 0), + fixed 10px 10px / 20px 20px radial-gradient(#7700ff 1px, transparent 0); +} + +pre { + background-color: #120d1c !important; + border: 1px solid #422875; +} diff --git a/website/styles.css b/website/styles.css deleted file mode 100644 index 8704641e9..000000000 --- a/website/styles.css +++ /dev/null @@ -1,25 +0,0 @@ -body { - font-family: "Inter", sans-serif; - font-weight: 400; -} - -h1, -h2, -h3, -h4, -h5, -h6 { - font-family: "Inter", sans-serif; - font-weight: 700; -} - -i, -b, -em { - font-family: "Inter", sans-serif; - font-weight: 600; -} - -pre code span { - font-family: "Fira Code", monospace; -} diff --git a/website/tailwind.config.js b/website/tailwind.config.js index 7cb7e37ab..c89b97776 100644 --- a/website/tailwind.config.js +++ b/website/tailwind.config.js @@ -1,77 +1,18 @@ /** @type {import('tailwindcss').Config} */ module.exports = { - darkMode: ["class"], content: [ - './pages/**/*.{ts,tsx}', - './components/**/*.{ts,tsx}', - './app/**/*.{ts,tsx}', - './src/**/*.{ts,tsx}', + "./pages/**/*.{js,ts,jsx,tsx,mdx}", + "./components/**/*.{js,ts,jsx,tsx}", + "./theme.config.tsx", ], - prefix: "", theme: { - container: { - center: true, - padding: "2rem", - screens: { - "2xl": "1400px", - }, - }, extend: { - colors: { - border: "hsl(var(--border))", - input: "hsl(var(--input))", - ring: "hsl(var(--ring))", - background: "hsl(var(--background))", - foreground: "hsl(var(--foreground))", - primary: { - DEFAULT: "hsl(var(--primary))", - foreground: "hsl(var(--primary-foreground))", - }, - secondary: { - DEFAULT: "hsl(var(--secondary))", - foreground: "hsl(var(--secondary-foreground))", - }, - destructive: { - DEFAULT: "hsl(var(--destructive))", - foreground: "hsl(var(--destructive-foreground))", - }, - muted: { - DEFAULT: "hsl(var(--muted))", - foreground: "hsl(var(--muted-foreground))", - }, - accent: { - DEFAULT: "hsl(var(--accent))", - foreground: "hsl(var(--accent-foreground))", - }, - popover: { - DEFAULT: "hsl(var(--popover))", - foreground: "hsl(var(--popover-foreground))", - }, - card: { - DEFAULT: "hsl(var(--card))", - foreground: "hsl(var(--card-foreground))", - }, - }, - borderRadius: { - lg: "var(--radius)", - md: "calc(var(--radius) - 2px)", - sm: "calc(var(--radius) - 4px)", - }, - keyframes: { - "accordion-down": { - from: { height: "0" }, - to: { height: "var(--radix-accordion-content-height)" }, - }, - "accordion-up": { - from: { height: "var(--radix-accordion-content-height)" }, - to: { height: "0" }, - }, - }, - animation: { - "accordion-down": "accordion-down 0.2s ease-out", - "accordion-up": "accordion-up 0.2s ease-out", + fontFamily: { + sans: ["var(--font-inter)"], + mono: ["var(--font-jetbrains-mono)"], }, }, }, - plugins: [require("tailwindcss-animate")], -} \ No newline at end of file + plugins: [], + darkMode: "class", +}; diff --git a/website/theme.config.js b/website/theme.config.tsx similarity index 83% rename from website/theme.config.js rename to website/theme.config.tsx index b66770cb5..c695d0fcf 100644 --- a/website/theme.config.js +++ b/website/theme.config.tsx @@ -1,6 +1,6 @@ import Image from "next/image"; -import CustomSearch from "./components/Search"; import { useRouter } from "next/router"; +import CustomSearch from "./components/Search"; const themeConfig = { useNextSeoProps() { @@ -14,25 +14,21 @@ const themeConfig = { logo: ( <> Mix Icon - Mix - - Effortlessly build Flutter design systems. - + Mix ), - project: { link: "https://github.com/conceptadev/mix", }, docsRepositoryBase: "https://github.com/conceptadev/mix/blob/main", - search: true, - customSearch: , + search: { + component: , + }, head: ( <> @@ -91,17 +87,26 @@ const themeConfig = { }, toc: { float: true, + backToTop: true, }, - - footer: true, + darkMode: true, nextThemes: { defaultTheme: "dark", + forcedTheme: "dark", }, sidebar: { - defaultMenuCollapseLevel: Infinity, + defaultMenuCollapseLevel: 5, autoCollapse: false, toggleButton: false, }, + primaryHue: { + light: 200, + dark: 251, + }, + primarySaturation: { + light: 50, + dark: 50, + }, editLink: { text: "Edit this page on GitHub", }, @@ -113,13 +118,16 @@ const themeConfig = { target="_blank" rel="noreferrer" > - {" "} + mix logo{" "}
), }, - - darkMode: true, }; export default themeConfig; diff --git a/website/tsconfig.json b/website/tsconfig.json index 18a501d28..b88dedffa 100644 --- a/website/tsconfig.json +++ b/website/tsconfig.json @@ -1,11 +1,7 @@ { "compilerOptions": { "target": "es5", - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], + "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "strict": false, @@ -29,11 +25,9 @@ "next-env.d.ts", "**/*.ts", "**/*.tsx", - "pages/_app.js", + "pages/_app.ts", "next.config.js", ".next/types/**/*.ts" ], - "exclude": [ - "node_modules" - ] + "exclude": ["node_modules"] }