From 3ad7907653cca73eabe2ddd0c07aa067e24e46d1 Mon Sep 17 00:00:00 2001 From: jeffrey Date: Mon, 18 Mar 2024 13:19:26 +0100 Subject: [PATCH 1/7] Update Notification center. --- .../notification-center/NotificationCenter.js | 86 +++++++++++++++++++ .../NotificationCenter.stories.js | 23 +++++ .../notification-center.stories.mdx | 24 +----- scss/bitstyles/utilities/bg/_settings.scss | 1 + .../utilities/border-radius/_settings.scss | 1 + 5 files changed, 114 insertions(+), 21 deletions(-) create mode 100644 scss/bitstyles/organisms/notification-center/NotificationCenter.js create mode 100644 scss/bitstyles/organisms/notification-center/NotificationCenter.stories.js diff --git a/scss/bitstyles/organisms/notification-center/NotificationCenter.js b/scss/bitstyles/organisms/notification-center/NotificationCenter.js new file mode 100644 index 000000000..095b4c0ca --- /dev/null +++ b/scss/bitstyles/organisms/notification-center/NotificationCenter.js @@ -0,0 +1,86 @@ +import icons from '../../../../assets/images/icons.svg'; + +export function NotificationWrapper(children) { + const contentWrapper = document.createElement('div'); + contentWrapper.style.position = 'relative'; + contentWrapper.style.zIndex = 0; + contentWrapper.style.transform = 'translate3d(0,0,0)'; + contentWrapper.style.minHeight = '15rem'; + + const notificationWrapper = document.createElement('div'); + notificationWrapper.classList.add( + 'o-notification-center', + 'a-content', + 'a-content--s', + 'u-margin-0' + ); + notificationWrapper.setAttribute('aria-live', 'polite'); + notificationWrapper.innerHTML = children; + + contentWrapper.appendChild(notificationWrapper); + + return contentWrapper; +} + +export default ({ title, subtitle }) => { + const article = document.createElement('article'); + const iconWrapperStart = document.createElement('div'); + const contentWrapper = document.createElement('div'); + const iconWrapperEnd = document.createElement('div'); + const heading = document.createElement('h2'); + const subtitleElement = document.createElement('p'); + + article.classList.add( + 'a-card', + 'u-padding-0', + 'u-border-radius-s2', + 'u-flex' + ); + + iconWrapperStart.classList.add( + 'u-flex-shrink-0', + 'u-flex', + 'u-items-center', + 'u-padding-s2', + 'u-bg-brand-2-light-4' + ); + iconWrapperStart.innerHTML = ` + + `; + + contentWrapper.classList.add('u-margin-l2'); + + heading.classList.add( + 'u-h4', + 'u-margin-0', + 'u-margin-s6-bottom', + 'u-white-space-nowrap' + ); + heading.textContent = title; + + subtitleElement.classList.add('u-margin-0', 'u-font-light'); + subtitleElement.textContent = subtitle; + + iconWrapperEnd.classList.add( + 'u-flex-shrink-0', + 'u-flex', + 'u-items-center', + 'u-padding-s2', + 'u-bg-grayscale-light-3' + ); + iconWrapperEnd.innerHTML = ` + + `; + + article.appendChild(iconWrapperStart); + contentWrapper.appendChild(heading); + contentWrapper.appendChild(subtitleElement); + article.appendChild(contentWrapper); + article.appendChild(iconWrapperEnd); + + return article; +}; diff --git a/scss/bitstyles/organisms/notification-center/NotificationCenter.stories.js b/scss/bitstyles/organisms/notification-center/NotificationCenter.stories.js new file mode 100644 index 000000000..439d0ccae --- /dev/null +++ b/scss/bitstyles/organisms/notification-center/NotificationCenter.stories.js @@ -0,0 +1,23 @@ +import NotificationCenter, { NotificationWrapper } from './NotificationCenter'; + +export default { + title: 'Organisms/Notification center', + component: NotificationCenter, + argTypes: {}, +}; + +const Template = (args) => NotificationCenter(args); + +export const Base = Template.bind({}); +const baseDecorator = (story) => { + return NotificationWrapper(story().outerHTML); +}; + +Base.args = { + title: 'Password update request confirmed', + subtitle: 'Thank you for updating your details.', +}; +Base.decorators = [baseDecorator]; +Base.parameters = { + zeplinLink: 'https://zpl.io/WQKegrn', +}; diff --git a/scss/bitstyles/organisms/notification-center/notification-center.stories.mdx b/scss/bitstyles/organisms/notification-center/notification-center.stories.mdx index 8926aa644..44054d088 100644 --- a/scss/bitstyles/organisms/notification-center/notification-center.stories.mdx +++ b/scss/bitstyles/organisms/notification-center/notification-center.stories.mdx @@ -1,7 +1,7 @@ import { Canvas, Meta, Story } from '@storybook/addon-docs'; -import icons from '../../../../assets/images/icons.svg'; +import NotificationCenter from './NotificationCenter'; - + # Notification center @@ -10,23 +10,5 @@ A collection of interactive elements that are closely-related can be visually bo Commonly, this layout is used for buttons. - - {` -
-
-
-
- -
-
-

Password update request sent

-

We sent an email to asdf@example.com. Please click the link inside to confirm your password change

-
-
-
-
- `} -
+
diff --git a/scss/bitstyles/utilities/bg/_settings.scss b/scss/bitstyles/utilities/bg/_settings.scss index 14a857802..7f1808577 100644 --- a/scss/bitstyles/utilities/bg/_settings.scss +++ b/scss/bitstyles/utilities/bg/_settings.scss @@ -2,6 +2,7 @@ $values: ( 'brand-2': var(design-token.get('color', 'brand-2')), + 'brand-2-light-4': var(design-token.get('color', 'brand-2', 'light-4')), 'black': var(design-token.get('color', 'grayscale', 'black')), 'grayscale-dark-2': var(design-token.get('color', 'grayscale', 'dark-2')), 'grayscale-dark-1': var(design-token.get('color', 'grayscale', 'dark-1')), diff --git a/scss/bitstyles/utilities/border-radius/_settings.scss b/scss/bitstyles/utilities/border-radius/_settings.scss index c78eeb061..4d0b2021e 100644 --- a/scss/bitstyles/utilities/border-radius/_settings.scss +++ b/scss/bitstyles/utilities/border-radius/_settings.scss @@ -3,6 +3,7 @@ $values: ( '0': 0, 's7': var(design-token.get('size', 's7')), + 's2': var(design-token.get('size', 's2')), ) !default; $breakpoints: () !default; $directions: ( From 8baef3f51b6502d83c6e6010b198dbda30f20676 Mon Sep 17 00:00:00 2001 From: jeffrey Date: Mon, 18 Mar 2024 14:16:56 +0100 Subject: [PATCH 2/7] Add dropdown story variant. --- .../NotificationCenter.stories.js | 24 +++++++++++++++++++ .../notification-center.stories.mdx | 5 ++++ .../bitstyles/utilities/border/_settings.scss | 2 ++ 3 files changed, 31 insertions(+) diff --git a/scss/bitstyles/organisms/notification-center/NotificationCenter.stories.js b/scss/bitstyles/organisms/notification-center/NotificationCenter.stories.js index 439d0ccae..2e475fd3e 100644 --- a/scss/bitstyles/organisms/notification-center/NotificationCenter.stories.js +++ b/scss/bitstyles/organisms/notification-center/NotificationCenter.stories.js @@ -1,3 +1,4 @@ +import Dropdown from '../../atoms/dropdown/Dropdown'; import NotificationCenter, { NotificationWrapper } from './NotificationCenter'; export default { @@ -21,3 +22,26 @@ Base.decorators = [baseDecorator]; Base.parameters = { zeplinLink: 'https://zpl.io/WQKegrn', }; + +export const InDropdown = Template.bind({}); +const dropdownDecorator = (story) => { + const decorator = document.createElement('div'); + decorator.style.height = '30rem'; + const children = ``; + decorator.appendChild(Dropdown({ alignment: ['right'], children })); + return decorator; +}; + +InDropdown.args = { + title: 'Password update request confirmed', + subtitle: 'Thank you for updating your details.', +}; +InDropdown.decorators = [dropdownDecorator]; +InDropdown.parameters = { + zeplinLink: 'https://zpl.io/Gn7L1d3', +}; diff --git a/scss/bitstyles/organisms/notification-center/notification-center.stories.mdx b/scss/bitstyles/organisms/notification-center/notification-center.stories.mdx index 44054d088..1b6bf358e 100644 --- a/scss/bitstyles/organisms/notification-center/notification-center.stories.mdx +++ b/scss/bitstyles/organisms/notification-center/notification-center.stories.mdx @@ -12,3 +12,8 @@ Commonly, this layout is used for buttons. + +### In dropdown + + + diff --git a/scss/bitstyles/utilities/border/_settings.scss b/scss/bitstyles/utilities/border/_settings.scss index d6d17111a..e1592dc1a 100644 --- a/scss/bitstyles/utilities/border/_settings.scss +++ b/scss/bitstyles/utilities/border/_settings.scss @@ -5,6 +5,8 @@ $values: ( var(design-token.get('color', 'grayscale', 'dark-1')), 'grayscale-light-1': 1px solid var(design-token.get('color', 'grayscale', 'light-1')), + 'brand-1-dark-2': 1px solid + var(design-token.get('color', 'brand-1', 'dark-2')), ) !default; $breakpoints: () !default; $directions: ( From b036892861f81a2660239691f0ccf5a80dad1330 Mon Sep 17 00:00:00 2001 From: jeffrey Date: Mon, 18 Mar 2024 14:40:01 +0100 Subject: [PATCH 3/7] Use button for second Icon wrapper. --- .../notification-center/NotificationCenter.js | 20 +++++++++++++------ .../utilities/overflow/_settings.scss | 1 + 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/scss/bitstyles/organisms/notification-center/NotificationCenter.js b/scss/bitstyles/organisms/notification-center/NotificationCenter.js index 095b4c0ca..cce2936e1 100644 --- a/scss/bitstyles/organisms/notification-center/NotificationCenter.js +++ b/scss/bitstyles/organisms/notification-center/NotificationCenter.js @@ -26,26 +26,30 @@ export default ({ title, subtitle }) => { const article = document.createElement('article'); const iconWrapperStart = document.createElement('div'); const contentWrapper = document.createElement('div'); - const iconWrapperEnd = document.createElement('div'); + const iconWrapperEnd = document.createElement('button'); const heading = document.createElement('h2'); const subtitleElement = document.createElement('p'); article.classList.add( 'a-card', - 'u-padding-0', 'u-border-radius-s2', - 'u-flex' + 'u-overflow-visible', + 'u-padding-0', + 'u-flex', + 'u-justify-between' ); iconWrapperStart.classList.add( 'u-flex-shrink-0', 'u-flex', + 'u-border-radius-s2-tl', + 'u-border-radius-s2-bl', 'u-items-center', 'u-padding-s2', 'u-bg-brand-2-light-4' ); iconWrapperStart.innerHTML = ` - Remove notification`, + classname: ['u-self-start'], + }); +}; -export default ({ title, subtitle }) => { - const article = document.createElement('article'); +const Notification = ({ title, subtitle, theme = 'default' }) => { + const notification = document.createElement('article'); const iconWrapperStart = document.createElement('div'); const contentWrapper = document.createElement('div'); - const iconWrapperEnd = document.createElement('button'); const heading = document.createElement('h2'); const subtitleElement = document.createElement('p'); - article.classList.add( - 'a-card', - 'u-border-radius-s2', - 'u-overflow-visible', - 'u-padding-0', - 'u-flex', - 'u-justify-between' - ); + notification.classList.add('m-notification'); + notification.setAttribute('data-theme', theme); - iconWrapperStart.classList.add( - 'u-flex-shrink-0', - 'u-flex', - 'u-border-radius-s2-tl', - 'u-border-radius-s2-bl', - 'u-items-center', - 'u-padding-s2', - 'u-bg-brand-2-light-4' - ); + iconWrapperStart.classList.add('m-notification__highlight'); iconWrapperStart.innerHTML = ` `; - contentWrapper.classList.add('u-margin-l2'); + contentWrapper.classList.add('m-notification__content'); - heading.classList.add( - 'u-h4', - 'u-margin-0', - 'u-margin-s6-bottom', - 'u-white-space-nowrap' - ); + heading.classList.add('u-h4', 'u-margin-s6-bottom'); heading.textContent = title; subtitleElement.classList.add('u-margin-0', 'u-font-light'); subtitleElement.textContent = subtitle; - iconWrapperEnd.classList.add( - 'u-flex', - 'a-button', - 'a-button--transparent', - 'u-border-radius-s2-tr', - 'u-border-radius-s2-br', - 'u-items-center', - 'u-padding-s2', - 'u-border-radius-0', - 'u-bg-grayscale-light-3' - ); - iconWrapperEnd.innerHTML = ` - - `; - - article.appendChild(iconWrapperStart); + notification.appendChild(iconWrapperStart); contentWrapper.appendChild(heading); contentWrapper.appendChild(subtitleElement); - article.appendChild(contentWrapper); - article.appendChild(iconWrapperEnd); + notification.appendChild(contentWrapper); + notification.appendChild(CloseButton()); + + return notification; +}; + +const NotificationCenter = ({ children = [], isGlobal = true }) => { + const notificationCenter = document.createElement('ul'); - return article; + if (isGlobal) { + notificationCenter.setAttribute('aria-live', 'polite'); + notificationCenter.classList.add( + 'o-notification-center', + 'a-content', + 'a-content--s' + ); + } + + children.forEach((child) => { + const listItem = document.createElement('li'); + listItem.classList.add('o-notification-center__item'); + listItem.appendChild(child); + notificationCenter.appendChild(listItem); + }); + + if (isGlobal) { + return notificationCenter; + } + + return Dropdown({ children: notificationCenter, alignment: ['right'] }); }; + +export { Notification, NotificationCenter }; diff --git a/scss/bitstyles/organisms/notification-center/NotificationCenter.stories.js b/scss/bitstyles/organisms/notification-center/NotificationCenter.stories.js index 2e475fd3e..12e410b9e 100644 --- a/scss/bitstyles/organisms/notification-center/NotificationCenter.stories.js +++ b/scss/bitstyles/organisms/notification-center/NotificationCenter.stories.js @@ -1,9 +1,9 @@ -import Dropdown from '../../atoms/dropdown/Dropdown'; -import NotificationCenter, { NotificationWrapper } from './NotificationCenter'; +import { Notification, NotificationCenter } from './NotificationCenter'; export default { title: 'Organisms/Notification center', component: NotificationCenter, + subcomponents: Notification, argTypes: {}, }; @@ -11,37 +11,58 @@ const Template = (args) => NotificationCenter(args); export const Base = Template.bind({}); const baseDecorator = (story) => { - return NotificationWrapper(story().outerHTML); + const decorator = document.createElement('div'); + decorator.style.height = '20rem'; + decorator.appendChild(story()); + return decorator; }; +const notifications = [ + Notification({ + title: 'Password update request sent', + subtitle: + 'We sent an email to asdf@example.com. Please click the link inside to confirm your password change', + theme: 'positive', + }), + Notification({ + title: 'Well Done!', + subtitle: 'You did something good', + theme: 'brand-1', + }), + Notification({ + title: 'Oops! That wasn’t good', + subtitle: 'Maybe that was a mistake?', + theme: 'danger', + }), +]; + Base.args = { - title: 'Password update request confirmed', - subtitle: 'Thank you for updating your details.', + children: notifications, }; Base.decorators = [baseDecorator]; Base.parameters = { zeplinLink: 'https://zpl.io/WQKegrn', }; -export const InDropdown = Template.bind({}); -const dropdownDecorator = (story) => { - const decorator = document.createElement('div'); - decorator.style.height = '30rem'; - const children = `
    -
  • ${story().outerHTML}
  • -
  • ${story().outerHTML}
  • -
  • ${story().outerHTML}
  • -
  • ${story().outerHTML}
  • -
`; - decorator.appendChild(Dropdown({ alignment: ['right'], children })); - return decorator; -}; +// export const InDropdown = Template.bind({}); +// const dropdownDecorator = (story) => { +// const decorator = document.createElement('div'); +// decorator.style.height = '30rem'; +// const children = `
    +//
  • ${story().outerHTML}
  • +//
  • ${story().outerHTML}
  • +//
  • ${story().outerHTML}
  • +//
  • ${story().outerHTML}
  • +//
`; +// decorator.appendChild(Dropdown({ alignment: ['right'], children })); +// return decorator; +// }; -InDropdown.args = { - title: 'Password update request confirmed', - subtitle: 'Thank you for updating your details.', -}; -InDropdown.decorators = [dropdownDecorator]; -InDropdown.parameters = { - zeplinLink: 'https://zpl.io/Gn7L1d3', -}; +// InDropdown.args = { +// title: 'Password update request confirmed', +// subtitle: 'Thank you for updating your details.', +// }; +// InDropdown.decorators = [dropdownDecorator]; +// InDropdown.parameters = { +// zeplinLink: 'https://zpl.io/Gn7L1d3', +// }; diff --git a/scss/bitstyles/organisms/notification-center/_index.scss b/scss/bitstyles/organisms/notification-center/_index.scss index 0f2223f82..b3663971f 100644 --- a/scss/bitstyles/organisms/notification-center/_index.scss +++ b/scss/bitstyles/organisms/notification-center/_index.scss @@ -1,12 +1,62 @@ +@forward "./settings"; +@use "./settings"; @use '../../tools/classname'; +@use '../../tools/design-token'; +@use '../../tools/themes'; +@use 'sass:map'; #{classname.get($classname-items: 'notification-center', $layer: 'organism')} { position: fixed; top: 0; right: 0; pointer-events: none; + margin: 0; + list-style: none; + padding: 0; + z-index: var(design-token.get("z-index", 'top')); + border-radius: var(design-token.get("size", "m")); + overflow-x: hidden; + overflow-y: auto; + max-height: 80vh; + box-shadow: var(design-token.get("shadow", "brand-1", "center", "box")); > * { pointer-events: auto; } } + +#{classname.get($classname-items: 'notification-center__item', $layer: 'organism')} { + border-bottom: 2px solid var(design-token.get("color", "brand-1", "light-2")); +} + +/* prettier-ignore */ +$highlight-color-property: design-token.get('notification', 'highlight-color'); +$highlight-background-color-property: design-token.get('notification', 'highlight-background-color'); + +#{classname.get($classname-items: 'notification', $layer: 'molecule')} { + display: flex; + background-color: var(design-token.get("color", "grayscale", "white")); + color: var(design-token.get("color", "grayscale", "dark-3")); +} + +#{classname.get($classname-items: 'notification__content', $layer: 'molecule')} { + flex: 1; + min-width: 0; + padding: var(design-token.get("size", "l2")) 0 var(design-token.get("size", "l2")) var(design-token.get("size", "l2")); +} + +#{classname.get($classname-items: 'notification__highlight', $layer: 'molecule')} { + flex-shrink: 0; + display: flex; + align-items: center; + padding: var(design-token.get("size", "s2")); + color: var($highlight-color-property, var(design-token.get("color", "brand-1", "dark-1"))); + background-color: var($highlight-background-color-property, var(design-token.get("color", "brand-1", "light-4"))); +} + +@each $theme-name, $theme in settings.$theme-variants { + @include themes.get($theme-name) { + #{$highlight-color-property}: map.get($theme, 'highlight-color'); + #{$highlight-background-color-property}: map.get($theme, 'highlight-background-color'); + } +} diff --git a/scss/bitstyles/organisms/notification-center/_settings.scss b/scss/bitstyles/organisms/notification-center/_settings.scss new file mode 100644 index 000000000..856228593 --- /dev/null +++ b/scss/bitstyles/organisms/notification-center/_settings.scss @@ -0,0 +1,28 @@ +@use '../../tools/design-token'; + +$theme-variants: ( + 'default': ( + 'highlight-background-color': var(design-token.get('color', 'grayscale', 'light-4')), + 'highlight-color': var(design-token.get('color', 'grayscale', 'dark-3')), + ), + 'brand-1': ( + 'highlight-background-color': var(design-token.get('color', 'brand-1', 'light-4')), + 'highlight-color': var(design-token.get('color', 'brand-1', 'dark-1')), + ), + 'brand-2': ( + 'highlight-background-color': var(design-token.get('color', 'brand-2', 'light-4')), + 'highlight-color': var(design-token.get('color', 'brand-2', 'dark-1')), + ), + 'positive': ( + 'highlight-background-color': var(design-token.get('color', 'positive', 'light-4')), + 'highlight-color': var(design-token.get('color', 'positive', 'dark-1')), + ), + 'warning': ( + 'highlight-background-color': var(design-token.get('color', 'warning', 'light-4')), + 'highlight-color': var(design-token.get('color', 'warning', 'dark-1')), + ), + 'danger': ( + 'highlight-background-color': var(design-token.get('color', 'danger', 'light-4')), + 'highlight-color': var(design-token.get('color', 'danger', 'dark-1')), + ), +) !default; diff --git a/scss/bitstyles/organisms/notification-center/notification-center.stories.mdx b/scss/bitstyles/organisms/notification-center/notification-center.stories.mdx index 907c9d778..04fd9f4e3 100644 --- a/scss/bitstyles/organisms/notification-center/notification-center.stories.mdx +++ b/scss/bitstyles/organisms/notification-center/notification-center.stories.mdx @@ -1,7 +1,7 @@ import { Canvas, Meta, Story } from '@storybook/addon-docs'; -import NotificationCenter from './NotificationCenter'; +import { Notification, NotificationCenter } from './NotificationCenter'; - + # Notification center diff --git a/scss/bitstyles/utilities/self/_settings.scss b/scss/bitstyles/utilities/self/_settings.scss index 766ea67c5..9cc5f30f6 100644 --- a/scss/bitstyles/utilities/self/_settings.scss +++ b/scss/bitstyles/utilities/self/_settings.scss @@ -1,4 +1,5 @@ $values: ( 'end': flex-end, + 'start': flex-start, ) !default; $breakpoints: ('m') !default; From 31c9c9ac5ed545362dd401a1683dcebafa158bcf Mon Sep 17 00:00:00 2001 From: Darren Cadwallader Date: Wed, 15 May 2024 16:55:55 +0200 Subject: [PATCH 6/7] - Moves Notification into its own component files in Molecules layer --- scss/bitstyles.scss | 1 + scss/bitstyles/molecules/_index.scss | 1 + .../molecules/notification/Notification.js | 46 +++++++++++++++++ .../notification/Notification.stories.js | 20 ++++++++ .../molecules/notification/_index.scss | 38 ++++++++++++++ .../molecules/notification/_settings.scss | 28 +++++++++++ .../notification/notification.stories.mdx | 14 ++++++ .../notification-center/NotificationCenter.js | 50 +------------------ .../NotificationCenter.stories.js | 4 +- .../organisms/notification-center/_index.scss | 49 +++++------------- .../notification-center/_settings.scss | 29 ++--------- 11 files changed, 166 insertions(+), 114 deletions(-) create mode 100644 scss/bitstyles/molecules/_index.scss create mode 100644 scss/bitstyles/molecules/notification/Notification.js create mode 100644 scss/bitstyles/molecules/notification/Notification.stories.js create mode 100644 scss/bitstyles/molecules/notification/_index.scss create mode 100644 scss/bitstyles/molecules/notification/_settings.scss create mode 100644 scss/bitstyles/molecules/notification/notification.stories.mdx diff --git a/scss/bitstyles.scss b/scss/bitstyles.scss index eacf48bcb..2fcc62fed 100644 --- a/scss/bitstyles.scss +++ b/scss/bitstyles.scss @@ -15,6 +15,7 @@ @forward 'bitstyles/generic/'; @forward 'bitstyles/base/'; @forward 'bitstyles/atoms/'; +@forward 'bitstyles/molecules/'; @forward 'bitstyles/organisms/'; // diff --git a/scss/bitstyles/molecules/_index.scss b/scss/bitstyles/molecules/_index.scss new file mode 100644 index 000000000..2b46b38a9 --- /dev/null +++ b/scss/bitstyles/molecules/_index.scss @@ -0,0 +1 @@ +@forward './notification' as notification-*; diff --git a/scss/bitstyles/molecules/notification/Notification.js b/scss/bitstyles/molecules/notification/Notification.js new file mode 100644 index 000000000..0e3e50c80 --- /dev/null +++ b/scss/bitstyles/molecules/notification/Notification.js @@ -0,0 +1,46 @@ +import icons from '../../../../assets/images/icons.svg'; +import Button from '../../atoms/button/Button'; + +const CloseButton = () => { + return Button({ + colorVariant: ['transparent'], + children: `Remove notification`, + classname: ['u-self-start'], + }); +}; + +export default ({ title, subtitle, theme = 'default' }) => { + const notification = document.createElement('article'); + const iconWrapperStart = document.createElement('div'); + const contentWrapper = document.createElement('div'); + const heading = document.createElement('h2'); + const subtitleElement = document.createElement('p'); + + notification.classList.add('m-notification'); + notification.setAttribute('data-theme', theme); + + iconWrapperStart.classList.add('m-notification__highlight'); + iconWrapperStart.innerHTML = ` + + `; + + contentWrapper.classList.add('m-notification__content'); + + heading.classList.add('u-h4', 'u-margin-s6-bottom'); + heading.textContent = title; + + subtitleElement.classList.add('u-margin-0', 'u-font-light'); + subtitleElement.textContent = subtitle; + + notification.appendChild(iconWrapperStart); + contentWrapper.appendChild(heading); + contentWrapper.appendChild(subtitleElement); + notification.appendChild(contentWrapper); + notification.appendChild(CloseButton()); + + return notification; +}; diff --git a/scss/bitstyles/molecules/notification/Notification.stories.js b/scss/bitstyles/molecules/notification/Notification.stories.js new file mode 100644 index 000000000..e255ffa5a --- /dev/null +++ b/scss/bitstyles/molecules/notification/Notification.stories.js @@ -0,0 +1,20 @@ +import Notification from './Notification'; + +export default { + title: 'Molecules/Notification', + component: Notification, + argTypes: {}, +}; + +const Template = (args) => Notification(args); + +export const Base = Template.bind({}); +Base.args = { + title: 'Password update request sent', + subtitle: + 'We sent an email to asdf@example.com. Please click the link inside to confirm your password change', + theme: 'positive', +}; +Base.parameters = { + zeplinLink: 'https://zpl.io/WQKegrn', +}; diff --git a/scss/bitstyles/molecules/notification/_index.scss b/scss/bitstyles/molecules/notification/_index.scss new file mode 100644 index 000000000..796a667a1 --- /dev/null +++ b/scss/bitstyles/molecules/notification/_index.scss @@ -0,0 +1,38 @@ +@forward "./settings"; +@use "./settings"; +@use '../../tools/classname'; +@use '../../tools/design-token'; +@use '../../tools/themes'; +@use 'sass:map'; + +/* prettier-ignore */ +$highlight-color-property: design-token.get('notification', 'highlight-color'); +$highlight-background-color-property: design-token.get('notification', 'highlight-background-color'); + +#{classname.get($classname-items: 'notification', $layer: 'molecule')} { + display: flex; + background-color: var(design-token.get("color", "grayscale", "white")); + color: var(design-token.get("color", "grayscale", "dark-3")); +} + +#{classname.get($classname-items: 'notification__content', $layer: 'molecule')} { + flex: 1; + min-width: 0; + padding: var(design-token.get("size", "l2")) 0 var(design-token.get("size", "l2")) var(design-token.get("size", "l2")); +} + +#{classname.get($classname-items: 'notification__highlight', $layer: 'molecule')} { + flex-shrink: 0; + display: flex; + align-items: center; + padding: var(design-token.get("size", "s2")); + color: var($highlight-color-property, var(design-token.get("color", "brand-1", "dark-1"))); + background-color: var($highlight-background-color-property, var(design-token.get("color", "brand-1", "light-4"))); +} + +@each $theme-name, $theme in settings.$theme-variants { + @include themes.get($theme-name) { + #{$highlight-color-property}: map.get($theme, 'highlight-color'); + #{$highlight-background-color-property}: map.get($theme, 'highlight-background-color'); + } +} diff --git a/scss/bitstyles/molecules/notification/_settings.scss b/scss/bitstyles/molecules/notification/_settings.scss new file mode 100644 index 000000000..856228593 --- /dev/null +++ b/scss/bitstyles/molecules/notification/_settings.scss @@ -0,0 +1,28 @@ +@use '../../tools/design-token'; + +$theme-variants: ( + 'default': ( + 'highlight-background-color': var(design-token.get('color', 'grayscale', 'light-4')), + 'highlight-color': var(design-token.get('color', 'grayscale', 'dark-3')), + ), + 'brand-1': ( + 'highlight-background-color': var(design-token.get('color', 'brand-1', 'light-4')), + 'highlight-color': var(design-token.get('color', 'brand-1', 'dark-1')), + ), + 'brand-2': ( + 'highlight-background-color': var(design-token.get('color', 'brand-2', 'light-4')), + 'highlight-color': var(design-token.get('color', 'brand-2', 'dark-1')), + ), + 'positive': ( + 'highlight-background-color': var(design-token.get('color', 'positive', 'light-4')), + 'highlight-color': var(design-token.get('color', 'positive', 'dark-1')), + ), + 'warning': ( + 'highlight-background-color': var(design-token.get('color', 'warning', 'light-4')), + 'highlight-color': var(design-token.get('color', 'warning', 'dark-1')), + ), + 'danger': ( + 'highlight-background-color': var(design-token.get('color', 'danger', 'light-4')), + 'highlight-color': var(design-token.get('color', 'danger', 'dark-1')), + ), +) !default; diff --git a/scss/bitstyles/molecules/notification/notification.stories.mdx b/scss/bitstyles/molecules/notification/notification.stories.mdx new file mode 100644 index 000000000..b3644c7d5 --- /dev/null +++ b/scss/bitstyles/molecules/notification/notification.stories.mdx @@ -0,0 +1,14 @@ +import { Canvas, Meta, Story } from '@storybook/addon-docs'; +import Notification from './Notification'; + + + +# Notification + +A collection of interactive elements that are closely-related can be visually bound together. + +Commonly, this layout is used for buttons. + + + + diff --git a/scss/bitstyles/organisms/notification-center/NotificationCenter.js b/scss/bitstyles/organisms/notification-center/NotificationCenter.js index 0b7ef44ea..d2cb0d92c 100644 --- a/scss/bitstyles/organisms/notification-center/NotificationCenter.js +++ b/scss/bitstyles/organisms/notification-center/NotificationCenter.js @@ -1,52 +1,6 @@ -import icons from '../../../../assets/images/icons.svg'; -import Button from '../../atoms/button/Button'; import Dropdown from '../../atoms/dropdown/Dropdown'; -const CloseButton = () => { - return Button({ - colorVariant: ['transparent'], - children: `Remove notification`, - classname: ['u-self-start'], - }); -}; - -const Notification = ({ title, subtitle, theme = 'default' }) => { - const notification = document.createElement('article'); - const iconWrapperStart = document.createElement('div'); - const contentWrapper = document.createElement('div'); - const heading = document.createElement('h2'); - const subtitleElement = document.createElement('p'); - - notification.classList.add('m-notification'); - notification.setAttribute('data-theme', theme); - - iconWrapperStart.classList.add('m-notification__highlight'); - iconWrapperStart.innerHTML = ` - - `; - - contentWrapper.classList.add('m-notification__content'); - - heading.classList.add('u-h4', 'u-margin-s6-bottom'); - heading.textContent = title; - - subtitleElement.classList.add('u-margin-0', 'u-font-light'); - subtitleElement.textContent = subtitle; - - notification.appendChild(iconWrapperStart); - contentWrapper.appendChild(heading); - contentWrapper.appendChild(subtitleElement); - notification.appendChild(contentWrapper); - notification.appendChild(CloseButton()); - - return notification; -}; - -const NotificationCenter = ({ children = [], isGlobal = true }) => { +export default ({ children = [], isGlobal = true }) => { const notificationCenter = document.createElement('ul'); if (isGlobal) { @@ -71,5 +25,3 @@ const NotificationCenter = ({ children = [], isGlobal = true }) => { return Dropdown({ children: notificationCenter, alignment: ['right'] }); }; - -export { Notification, NotificationCenter }; diff --git a/scss/bitstyles/organisms/notification-center/NotificationCenter.stories.js b/scss/bitstyles/organisms/notification-center/NotificationCenter.stories.js index 12e410b9e..6f3fb4cf7 100644 --- a/scss/bitstyles/organisms/notification-center/NotificationCenter.stories.js +++ b/scss/bitstyles/organisms/notification-center/NotificationCenter.stories.js @@ -1,9 +1,9 @@ -import { Notification, NotificationCenter } from './NotificationCenter'; +import Notification from '../../molecules/notification/Notification'; +import NotificationCenter from './NotificationCenter'; export default { title: 'Organisms/Notification center', component: NotificationCenter, - subcomponents: Notification, argTypes: {}, }; diff --git a/scss/bitstyles/organisms/notification-center/_index.scss b/scss/bitstyles/organisms/notification-center/_index.scss index b3663971f..540a262d0 100644 --- a/scss/bitstyles/organisms/notification-center/_index.scss +++ b/scss/bitstyles/organisms/notification-center/_index.scss @@ -2,10 +2,16 @@ @use "./settings"; @use '../../tools/classname'; @use '../../tools/design-token'; -@use '../../tools/themes'; -@use 'sass:map'; + +/* prettier-ignore */ +$border-radius-property: design-token.get('notification-center', 'border-radius'); +$shadow-property: design-token.get('notification-center', 'shadow'); +$border-bottom-property: design-token.get('notification-center-item', 'border-bottom'); #{classname.get($classname-items: 'notification-center', $layer: 'organism')} { + #{$border-radius-property}: settings.$border-radius; + #{$shadow-property}: settings.$shadow; + position: fixed; top: 0; right: 0; @@ -14,11 +20,11 @@ list-style: none; padding: 0; z-index: var(design-token.get("z-index", 'top')); - border-radius: var(design-token.get("size", "m")); + border-radius: var($border-radius-property); overflow-x: hidden; overflow-y: auto; max-height: 80vh; - box-shadow: var(design-token.get("shadow", "brand-1", "center", "box")); + box-shadow: var(#{$shadow-property}); > * { pointer-events: auto; @@ -26,37 +32,6 @@ } #{classname.get($classname-items: 'notification-center__item', $layer: 'organism')} { - border-bottom: 2px solid var(design-token.get("color", "brand-1", "light-2")); -} - -/* prettier-ignore */ -$highlight-color-property: design-token.get('notification', 'highlight-color'); -$highlight-background-color-property: design-token.get('notification', 'highlight-background-color'); - -#{classname.get($classname-items: 'notification', $layer: 'molecule')} { - display: flex; - background-color: var(design-token.get("color", "grayscale", "white")); - color: var(design-token.get("color", "grayscale", "dark-3")); -} - -#{classname.get($classname-items: 'notification__content', $layer: 'molecule')} { - flex: 1; - min-width: 0; - padding: var(design-token.get("size", "l2")) 0 var(design-token.get("size", "l2")) var(design-token.get("size", "l2")); -} - -#{classname.get($classname-items: 'notification__highlight', $layer: 'molecule')} { - flex-shrink: 0; - display: flex; - align-items: center; - padding: var(design-token.get("size", "s2")); - color: var($highlight-color-property, var(design-token.get("color", "brand-1", "dark-1"))); - background-color: var($highlight-background-color-property, var(design-token.get("color", "brand-1", "light-4"))); -} - -@each $theme-name, $theme in settings.$theme-variants { - @include themes.get($theme-name) { - #{$highlight-color-property}: map.get($theme, 'highlight-color'); - #{$highlight-background-color-property}: map.get($theme, 'highlight-background-color'); - } + #{$border-bottom-property}: settings.$item-border-bottom; + border-bottom: var(#{$border-bottom-property}); } diff --git a/scss/bitstyles/organisms/notification-center/_settings.scss b/scss/bitstyles/organisms/notification-center/_settings.scss index 856228593..add904a38 100644 --- a/scss/bitstyles/organisms/notification-center/_settings.scss +++ b/scss/bitstyles/organisms/notification-center/_settings.scss @@ -1,28 +1,5 @@ @use '../../tools/design-token'; -$theme-variants: ( - 'default': ( - 'highlight-background-color': var(design-token.get('color', 'grayscale', 'light-4')), - 'highlight-color': var(design-token.get('color', 'grayscale', 'dark-3')), - ), - 'brand-1': ( - 'highlight-background-color': var(design-token.get('color', 'brand-1', 'light-4')), - 'highlight-color': var(design-token.get('color', 'brand-1', 'dark-1')), - ), - 'brand-2': ( - 'highlight-background-color': var(design-token.get('color', 'brand-2', 'light-4')), - 'highlight-color': var(design-token.get('color', 'brand-2', 'dark-1')), - ), - 'positive': ( - 'highlight-background-color': var(design-token.get('color', 'positive', 'light-4')), - 'highlight-color': var(design-token.get('color', 'positive', 'dark-1')), - ), - 'warning': ( - 'highlight-background-color': var(design-token.get('color', 'warning', 'light-4')), - 'highlight-color': var(design-token.get('color', 'warning', 'dark-1')), - ), - 'danger': ( - 'highlight-background-color': var(design-token.get('color', 'danger', 'light-4')), - 'highlight-color': var(design-token.get('color', 'danger', 'dark-1')), - ), -) !default; +$border-radius: var(design-token.get("size", "m")) !default; +$shadow: var(design-token.get("shadow", "brand-1", "center", "box")) !default; +$item-border-bottom: 2px solid var(design-token.get("color", "brand-1", "light-2")) !default; From 8c457dd618bb3128118293c021bcb8dbfbb2775b Mon Sep 17 00:00:00 2001 From: Darren Cadwallader Date: Wed, 15 May 2024 17:32:31 +0200 Subject: [PATCH 7/7] - Fixes the font-weight issue (was due to non-existent CSS variables being referenced) - Buttons in notifications have no border-radius --- scss/bitstyles/design-tokens/_typography.scss | 13 +++--- .../molecules/notification/Notification.js | 4 +- .../molecules/notification/_index.scss | 45 ++++++++++++++++--- 3 files changed, 49 insertions(+), 13 deletions(-) diff --git a/scss/bitstyles/design-tokens/_typography.scss b/scss/bitstyles/design-tokens/_typography.scss index 5ef441058..c3f47f104 100644 --- a/scss/bitstyles/design-tokens/_typography.scss +++ b/scss/bitstyles/design-tokens/_typography.scss @@ -1,5 +1,6 @@ @use '../tools/custom-property'; @use 'sass:list'; +@use 'sass:map'; // // Font-weights ///////////////////////////////////////// @@ -26,37 +27,37 @@ $webfont-variants: ( 'normal': ( 'font-family': $webfont-family-name, 'font-style': normal, - 'font-weight': var(custom-property.name('font-weight', 'normal')), + 'font-weight': map.get($font-weights, 'normal'), 'filename': 'poppins-v20-latin-400', ), 'italic': ( 'font-family': $webfont-family-name, 'font-style': italic, - 'font-weight': var(custom-property.name('font-weight', 'normal')), + 'font-weight': map.get($font-weights, 'normal'), 'filename': 'poppins-v20-latin-400italic', ), 'medium': ( 'font-family': $webfont-family-name, 'font-style': normal, - 'font-weight': var(custom-property.name('font-weight', 'medium')), + 'font-weight': map.get($font-weights, 'medium'), 'filename': 'poppins-v20-latin-500', ), 'medium-italic': ( 'font-family': $webfont-family-name, 'font-style': italic, - 'font-weight': var(custom-property.name('font-weight', 'medium')), + 'font-weight': map.get($font-weights, 'medium'), 'filename': 'poppins-v20-latin-500italic', ), 'semibold': ( 'font-family': $webfont-family-name, 'font-style': normal, - 'font-weight': var(custom-property.name('font-weight', 'semibold')), + 'font-weight': map.get($font-weights, 'semibold'), 'filename': 'poppins-v20-latin-600', ), 'semibold-italic': ( 'font-family': $webfont-family-name, 'font-style': italic, - 'font-weight': var(custom-property.name('font-weight', 'semibold')), + 'font-weight': map.get($font-weights, 'semibold'), 'filename': 'poppins-v20-latin-600italic', ), ) !default; diff --git a/scss/bitstyles/molecules/notification/Notification.js b/scss/bitstyles/molecules/notification/Notification.js index 0e3e50c80..38daab263 100644 --- a/scss/bitstyles/molecules/notification/Notification.js +++ b/scss/bitstyles/molecules/notification/Notification.js @@ -3,11 +3,11 @@ import Button from '../../atoms/button/Button'; const CloseButton = () => { return Button({ - colorVariant: ['transparent'], + colorVariant: ['secondary'], children: `Remove notification`, - classname: ['u-self-start'], + classname: ['m-notification__button'], }); }; diff --git a/scss/bitstyles/molecules/notification/_index.scss b/scss/bitstyles/molecules/notification/_index.scss index 796a667a1..768bfd0df 100644 --- a/scss/bitstyles/molecules/notification/_index.scss +++ b/scss/bitstyles/molecules/notification/_index.scss @@ -8,6 +8,34 @@ /* prettier-ignore */ $highlight-color-property: design-token.get('notification', 'highlight-color'); $highlight-background-color-property: design-token.get('notification', 'highlight-background-color'); +$button-border-top-right-radius-property: design-token.get( + 'button', + 'border', + 'top', + 'right', + 'radius' +); +$button-border-bottom-right-radius-property: design-token.get( + 'button', + 'border', + 'bottom', + 'right', + 'radius' +); +$button-border-bottom-left-radius-property: design-token.get( + 'button', + 'border', + 'bottom', + 'left', + 'radius' +); +$button-border-top-left-radius-property: design-token.get( + 'button', + 'border', + 'top', + 'left', + 'radius' +); #{classname.get($classname-items: 'notification', $layer: 'molecule')} { display: flex; @@ -15,21 +43,28 @@ $highlight-background-color-property: design-token.get('notification', 'highligh color: var(design-token.get("color", "grayscale", "dark-3")); } -#{classname.get($classname-items: 'notification__content', $layer: 'molecule')} { - flex: 1; - min-width: 0; - padding: var(design-token.get("size", "l2")) 0 var(design-token.get("size", "l2")) var(design-token.get("size", "l2")); +#{classname.get($classname-items: 'notification__button', $layer: 'molecule')} { + #{$button-border-top-right-radius-property}: 0; + #{$button-border-bottom-right-radius-property}: 0; + #{$button-border-bottom-left-radius-property}: 0; + #{$button-border-top-left-radius-property}: 0; } #{classname.get($classname-items: 'notification__highlight', $layer: 'molecule')} { flex-shrink: 0; display: flex; align-items: center; - padding: var(design-token.get("size", "s2")); + padding: 0 var(design-token.get("size", "s1")); color: var($highlight-color-property, var(design-token.get("color", "brand-1", "dark-1"))); background-color: var($highlight-background-color-property, var(design-token.get("color", "brand-1", "light-4"))); } +#{classname.get($classname-items: 'notification__content', $layer: 'molecule')} { + flex: 1; + min-width: 0; + padding: var(design-token.get("size", "l2")) 0 var(design-token.get("size", "l2")) var(design-token.get("size", "l2")); +} + @each $theme-name, $theme in settings.$theme-variants { @include themes.get($theme-name) { #{$highlight-color-property}: map.get($theme, 'highlight-color');