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/atoms/dropdown/Dropdown.js b/scss/bitstyles/atoms/dropdown/Dropdown.js index 5be985a5c..aa0a8bd97 100644 --- a/scss/bitstyles/atoms/dropdown/Dropdown.js +++ b/scss/bitstyles/atoms/dropdown/Dropdown.js @@ -11,7 +11,7 @@ export default ({ alignment = [], children }) => { }); wrapper.appendChild(button); const dropdown = document.createElement('div'); - dropdown.innerHTML = children || 'Dropdown'; + dropdown.appendChild(children); dropdown.classList.add('a-dropdown', 'u-overflow-y-auto'); alignment.forEach((variant) => { dropdown.classList.add(`a-dropdown--${variant}`); 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/_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..38daab263 --- /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: ['secondary'], + children: `Remove notification`, + classname: ['m-notification__button'], + }); +}; + +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..768bfd0df --- /dev/null +++ b/scss/bitstyles/molecules/notification/_index.scss @@ -0,0 +1,73 @@ +@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'); +$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; + background-color: var(design-token.get("color", "grayscale", "white")); + color: var(design-token.get("color", "grayscale", "dark-3")); +} + +#{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: 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'); + #{$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 new file mode 100644 index 000000000..d2cb0d92c --- /dev/null +++ b/scss/bitstyles/organisms/notification-center/NotificationCenter.js @@ -0,0 +1,27 @@ +import Dropdown from '../../atoms/dropdown/Dropdown'; + +export default ({ children = [], isGlobal = true }) => { + const notificationCenter = document.createElement('ul'); + + 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'] }); +}; 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..6f3fb4cf7 --- /dev/null +++ b/scss/bitstyles/organisms/notification-center/NotificationCenter.stories.js @@ -0,0 +1,68 @@ +import Notification from '../../molecules/notification/Notification'; +import NotificationCenter from './NotificationCenter'; + +export default { + title: 'Organisms/Notification center', + component: NotificationCenter, + argTypes: {}, +}; + +const Template = (args) => NotificationCenter(args); + +export const Base = Template.bind({}); +const baseDecorator = (story) => { + 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 = { + 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 = ``; +// 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/_index.scss b/scss/bitstyles/organisms/notification-center/_index.scss index 0f2223f82..540a262d0 100644 --- a/scss/bitstyles/organisms/notification-center/_index.scss +++ b/scss/bitstyles/organisms/notification-center/_index.scss @@ -1,12 +1,37 @@ +@forward "./settings"; +@use "./settings"; @use '../../tools/classname'; +@use '../../tools/design-token'; + +/* 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; pointer-events: none; + margin: 0; + list-style: none; + padding: 0; + z-index: var(design-token.get("z-index", 'top')); + border-radius: var($border-radius-property); + overflow-x: hidden; + overflow-y: auto; + max-height: 80vh; + box-shadow: var(#{$shadow-property}); > * { pointer-events: auto; } } + +#{classname.get($classname-items: 'notification-center__item', $layer: 'organism')} { + #{$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 new file mode 100644 index 000000000..add904a38 --- /dev/null +++ b/scss/bitstyles/organisms/notification-center/_settings.scss @@ -0,0 +1,5 @@ +@use '../../tools/design-token'; + +$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; diff --git a/scss/bitstyles/organisms/notification-center/notification-center.stories.mdx b/scss/bitstyles/organisms/notification-center/notification-center.stories.mdx index 8926aa644..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 icons from '../../../../assets/images/icons.svg'; +import { Notification, NotificationCenter } from './NotificationCenter'; - + # Notification center @@ -10,23 +10,11 @@ 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

-
-
-
-
- `} -
+ +
+ +### In dropdown + + + 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: ( 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: ( diff --git a/scss/bitstyles/utilities/overflow/_settings.scss b/scss/bitstyles/utilities/overflow/_settings.scss index d455f707f..985ed5404 100644 --- a/scss/bitstyles/utilities/overflow/_settings.scss +++ b/scss/bitstyles/utilities/overflow/_settings.scss @@ -3,6 +3,7 @@ $values: ( 'hidden': hidden, 'scroll': scroll, 'auto': auto, + 'visible': visible, ), 'overflow-x': ( 'auto': auto, 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;