From e8ede02505a744824aa156ebf58a314754e04424 Mon Sep 17 00:00:00 2001 From: Sigve Hansen Date: Thu, 10 Sep 2026 16:10:10 +0200 Subject: [PATCH] feat(design): add message variant colors to design system --- .../features/design_system/design_system.dart | 128 ++++++++++-------- .../src/features/graphql/queries/page.graphql | 1 + .../graphql/queries/page.graphql.dart | 34 ++++- .../graphql/queries/sections.graphql.dart | 54 +++++++- 4 files changed, 157 insertions(+), 60 deletions(-) diff --git a/bccm_core/lib/src/features/design_system/design_system.dart b/bccm_core/lib/src/features/design_system/design_system.dart index a6c38d5..51e5b18 100644 --- a/bccm_core/lib/src/features/design_system/design_system.dart +++ b/bccm_core/lib/src/features/design_system/design_system.dart @@ -1,6 +1,7 @@ library; import '../../utils/primitive_extensions.dart'; + import 'package:flutter/material.dart'; import 'package:responsive_framework/responsive_framework.dart'; @@ -8,11 +9,7 @@ import 'package:responsive_framework/responsive_framework.dart'; /// See https://api.flutter.dev/flutter/widgets/InheritedWidget-class.html class DesignSystem extends InheritedWidget { final DesignSystemData designSystem; - DesignSystem({ - super.key, - required Widget Function(BuildContext) builder, - required this.designSystem, - }) : super(child: Builder(builder: builder)); + DesignSystem({super.key, required Widget Function(BuildContext) builder, required this.designSystem}) : super(child: Builder(builder: builder)); @override bool updateShouldNotify(DesignSystem oldWidget) => designSystem != oldWidget.designSystem; @@ -89,6 +86,7 @@ class DesignSystemColors { final Color background2; final Color separatorOnLight; final Color separator2; + final DesignSystemMessageColors messages; DesignSystemColors({ required this.tint1, @@ -104,22 +102,35 @@ class DesignSystemColors { required this.background2, required this.separatorOnLight, required this.separator2, + required this.messages, }); } -enum ButtonVariant { - primary, - secondary, - dark, - green, - red, +/// Colors for the message section variants, see `MessageStyleVariant` in the GraphQL schema. +class DesignSystemMessageColors { + final MessageColors info; + final MessageColors warning; + final MessageColors error; + + const DesignSystemMessageColors({required this.info, required this.warning, required this.error}); } -enum ButtonImagePosition { - left, - right, +/// Colors for a single message variant. +class MessageColors { + final Color background; + final Color border; + final Color text; + + /// Used for the variant icon and for links in the message body. + final Color accent; + + const MessageColors({required this.background, required this.border, required this.text, required this.accent}); } +enum ButtonVariant { primary, secondary, dark, green, red } + +enum ButtonImagePosition { left, right } + abstract class DesignSystemButtons { Widget small({ Key? key, @@ -167,37 +178,37 @@ extension ResponsiveButton on DesignSystemButtons { bool disabled = false, bool? autofocus, }) { - return Builder(builder: (context) { - final bp = ResponsiveBreakpoints.of(context); - if (bp.smallerThan(TABLET)) { - return small( - key: key, - variant: variant, - labelText: labelText, - onPressed: onPressed, - image: image, - disabled: disabled, - autofocus: autofocus, - ); - } else { - return large( - key: key, - variant: variant, - labelText: labelText, - onPressed: onPressed, - image: image, - disabled: disabled, - autofocus: autofocus, - ); - } - }); + return Builder( + builder: (context) { + final bp = ResponsiveBreakpoints.of(context); + if (bp.smallerThan(TABLET)) { + return small( + key: key, + variant: variant, + labelText: labelText, + onPressed: onPressed, + image: image, + disabled: disabled, + autofocus: autofocus, + ); + } else { + return large( + key: key, + variant: variant, + labelText: labelText, + onPressed: onPressed, + image: image, + disabled: disabled, + autofocus: autofocus, + ); + } + }, + ); } } class DesignSystemInputDecorations { - DesignSystemInputDecorations({ - required this.textFormField, - }); + DesignSystemInputDecorations({required this.textFormField}); final InputDecoration textFormField; } @@ -207,21 +218,24 @@ class TypographyListForDebugging extends StatelessWidget { @override Widget build(BuildContext context) { final textStyles = DesignSystem.of(context).textStyles; - return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text('Headline 1', style: textStyles.headline1), - Text('Headline 2', style: textStyles.headline2), - Text('Title 1', style: textStyles.title1), - Text('Title 2', style: textStyles.title2), - Text('Title 3', style: textStyles.title3), - Text('Body 1', style: textStyles.body1), - Text('Body 2', style: textStyles.body2), - Text('Caption 1', style: textStyles.caption1), - Text('Caption 2', style: textStyles.caption2), - Text('Caption 3', style: textStyles.caption3), - Text('Button 1', style: textStyles.button1), - Text('Button 2', style: textStyles.button2), - Text('button 2 upper'.toUpperCase(), style: textStyles.button2), - Text('overline'.toUpperCase(), style: textStyles.overline), - ]); + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Headline 1', style: textStyles.headline1), + Text('Headline 2', style: textStyles.headline2), + Text('Title 1', style: textStyles.title1), + Text('Title 2', style: textStyles.title2), + Text('Title 3', style: textStyles.title3), + Text('Body 1', style: textStyles.body1), + Text('Body 2', style: textStyles.body2), + Text('Caption 1', style: textStyles.caption1), + Text('Caption 2', style: textStyles.caption2), + Text('Caption 3', style: textStyles.caption3), + Text('Button 1', style: textStyles.button1), + Text('Button 2', style: textStyles.button2), + Text('button 2 upper'.toUpperCase(), style: textStyles.button2), + Text('overline'.toUpperCase(), style: textStyles.overline), + ], + ); } } diff --git a/bccm_core/lib/src/features/graphql/queries/page.graphql b/bccm_core/lib/src/features/graphql/queries/page.graphql index d02aa10..d4ed6ab 100644 --- a/bccm_core/lib/src/features/graphql/queries/page.graphql +++ b/bccm_core/lib/src/features/graphql/queries/page.graphql @@ -220,6 +220,7 @@ fragment Section on Section { ... on MessageSection { id messages { + title content variant style { diff --git a/bccm_core/lib/src/features/graphql/queries/page.graphql.dart b/bccm_core/lib/src/features/graphql/queries/page.graphql.dart index 067dbed..fce491a 100644 --- a/bccm_core/lib/src/features/graphql/queries/page.graphql.dart +++ b/bccm_core/lib/src/features/graphql/queries/page.graphql.dart @@ -22180,6 +22180,13 @@ const fragmentDefinitionSection = FragmentDefinitionNode( directives: [], selectionSet: SelectionSetNode( selections: [ + FieldNode( + name: NameNode(value: 'title'), + alias: null, + arguments: [], + directives: [], + selectionSet: null, + ), FieldNode( name: NameNode(value: 'content'), alias: null, @@ -64157,6 +64164,7 @@ class _CopyWithStubImpl$Fragment$Section$$MessageSection class Fragment$Section$$MessageSection$messages { Fragment$Section$$MessageSection$messages({ + required this.title, required this.content, required this.variant, required this.style, @@ -64166,11 +64174,13 @@ class Fragment$Section$$MessageSection$messages { factory Fragment$Section$$MessageSection$messages.fromJson( Map json, ) { + final l$title = json['title']; final l$content = json['content']; final l$variant = json['variant']; final l$style = json['style']; final l$$__typename = json['__typename']; return Fragment$Section$$MessageSection$messages( + title: (l$title as String), content: (l$content as String), variant: fromJson$Enum$MessageStyleVariant((l$variant as String)), style: Fragment$Section$$MessageSection$messages$style.fromJson( @@ -64180,6 +64190,8 @@ class Fragment$Section$$MessageSection$messages { ); } + final String title; + final String content; final Enum$MessageStyleVariant variant; @@ -64193,6 +64205,8 @@ class Fragment$Section$$MessageSection$messages { Map toJson() { final _resultData = {}; + final l$title = title; + _resultData['title'] = l$title; final l$content = content; _resultData['content'] = l$content; final l$variant = variant; @@ -64206,11 +64220,18 @@ class Fragment$Section$$MessageSection$messages { @override int get hashCode { + final l$title = title; final l$content = content; final l$variant = variant; final l$style = style; final l$$__typename = $__typename; - return Object.hashAll([l$content, l$variant, l$style, l$$__typename]); + return Object.hashAll([ + l$title, + l$content, + l$variant, + l$style, + l$$__typename, + ]); } @override @@ -64222,6 +64243,11 @@ class Fragment$Section$$MessageSection$messages { runtimeType != other.runtimeType) { return false; } + final l$title = title; + final lOther$title = other.title; + if (l$title != lOther$title) { + return false; + } final l$content = content; final lOther$content = other.content; if (l$content != lOther$content) { @@ -64265,6 +64291,7 @@ abstract class CopyWith$Fragment$Section$$MessageSection$messages { _CopyWithStubImpl$Fragment$Section$$MessageSection$messages; TRes call({ + String? title, String? content, Enum$MessageStyleVariant? variant, Fragment$Section$$MessageSection$messages$style? style, @@ -64287,12 +64314,16 @@ class _CopyWithImpl$Fragment$Section$$MessageSection$messages static const _undefined = {}; TRes call({ + Object? title = _undefined, Object? content = _undefined, Object? variant = _undefined, Object? style = _undefined, Object? $__typename = _undefined, }) => _then( Fragment$Section$$MessageSection$messages( + title: title == _undefined || title == null + ? _instance.title + : (title as String), content: content == _undefined || content == null ? _instance.content : (content as String), @@ -64324,6 +64355,7 @@ class _CopyWithStubImpl$Fragment$Section$$MessageSection$messages TRes _res; call({ + String? title, String? content, Enum$MessageStyleVariant? variant, Fragment$Section$$MessageSection$messages$style? style, diff --git a/bccm_core/lib/src/features/graphql/queries/sections.graphql.dart b/bccm_core/lib/src/features/graphql/queries/sections.graphql.dart index e65ae9a..1ef0cba 100644 --- a/bccm_core/lib/src/features/graphql/queries/sections.graphql.dart +++ b/bccm_core/lib/src/features/graphql/queries/sections.graphql.dart @@ -47091,6 +47091,7 @@ class _CopyWithStubImpl$Query$FetchMoreItemsForItemSection$section$$MessageSecti class Query$FetchMoreItemsForItemSection$section$$MessageSection$messages implements Fragment$Section$$MessageSection$messages { Query$FetchMoreItemsForItemSection$section$$MessageSection$messages({ + required this.title, required this.content, required this.variant, required this.style, @@ -47100,11 +47101,13 @@ class Query$FetchMoreItemsForItemSection$section$$MessageSection$messages factory Query$FetchMoreItemsForItemSection$section$$MessageSection$messages.fromJson( Map json, ) { + final l$title = json['title']; final l$content = json['content']; final l$variant = json['variant']; final l$style = json['style']; final l$$__typename = json['__typename']; return Query$FetchMoreItemsForItemSection$section$$MessageSection$messages( + title: (l$title as String), content: (l$content as String), variant: fromJson$Enum$MessageStyleVariant((l$variant as String)), style: @@ -47115,6 +47118,8 @@ class Query$FetchMoreItemsForItemSection$section$$MessageSection$messages ); } + final String title; + final String content; final Enum$MessageStyleVariant variant; @@ -47129,6 +47134,8 @@ class Query$FetchMoreItemsForItemSection$section$$MessageSection$messages Map toJson() { final _resultData = {}; + final l$title = title; + _resultData['title'] = l$title; final l$content = content; _resultData['content'] = l$content; final l$variant = variant; @@ -47142,11 +47149,18 @@ class Query$FetchMoreItemsForItemSection$section$$MessageSection$messages @override int get hashCode { + final l$title = title; final l$content = content; final l$variant = variant; final l$style = style; final l$$__typename = $__typename; - return Object.hashAll([l$content, l$variant, l$style, l$$__typename]); + return Object.hashAll([ + l$title, + l$content, + l$variant, + l$style, + l$$__typename, + ]); } @override @@ -47159,6 +47173,11 @@ class Query$FetchMoreItemsForItemSection$section$$MessageSection$messages runtimeType != other.runtimeType) { return false; } + final l$title = title; + final lOther$title = other.title; + if (l$title != lOther$title) { + return false; + } final l$content = content; final lOther$content = other.content; if (l$content != lOther$content) { @@ -47212,6 +47231,7 @@ abstract class CopyWith$Query$FetchMoreItemsForItemSection$section$$MessageSecti ) = _CopyWithStubImpl$Query$FetchMoreItemsForItemSection$section$$MessageSection$messages; TRes call({ + String? title, String? content, Enum$MessageStyleVariant? variant, Query$FetchMoreItemsForItemSection$section$$MessageSection$messages$style? @@ -47247,12 +47267,16 @@ class _CopyWithImpl$Query$FetchMoreItemsForItemSection$section$$MessageSection$m static const _undefined = {}; TRes call({ + Object? title = _undefined, Object? content = _undefined, Object? variant = _undefined, Object? style = _undefined, Object? $__typename = _undefined, }) => _then( Query$FetchMoreItemsForItemSection$section$$MessageSection$messages( + title: title == _undefined || title == null + ? _instance.title + : (title as String), content: content == _undefined || content == null ? _instance.content : (content as String), @@ -47295,6 +47319,7 @@ class _CopyWithStubImpl$Query$FetchMoreItemsForItemSection$section$$MessageSecti TRes _res; call({ + String? title, String? content, Enum$MessageStyleVariant? variant, Query$FetchMoreItemsForItemSection$section$$MessageSection$messages$style? @@ -93254,6 +93279,7 @@ class _CopyWithStubImpl$Query$GetSection$section$$MessageSection class Query$GetSection$section$$MessageSection$messages implements Fragment$Section$$MessageSection$messages { Query$GetSection$section$$MessageSection$messages({ + required this.title, required this.content, required this.variant, required this.style, @@ -93263,11 +93289,13 @@ class Query$GetSection$section$$MessageSection$messages factory Query$GetSection$section$$MessageSection$messages.fromJson( Map json, ) { + final l$title = json['title']; final l$content = json['content']; final l$variant = json['variant']; final l$style = json['style']; final l$$__typename = json['__typename']; return Query$GetSection$section$$MessageSection$messages( + title: (l$title as String), content: (l$content as String), variant: fromJson$Enum$MessageStyleVariant((l$variant as String)), style: Query$GetSection$section$$MessageSection$messages$style.fromJson( @@ -93277,6 +93305,8 @@ class Query$GetSection$section$$MessageSection$messages ); } + final String title; + final String content; final Enum$MessageStyleVariant variant; @@ -93290,6 +93320,8 @@ class Query$GetSection$section$$MessageSection$messages Map toJson() { final _resultData = {}; + final l$title = title; + _resultData['title'] = l$title; final l$content = content; _resultData['content'] = l$content; final l$variant = variant; @@ -93303,11 +93335,18 @@ class Query$GetSection$section$$MessageSection$messages @override int get hashCode { + final l$title = title; final l$content = content; final l$variant = variant; final l$style = style; final l$$__typename = $__typename; - return Object.hashAll([l$content, l$variant, l$style, l$$__typename]); + return Object.hashAll([ + l$title, + l$content, + l$variant, + l$style, + l$$__typename, + ]); } @override @@ -93319,6 +93358,11 @@ class Query$GetSection$section$$MessageSection$messages runtimeType != other.runtimeType) { return false; } + final l$title = title; + final lOther$title = other.title; + if (l$title != lOther$title) { + return false; + } final l$content = content; final lOther$content = other.content; if (l$content != lOther$content) { @@ -93367,6 +93411,7 @@ abstract class CopyWith$Query$GetSection$section$$MessageSection$messages< ) = _CopyWithStubImpl$Query$GetSection$section$$MessageSection$messages; TRes call({ + String? title, String? content, Enum$MessageStyleVariant? variant, Query$GetSection$section$$MessageSection$messages$style? style, @@ -93391,12 +93436,16 @@ class _CopyWithImpl$Query$GetSection$section$$MessageSection$messages static const _undefined = {}; TRes call({ + Object? title = _undefined, Object? content = _undefined, Object? variant = _undefined, Object? style = _undefined, Object? $__typename = _undefined, }) => _then( Query$GetSection$section$$MessageSection$messages( + title: title == _undefined || title == null + ? _instance.title + : (title as String), content: content == _undefined || content == null ? _instance.content : (content as String), @@ -93432,6 +93481,7 @@ class _CopyWithStubImpl$Query$GetSection$section$$MessageSection$messages TRes _res; call({ + String? title, String? content, Enum$MessageStyleVariant? variant, Query$GetSection$section$$MessageSection$messages$style? style,