diff --git a/packages/charts/package.json b/packages/charts/package.json index 08a4746fa9d..35ff8146574 100644 --- a/packages/charts/package.json +++ b/packages/charts/package.json @@ -1,6 +1,6 @@ { "name": "@buildcanada/charts", - "version": "0.2.2", + "version": "0.3.0", "description": "A configurable data visualization library for creating interactive charts.", "type": "module", "main": "src/index.ts", @@ -54,6 +54,8 @@ "react-dom": "^19.0.0" }, "dependencies": { + "@buildcanada/colours": "workspace:*", + "@buildcanada/components": "workspace:*", "@fortawesome/fontawesome-svg-core": "^6.7.2", "@fortawesome/free-brands-svg-icons": "^6.7.2", "@fortawesome/free-solid-svg-icons": "^6.7.2", diff --git a/packages/charts/src/components/Button/Button.scss b/packages/charts/src/components/Button/Button.scss index 1e618584c24..64734796900 100644 --- a/packages/charts/src/components/Button/Button.scss +++ b/packages/charts/src/components/Button/Button.scss @@ -1,90 +1,188 @@ +/******************************************************************************* + * Charts Button Component + * + * Uses Build Canada design system styling with square corners and brand colors. + ******************************************************************************/ + .charts-btn { @include body-3-medium; - padding: 8.5px 24px; - border: 1px solid transparent; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + padding: 10px 24px; + border: 2px solid transparent; border-radius: 0; text-align: center; - display: block; cursor: pointer; + transition: all 150ms ease; + white-space: nowrap; + text-transform: uppercase; + letter-spacing: 0.05em; + font-weight: 500; + + &:focus-visible { + outline: 2px solid $auburn; + outline-offset: 2px; + } &.charts-btn--icon-only { - padding: 4.5px 9px; + padding: 8px; + min-width: 40px; + min-height: 40px; } - &:disabled { - cursor: default; - - &.charts-btn--solid-blue, - &.charts-btn--solid-dark-blue, - &.charts-btn--solid-light-blue, - &.charts-btn--solid-vermillion { - color: $blue-50; - background-color: $blue-10; - } - - &.charts-btn--outline-vermillion, - &.charts-btn--outline-white { - color: $blue-40; - border-color: $blue-40; - } + svg { + font-size: 0.875em; + transition: transform 150ms ease; } - svg { - font-size: 0.75rem; + // Animated arrow on hover + &:hover:not(:disabled) svg.icon-right { + transform: translateX(4px); } } +/******************************************************************************* + * Icon Position Modifiers + ******************************************************************************/ + .charts-btn--icon-right { - margin-left: 0.5rem; + margin-left: 8px; } .charts-btn--icon-left { - margin-right: 0.5rem; + margin-right: 8px; } +/******************************************************************************* + * Solid Variants + ******************************************************************************/ + +.charts-btn--solid-auburn, .charts-btn--solid-vermillion { - background-color: $vermillion; - color: #fff; + background-color: $auburn; + border-color: $auburn; + color: $white; + + &:hover:not(:disabled) { + background-color: $auburn-600; + border-color: $auburn-600; + } - &:hover { - background-color: $accent-vermillion; + &:active:not(:disabled) { + background-color: $auburn-700; + border-color: $auburn-700; } } -.charts-btn--outline-vermillion { - border-color: $vermillion; - color: $vermillion; +.charts-btn--solid-charcoal { + background-color: $charcoal; + border-color: $charcoal; + color: $white; - &:hover { - border-color: $accent-vermillion; - color: $accent-vermillion; + &:hover:not(:disabled) { + background-color: $gray-70; + border-color: $gray-70; + } + + &:active:not(:disabled) { + background-color: $gray-60; + border-color: $gray-60; } } +.charts-btn--solid-cerulean, .charts-btn--solid-blue { - background-color: $blue-60; - color: #fff; + background-color: $cerulean-500; + border-color: $cerulean-500; + color: $white; - &:hover { - background-color: $blue-90; + &:hover:not(:disabled) { + background-color: $cerulean-600; + border-color: $cerulean-600; + } + + &:active:not(:disabled) { + background-color: $cerulean-700; + border-color: $cerulean-700; } } .charts-btn--solid-dark-blue { - background-color: $blue-95; - color: #fff; + background-color: $cerulean-900; + border-color: $cerulean-900; + color: $white; - &:hover { - background-color: #164377; + &:hover:not(:disabled) { + background-color: $cerulean-950; + border-color: $cerulean-950; } } .charts-btn--solid-light-blue { - background-color: $blue-20; - color: $blue-90; + background-color: $cerulean-100; + border-color: $cerulean-100; + color: $cerulean-900; + + &:hover:not(:disabled) { + background-color: $cerulean-200; + border-color: $cerulean-200; + } +} + +.charts-btn--solid-linen { + background-color: $linen; + border-color: $linen; + color: $charcoal; + + &:hover:not(:disabled) { + background-color: $gray-20; + border-color: $gray-20; + } - &:hover { - background-color: $blue-10; + &:active:not(:disabled) { + background-color: $gray-30; + border-color: $gray-30; + } +} + +/******************************************************************************* + * Outline Variants + ******************************************************************************/ + +.charts-btn--outline-auburn, +.charts-btn--outline-vermillion { + background-color: transparent; + border-color: $auburn; + color: $auburn; + + &:hover:not(:disabled) { + background-color: $auburn; + color: $white; + } + + &:active:not(:disabled) { + background-color: $auburn-600; + border-color: $auburn-600; + color: $white; + } +} + +.charts-btn--outline-charcoal { + background-color: transparent; + border-color: $charcoal; + color: $charcoal; + + &:hover:not(:disabled) { + background-color: $charcoal; + color: $white; + } + + &:active:not(:disabled) { + background-color: $gray-70; + border-color: $gray-70; + color: $white; } } @@ -93,18 +191,41 @@ border-color: $white; color: $white; - &:hover { + &:hover:not(:disabled) { background-color: $white; - color: $blue-90; + color: $charcoal; + } + + &:active:not(:disabled) { + background-color: $gray-10; + border-color: $gray-10; + color: $charcoal; } } +.charts-btn--outline-cerulean, .charts-btn--outline-light-blue { - border-color: $blue-20; - color: $blue-90; + background-color: transparent; + border-color: $cerulean-500; + color: $cerulean-700; - &:hover { - background-color: $white; - color: $blue-90; + &:hover:not(:disabled) { + background-color: $cerulean-500; + color: $white; + } + + &:active:not(:disabled) { + background-color: $cerulean-600; + border-color: $cerulean-600; + color: $white; } } + +/******************************************************************************* + * Disabled State + ******************************************************************************/ + +.charts-btn:disabled { + opacity: 0.5; + cursor: not-allowed; +} diff --git a/packages/charts/src/components/Checkbox.scss b/packages/charts/src/components/Checkbox.scss index 85b105cfd87..949185be6a1 100644 --- a/packages/charts/src/components/Checkbox.scss +++ b/packages/charts/src/components/Checkbox.scss @@ -1,14 +1,23 @@ +/******************************************************************************* + * Checkbox + * + * Custom checkbox styling. + * Uses Build Canada design system colors. + ******************************************************************************/ + .checkbox { - $checkbox-size: 16px; + $checkbox-size: 18px; $light-stroke: $gray-30; - $hover-stroke: $blue-30; - $active-fill: $blue-30; + $hover-stroke: $auburn-500; + $active-fill: $auburn-500; position: relative; + display: flex; + align-items: flex-start; label { - margin: 0; // style leak in admin + margin: 0; } input { @@ -27,28 +36,29 @@ width: $checkbox-size; height: $checkbox-size; - background: white; + background: $white; pointer-events: none; - border-radius: 2px; - border: 1px solid $light-stroke; - color: #fff; + border-radius: 0; + border: 2px solid $light-stroke; + color: $white; display: flex; align-items: center; justify-content: center; + transition: all 150ms ease; svg { font-size: 10px; - padding-left: 0.75px; } } input:focus-visible + .custom { - outline: 2px solid $controls-color; + outline: 2px solid $auburn; + outline-offset: 2px; } input:active + .custom { - background: $active-fill; + background: $auburn-100; } input:checked + .custom { @@ -57,36 +67,38 @@ } input:checked:active + .custom { - background: white; + background: $auburn-600; + border-color: $auburn-600; } input:disabled { + .custom { - background: $blue-10; - border-color: $blue-20; - color: $blue-50; + background: $gray-10; + border-color: $gray-20; + color: $gray-50; } &:active + .custom { - background: $blue-10; + background: $gray-10; } ~ .label { - color: $blue-50; + color: $gray-50; cursor: not-allowed; } } .label { @include grapher_label-2-regular; - padding-left: $checkbox-size + 8px; + padding-left: $checkbox-size + 10px; cursor: pointer; user-select: none; - color: $dark-text; + color: $charcoal; + line-height: $checkbox-size; } &:hover { - input:not(:checked) + .custom { + input:not(:checked):not(:disabled) + .custom { border-color: $hover-stroke; } } diff --git a/packages/charts/src/components/LabeledSwitch/LabeledSwitch.scss b/packages/charts/src/components/LabeledSwitch/LabeledSwitch.scss index d0778b65832..9963cf45adc 100644 --- a/packages/charts/src/components/LabeledSwitch/LabeledSwitch.scss +++ b/packages/charts/src/components/LabeledSwitch/LabeledSwitch.scss @@ -1,20 +1,26 @@ +/******************************************************************************* + * Labeled Switch + * + * Toggle switch with label. + * Uses Build Canada design system colors. + ******************************************************************************/ + @use "sass:color"; $light-fill: $gray-30; -$active-fill: $blue-20; - -$active-switch: $blue-50; - +$active-fill: $cerulean-100; +$active-switch: $cerulean-500; $medium: 400; $lato: $sans-serif-font-stack; -// on/off switch with label written to the right +// On/off switch with label written to the right .labeled-switch { - // keep in sync with TableFilterToggle.tsx + // Keep in sync with TableFilterToggle.tsx // where the width of a labeled switch is calculated display: flex; - color: $gray-70; + align-items: center; + color: $gray-60; font: $medium 13px/16px $lato; letter-spacing: 0.01em; @@ -24,23 +30,20 @@ $lato: $sans-serif-font-stack; user-select: none; label { - color: $gray-80; - padding-left: 35px; + color: $charcoal; + padding-left: 40px; white-space: nowrap; - - &:hover { - cursor: pointer; - } + cursor: pointer; svg { - color: $gray-60; + color: $gray-50; height: 13px; padding: 0 0.333em; } } .labeled-switch-subtitle { - // only show subtitle in settings menu, otherwise use icon + tooltip + // Only show subtitle in settings menu, otherwise use icon + tooltip display: none; } @@ -48,61 +51,71 @@ $lato: $sans-serif-font-stack; position: absolute; opacity: 0; left: 0; + cursor: pointer; } .outer { position: absolute; left: 0; - top: 0; + top: 50%; + transform: translateY(-50%); content: " "; - width: 29px; - height: 16px; + width: 32px; + height: 18px; background: $light-fill; - border-radius: 8px; + border-radius: 9px; pointer-events: none; + transition: background 200ms ease; + .inner { position: relative; content: " "; - width: 10px; - height: 10px; - background: $gray-70; - border-radius: 5px; + width: 12px; + height: 12px; + background: $gray-60; + border-radius: 50%; top: 3px; left: 3px; pointer-events: none; - transition: transform 333ms; + transition: transform 200ms ease, background 200ms ease; } } &:hover { .outer .inner { - background: $gray-80; + background: $charcoal; } } input:focus-visible + .outer { - outline: 2px solid $controls-color; + outline: 2px solid $auburn; + outline-offset: 2px; } input:checked + .outer { background: $active-fill; + .inner { background: $active-switch; - transform: translate(13px, 0); + transform: translate(14px, 0); } } + &:hover input:checked + .outer .inner { - background: color.adjust($active-switch, $lightness: -13%); + background: $cerulean-600; } &.labeled-switch--is-disabled { opacity: 0.5; + cursor: not-allowed; + label { - cursor: default; + cursor: not-allowed; } + &:hover { .inner { - background: $gray-70; + background: $gray-60; } } } diff --git a/packages/charts/src/components/RadioButton.scss b/packages/charts/src/components/RadioButton.scss index 68c7a3c9e43..61bf1a5235a 100644 --- a/packages/charts/src/components/RadioButton.scss +++ b/packages/charts/src/components/RadioButton.scss @@ -1,16 +1,25 @@ +/******************************************************************************* + * Radio Button + * + * Custom radio button styling. + * Uses Build Canada design system colors. + ******************************************************************************/ + @use "sass:math"; .radio { - $radio-size: 16px; + $radio-size: 18px; $light-stroke: $gray-30; - $hover-stroke: $blue-30; - $active-fill: $blue-50; + $hover-stroke: $cerulean-500; + $active-fill: $cerulean-500; position: relative; + display: flex; + align-items: flex-start; label { - margin: 0; // style leak in admin + margin: 0; cursor: pointer; } @@ -28,37 +37,48 @@ width: $radio-size; height: $radio-size; - background: white; + background: $white; pointer-events: none; border-radius: 50%; - border: 1px solid $light-stroke; + border: 2px solid $light-stroke; display: flex; align-items: center; justify-content: center; + transition: all 150ms ease; .inner { width: math.div($radio-size, 2); height: math.div($radio-size, 2); background-color: $active-fill; border-radius: 50%; + opacity: 0; + transform: scale(0); + transition: all 150ms ease; } } input:focus-visible + .outer { - outline: 2px solid $controls-color; + outline: 2px solid $auburn; + outline-offset: 2px; } input:checked + .outer { border-color: $hover-stroke; + + .inner { + opacity: 1; + transform: scale(1); + } } .label { @include grapher_label-2-regular; - padding-left: $radio-size + 8px; + padding-left: $radio-size + 10px; cursor: pointer; user-select: none; - color: $dark-text; + color: $charcoal; + line-height: $radio-size; } &:hover { diff --git a/packages/charts/src/components/closeButton/CloseButton.scss b/packages/charts/src/components/closeButton/CloseButton.scss index 5473c30f8be..34eb47811ef 100644 --- a/packages/charts/src/components/closeButton/CloseButton.scss +++ b/packages/charts/src/components/closeButton/CloseButton.scss @@ -1,10 +1,16 @@ +/******************************************************************************* + * Close Button + * + * Circular close/dismiss button. + * Uses Build Canada design system colors. + ******************************************************************************/ + .close-button { - // keep in sync with CLOSE_BUTTON_SIZE in CloseButton.tsx + // Keep in sync with CLOSE_BUTTON_SIZE in CloseButton.tsx $size: 32px; $light-stroke: $gray-20; - - $active-fill: #dbe5f0; + $active-fill: $cerulean-100; $hover-fill: $gray-10; display: flex; @@ -14,23 +20,30 @@ position: relative; height: $size; width: $size; - padding: 7px; + padding: 0; - color: $light-text; - background: white; + color: $gray-60; + background: $white; border: 1px solid $light-stroke; - border-radius: 50%; + border-radius: 0; + cursor: pointer; + transition: all 150ms ease; &:hover { background: $hover-fill; - border-color: $hover-fill; - cursor: pointer; - color: $dark-text; + border-color: $gray-30; + color: $charcoal; } &:active { background: $active-fill; - border: 1px solid $active-fill; + border-color: $cerulean-500; + color: $cerulean-900; + } + + &:focus-visible { + outline: 2px solid $auburn; + outline-offset: 2px; } svg { diff --git a/packages/charts/src/components/styles/colors.scss b/packages/charts/src/components/styles/colors.scss index 55449294c81..4f51a9121d4 100644 --- a/packages/charts/src/components/styles/colors.scss +++ b/packages/charts/src/components/styles/colors.scss @@ -1,89 +1,208 @@ /******************************************************************************* - * Colors - */ + * Colors - Build Canada Design System + * + * This file imports and extends the Build Canada color tokens for use in charts. + ******************************************************************************/ @use "sass:color"; -// Brand colors -$oxford-blue: #002147; -$vermillion: #ce261e; -$amber: #f7c020; - -// Blue shades -$blue-100: #002147; -$blue-95: #112e4f; -$blue-90: #1d3d63; -$blue-60: #577291; -$blue-65: #46688f; -$blue-50: #6e87a2; -$blue-40: #98a9bd; -$blue-30: #a4b6ca; -$blue-20: #dbe5f0; -$blue-10: #ebeef2; -$blue-5: #f0f4fa; - -// Gray shades -$gray-100: #2d2e2d; -$gray-90: #4e4e4e; -$gray-80: #5b5b5b; -$gray-70: #767676; -$gray-60: #a1a1a1; -$gray-50: #c6c6c6; -$gray-30: #dadada; -$gray-20: #e7e7e7; -$gray-10: #f2f2f2; +/******************************************************************************* + * Import Build Canada Design Tokens + ******************************************************************************/ + +@use "@buildcanada/components/src/styles/tokens" as bc; + +/******************************************************************************* + * Brand Colors (from Build Canada design system) + ******************************************************************************/ + +$linen: bc.$linen; +$charcoal: bc.$charcoal; +$auburn: bc.$auburn; +$white: bc.$white; + +/******************************************************************************* + * Primary Color Scale - Auburn (Red) + ******************************************************************************/ + +$auburn-50: bc.$auburn-50; +$auburn-100: bc.$auburn-100; +$auburn-200: bc.$auburn-200; +$auburn-300: bc.$auburn-300; +$auburn-400: bc.$auburn-400; +$auburn-500: bc.$auburn-500; +$auburn-600: bc.$auburn-600; +$auburn-700: bc.$auburn-700; +$auburn-800: bc.$auburn-800; +$auburn-900: bc.$auburn-900; +$auburn-950: bc.$auburn-950; + +/******************************************************************************* + * Secondary Color Scale - Cerulean (Blue) + ******************************************************************************/ + +$cerulean-50: bc.$cerulean-50; +$cerulean-100: bc.$cerulean-100; +$cerulean-200: bc.$cerulean-200; +$cerulean-300: bc.$cerulean-300; +$cerulean-400: bc.$cerulean-400; +$cerulean-500: bc.$cerulean-500; +$cerulean-600: bc.$cerulean-600; +$cerulean-700: bc.$cerulean-700; +$cerulean-800: bc.$cerulean-800; +$cerulean-900: bc.$cerulean-900; +$cerulean-950: bc.$cerulean-950; + +/******************************************************************************* + * Tertiary Color Scale - Sienna (Orange) + ******************************************************************************/ + +$sienna-50: bc.$sienna-50; +$sienna-100: bc.$sienna-100; +$sienna-200: bc.$sienna-200; +$sienna-300: bc.$sienna-300; +$sienna-400: bc.$sienna-400; +$sienna-500: bc.$sienna-500; +$sienna-600: bc.$sienna-600; +$sienna-700: bc.$sienna-700; +$sienna-800: bc.$sienna-800; +$sienna-900: bc.$sienna-900; +$sienna-950: bc.$sienna-950; + +/******************************************************************************* + * Supporting Color Scale - Fantasia (Purple) + ******************************************************************************/ + +$fantasia-50: bc.$fantasia-50; +$fantasia-100: bc.$fantasia-100; +$fantasia-200: bc.$fantasia-200; +$fantasia-300: bc.$fantasia-300; +$fantasia-400: bc.$fantasia-400; +$fantasia-500: bc.$fantasia-500; +$fantasia-600: bc.$fantasia-600; +$fantasia-700: bc.$fantasia-700; +$fantasia-800: bc.$fantasia-800; +$fantasia-900: bc.$fantasia-900; +$fantasia-950: bc.$fantasia-950; + +/******************************************************************************* + * Supporting Color Scale - Emerald (Green) + ******************************************************************************/ + +$emerald-50: bc.$emerald-50; +$emerald-100: bc.$emerald-100; +$emerald-200: bc.$emerald-200; +$emerald-300: bc.$emerald-300; +$emerald-400: bc.$emerald-400; +$emerald-500: bc.$emerald-500; +$emerald-600: bc.$emerald-600; +$emerald-700: bc.$emerald-700; +$emerald-800: bc.$emerald-800; +$emerald-900: bc.$emerald-900; +$emerald-950: bc.$emerald-950; + +/******************************************************************************* + * Gray Scale + ******************************************************************************/ + $gray-5: #f7f7f7; +$gray-10: bc.$gray-100; +$gray-20: bc.$gray-200; +$gray-30: bc.$gray-300; +$gray-50: bc.$gray-400; +$gray-60: bc.$gray-500; +$gray-70: bc.$gray-600; +$gray-80: bc.$gray-700; +$gray-90: bc.$gray-800; +$gray-100: bc.$gray-900; -// Amber shades -$amber-110: #f9cf44; -$amber-10: #f4eddb; - -$beige: #fbf9f3; -$white: #ffffff; - -// Accent colors -$accent-electric-blue: #2162e6; -$accent-pale-blue: #e7f2ff; -$accent-vermillion: #b40000; - -// Visited -$purple-90: #631d49; -$purple-60: #91577c; -$visited-light: #b398a9; - -/* Text colors */ -$tertiary-text-color: $amber; -$grey-text-color: #616161; -$text-color: $blue-90; -$secondary-text-color: $blue-60; -$bluish-grey-text-color: $blue-50; -$error-text-color: $vermillion; - -/* Category colors */ -$population-color: #2082a2; -$health-color: #bf1b1b; -$food-color: #588a0f; -$energy-color: #ca6f34; -$environment-color: #0c6947; -$technology-color: #2774c6; -$growth-inequality-color: #009655; -$work-life-color: #ab348a; -$public-sector-color: #eb6400; -$global-connections-color: #17393d; -$war-peace-color: #660000; -$politics-color: #1b0655; -$violence-rights-color: #cc235c; -$education-color: #253f77; -$media-color: #0089be; -$culture-color: #af488f; - -/* Controls color */ -$controls-color: #0073e6; +/******************************************************************************* + * Legacy Brand Colors (backwards compatibility) + * Maps old OWID colors to Build Canada equivalents + ******************************************************************************/ + +$oxford-blue: $charcoal; +$vermillion: $auburn; +$amber: $sienna-400; + +// Legacy blue shades mapped to cerulean +$blue-100: $cerulean-950; +$blue-95: $cerulean-900; +$blue-90: $cerulean-800; +$blue-65: $cerulean-700; +$blue-60: $cerulean-600; +$blue-50: $cerulean-500; +$blue-40: $cerulean-400; +$blue-30: $cerulean-300; +$blue-20: $cerulean-200; +$blue-10: $cerulean-100; +$blue-5: $cerulean-50; + +// Legacy amber shades mapped to sienna +$amber-110: $sienna-300; +$amber-10: $sienna-50; + +$beige: $linen; + +/******************************************************************************* + * Accent Colors + ******************************************************************************/ + +$accent-electric-blue: $cerulean-500; +$accent-pale-blue: $cerulean-50; +$accent-vermillion: $auburn-700; + +// Visited link colors mapped to fantasia (purple) +$purple-90: $fantasia-800; +$purple-60: $fantasia-600; +$visited-light: $fantasia-300; + +/******************************************************************************* + * Text Colors + ******************************************************************************/ + +$text-color: $charcoal; +$secondary-text-color: bc.$gray-600; +$tertiary-text-color: $sienna-500; +$grey-text-color: bc.$gray-500; +$bluish-grey-text-color: $cerulean-600; +$error-text-color: $auburn; + +/******************************************************************************* + * Category Colors (for data visualization) + * Using Build Canada palette + ******************************************************************************/ + +$population-color: $cerulean-500; +$health-color: $auburn-500; +$food-color: $emerald-600; +$energy-color: $sienna-500; +$environment-color: $emerald-800; +$technology-color: $cerulean-600; +$growth-inequality-color: $emerald-500; +$work-life-color: $fantasia-500; +$public-sector-color: $sienna-400; +$global-connections-color: $cerulean-900; +$war-peace-color: $auburn-900; +$politics-color: $fantasia-900; +$violence-rights-color: $auburn-400; +$education-color: $cerulean-800; +$media-color: $cerulean-400; +$culture-color: $fantasia-600; + +/******************************************************************************* + * Controls & UI Colors + ******************************************************************************/ + +$controls-color: $cerulean-500; $light-shadow: - rgba(0, 0, 0, 0.1) 0px 0px 0px 1px, - rgba(0, 0, 0, 0.08) 0px 2px 2px; + rgba(39, 39, 39, 0.1) 0px 0px 0px 1px, + rgba(39, 39, 39, 0.08) 0px 2px 2px; + +/******************************************************************************* + * SDG Colors (UN Sustainable Development Goals) + ******************************************************************************/ -/* SDG colors */ $sdgColors: ( 1: color.scale(#e5243b, $lightness: -15%), 2: #dda63a, @@ -104,9 +223,20 @@ $sdgColors: ( 17: color.scale(#19486a, $lightness: -15%), ); +/******************************************************************************* + * CSS Custom Properties Export + ******************************************************************************/ + :root { - // See also gdocTypes/Gdoc.ts > GdocPostContent > cover-color + // Brand colors + --bc-linen: #{$linen}; + --bc-charcoal: #{$charcoal}; + --bc-auburn: #{$auburn}; + + // Legacy variables for backwards compatibility --amber: #{$amber}; + + // SDG colors @each $i, $sdgColor in $sdgColors { --sdg-color-#{$i}: #{$sdgColor}; } diff --git a/packages/charts/src/components/styles/typography.scss b/packages/charts/src/components/styles/typography.scss index c9b37cb71bb..b3d542cf139 100644 --- a/packages/charts/src/components/styles/typography.scss +++ b/packages/charts/src/components/styles/typography.scss @@ -1,9 +1,15 @@ -$sans-serif-font-stack: - Lato, "Helvetica Neue", Helvetica, Arial, "Liberation Sans", sans-serif; -$serif-font-stack: - "Playfair Display", Georgia, "Times New Roman", "Liberation Serif", serif; -$monospace-font-stack: - "Menlo", "Courier New", Courier, monospace; // only to be used for code blocks +// Build Canada brand fonts +// Headlines: Söhne Kraftig - modern neo-grotesque +// Body: Financier Text - serif for readability +// Mono: Founder's Grotesk Mono - for data/code +$font-headline: "Soehne Kraftig", "Helvetica Neue", Helvetica, Arial, sans-serif; +$font-body: "Financier Text", Georgia, "Times New Roman", serif; +$font-mono: "Founders Grotesk Mono", "Menlo", "Courier New", monospace; + +// Legacy aliases for backwards compatibility +$sans-serif-font-stack: $font-headline; +$serif-font-stack: $font-body; +$monospace-font-stack: $font-mono; $default-font-features: "liga", "kern", "calt", "lnum"; // diff --git a/packages/charts/src/grapher/color/ColorConstants.ts b/packages/charts/src/grapher/color/ColorConstants.ts index e5b457782e0..dafc0c1b6d7 100644 --- a/packages/charts/src/grapher/color/ColorConstants.ts +++ b/packages/charts/src/grapher/color/ColorConstants.ts @@ -1,20 +1,34 @@ -// gray shades -export const GRAY_100 = "#2d2e2d" -export const GRAY_90 = "#4e4e4e" -export const GRAY_80 = "#5b5b5b" -export const GRAY_70 = "#767676" -export const GRAY_60 = "#a1a1a1" -export const GRAY_50 = "#c6c6c6" -export const GRAY_30 = "#dadada" -export const GRAY_20 = "#e7e7e7" -export const GRAY_10 = "#f2f2f2" -export const GRAY_5 = "#f7f7f7" +/******************************************************************************* + * Color Constants + * + * Uses Build Canada design system colors. + ******************************************************************************/ -export const GRAPHER_BACKGROUND_DEFAULT = "#ffffff" -export const GRAPHER_BACKGROUND_BEIGE = "#fbf9f3" +// Build Canada brand colors +export const LINEN = "#F6ECE3" +export const CHARCOAL = "#272727" +export const AUBURN = "#932F2F" -export const GRAPHER_DARK_TEXT = GRAY_80 -export const GRAPHER_LIGHT_TEXT = GRAY_70 +// Gray shades +export const GRAY_100 = "#171717" +export const GRAY_90 = "#272727" +export const GRAY_80 = "#404040" +export const GRAY_70 = "#525252" +export const GRAY_60 = "#737373" +export const GRAY_50 = "#a3a3a3" +export const GRAY_30 = "#d4d4d4" +export const GRAY_20 = "#e5e5e5" +export const GRAY_10 = "#f5f5f5" +export const GRAY_5 = "#fafafa" +// Grapher backgrounds - using Build Canada linen +export const GRAPHER_BACKGROUND_DEFAULT = LINEN +export const GRAPHER_BACKGROUND_BEIGE = LINEN + +// Text colors +export const GRAPHER_DARK_TEXT = CHARCOAL +export const GRAPHER_LIGHT_TEXT = GRAY_60 + +// Other export const NO_DATA_GRAY = "#6e7581" export const ERROR_COLOR = "ff0002" diff --git a/packages/charts/src/grapher/controls/ActionButtons.scss b/packages/charts/src/grapher/controls/ActionButtons.scss index 4806684fbdf..a5eecf329ae 100644 --- a/packages/charts/src/grapher/controls/ActionButtons.scss +++ b/packages/charts/src/grapher/controls/ActionButtons.scss @@ -1,57 +1,63 @@ -// keep in sync with constant values in ActionButtons.tsx -$actionButtonHeight: 32px; // keep in sync with BUTTON_HEIGHT -$paddingBetweenActionButtons: 8px; // keep in sync with PADDING_BETWEEN_BUTTONS -$paddingBetweenIconAndLabel: 8px; // keep in sync with PADDING_BETWEEN_ICON_AND_LABEL -$paddingX: 12px; // keep in sync with PADDING_X +/******************************************************************************* + * Action Buttons + * + * Row of action buttons in the grapher (download, share, etc.) + * Uses Build Canada design system colors. + ******************************************************************************/ + +// Keep in sync with constant values in ActionButtons.tsx +$actionButtonHeight: 32px; +$paddingBetweenActionButtons: 8px; +$paddingBetweenIconAndLabel: 8px; +$paddingX: 12px; .ActionButtons { margin: 0; padding: 0; - white-space: nowrap; + height: $actionButtonHeight; ul { display: flex; list-style: none; - height: $actionButtonHeight; + height: 100%; padding: 0; + margin: 0; + gap: $paddingBetweenActionButtons; } li { height: 100%; - display: inline-block; + display: flex; position: relative; } - - li + li { - margin-left: $paddingBetweenActionButtons; - } } div.ActionButton { - --light-fill: #{$gray-10}; - --hover-fill: #{$gray-20}; - --active-fill: #{$blue-20}; - --text-color: #{$dark-text}; + --light-fill: #{$white}; + --hover-fill: #{$gray-10}; + --active-fill: #{$cerulean-100}; + --text-color: #{$charcoal}; + --border-color: #{$gray-20}; &.ActionButton--exploreData { - --light-fill: #{$blue-20}; - --hover-fill: #{$blue-20}; - --active-fill: #{$blue-10}; - --text-color: #{$blue-90}; - + --light-fill: #{$cerulean-100}; + --hover-fill: #{$cerulean-200}; + --active-fill: #{$cerulean-100}; + --text-color: #{$cerulean-900}; --hover-decoration: underline; } &.ActionButton--donate { - --light-fill: #{rgba($vermillion, 0.15)}; - --hover-fill: #{rgba(#f4a39f, 0.15)}; - --active-fill: var(--hover-fill); - --text-color: #{$vermillion}; + --light-fill: #{$auburn-100}; + --hover-fill: #{$auburn-200}; + --active-fill: #{$auburn-100}; + --text-color: #{$auburn}; } height: 100%; - border-radius: 4px; + border-radius: 0; position: relative; + transition: all 150ms ease; button, a { @@ -59,24 +65,32 @@ div.ActionButton { align-items: center; gap: $paddingBetweenIconAndLabel; height: 100%; - width: 100%; + box-sizing: border-box; cursor: pointer; color: var(--text-color); + font-family: $sans-serif-font-stack; font-size: 13px; font-weight: 500; + line-height: 1; padding: 0 $paddingX; border-radius: inherit; background-color: var(--light-fill); - position: relative; letter-spacing: 0.01em; + text-transform: uppercase; + transition: all 150ms ease; + border: none; + outline: none; + text-decoration: none; + white-space: nowrap; svg { font-size: 12px; + transition: transform 150ms ease; } &.icon-only { justify-content: center; - padding: 0; + padding: 0 8px; } &:visited { @@ -85,13 +99,18 @@ div.ActionButton { &:hover { background-color: var(--hover-fill); - text-decoration: var(--hover-decoration); + text-decoration: var(--hover-decoration, none); } &:active, &.active { - color: $active-text; + color: $cerulean-900; background-color: var(--active-fill); } + + &:focus-visible { + outline: 2px solid $auburn; + outline-offset: 2px; + } } } diff --git a/packages/charts/src/grapher/controls/ActionButtons.tsx b/packages/charts/src/grapher/controls/ActionButtons.tsx index 676f59db37f..68ce267cccb 100644 --- a/packages/charts/src/grapher/controls/ActionButtons.tsx +++ b/packages/charts/src/grapher/controls/ActionButtons.tsx @@ -17,12 +17,9 @@ import { shareUsingShareApi, shouldShareUsingShareApi, } from "./ShareMenu.js" -import { Bounds, Tippy } from "../../utils/index.js" +import { Tippy } from "../../utils/index.js" import classNames from "classnames" -import { - DEFAULT_GRAPHER_BOUNDS, - GrapherModal, -} from "../core/GrapherConstants.js" +import { GrapherModal } from "../core/GrapherConstants.js" import { DownloadModalTabName } from "../modal/DownloadModal.js" export interface ActionButtonsManager extends ShareMenuManager { @@ -41,15 +38,9 @@ export interface ActionButtonsManager extends ShareMenuManager { // keep in sync with sass variables in ActionButtons.scss const BUTTON_HEIGHT = 32 -const PADDING_BETWEEN_BUTTONS = 8 -const PADDING_BETWEEN_ICON_AND_LABEL = 8 -const PADDING_X = 12 - -const BUTTON_WIDTH_ICON_ONLY = BUTTON_HEIGHT interface ActionButtonsProps { manager: ActionButtonsManager - maxWidth?: number } @observer @@ -63,165 +54,15 @@ export class ActionButtons extends React.Component { return this.props.manager } - @computed protected get maxWidth(): number { - return this.props.maxWidth ?? DEFAULT_GRAPHER_BOUNDS.width - } - @computed get height(): number { return BUTTON_HEIGHT } - @computed private get widthWithButtonLabels(): number { - const { - buttonCount, - hasDownloadButton, - hasDonateButton, - hasShareButton, - hasFullScreenButton, - hasExploreTheDataButton, - downloadButtonWithLabelWidth, - donateButtonWithLabelWidth, - shareButtonWithLabelWidth, - fullScreenButtonWithLabelWidth, - exploreTheDataButtonWithLabelWidth, - } = this - - let width = 0 - if (hasDownloadButton) { - width += downloadButtonWithLabelWidth - } - if (hasShareButton) { - width += shareButtonWithLabelWidth - } - if (hasFullScreenButton) { - width += fullScreenButtonWithLabelWidth - } - if (hasDonateButton) { - width += donateButtonWithLabelWidth - } - if (hasExploreTheDataButton) { - width += exploreTheDataButtonWithLabelWidth - } - - return width + (buttonCount - 1) * PADDING_BETWEEN_BUTTONS - } - - @computed get widthWithIconsOnly(): number { - const { - buttonCount, - hasExploreTheDataButton, - exploreTheDataButtonWidth, - } = this - - let width = 0 - let remainingButtonCount = buttonCount - - // When shown, the explore the data button always has a label - if (hasExploreTheDataButton) { - width += exploreTheDataButtonWidth - remainingButtonCount-- - } - width += remainingButtonCount * BUTTON_WIDTH_ICON_ONLY - width += (buttonCount - 1) * PADDING_BETWEEN_BUTTONS - - return width - } - - @computed get showButtonLabels(): boolean { - const { maxWidth, widthWithButtonLabels } = this - return widthWithButtonLabels <= maxWidth - } - - @computed get width(): number { - const { showButtonLabels, widthWithButtonLabels, widthWithIconsOnly } = - this - return showButtonLabels ? widthWithButtonLabels : widthWithIconsOnly - } - - private static computeButtonWidth(label: string): number { - const labelWidth = Bounds.forText(label, { fontSize: 13 }).width - return ( - 2 * PADDING_X + - 12 + // icon width - PADDING_BETWEEN_ICON_AND_LABEL + - labelWidth - ) - } - - @computed private get downloadButtonWithLabelWidth(): number { - return ActionButtons.computeButtonWidth("Download") - } - - @computed private get shareButtonWithLabelWidth(): number { - return ActionButtons.computeButtonWidth("Share") - } - @computed private get fullScreenButtonLabel(): string { const { isInFullScreenMode } = this.manager return isInFullScreenMode ? "Exit full-screen" : "Enter full-screen" } - @computed private get fullScreenButtonWithLabelWidth(): number { - return ActionButtons.computeButtonWidth(this.fullScreenButtonLabel) - } - - @computed private get donateButtonWithLabelWidth(): number { - return ActionButtons.computeButtonWidth("Donate") - } - - @computed private get exploreTheDataButtonWithLabelWidth(): number { - return ActionButtons.computeButtonWidth("Explore the data") - } - - @computed private get downloadButtonWidth(): number { - const { - hasDownloadButton, - showButtonLabels, - downloadButtonWithLabelWidth, - } = this - if (!hasDownloadButton) return 0 - if (!showButtonLabels) return BUTTON_WIDTH_ICON_ONLY - return downloadButtonWithLabelWidth - } - - @computed private get shareButtonWidth(): number { - const { hasShareButton, showButtonLabels, shareButtonWithLabelWidth } = - this - if (!hasShareButton) return 0 - if (!showButtonLabels) return BUTTON_WIDTH_ICON_ONLY - return shareButtonWithLabelWidth - } - - @computed private get fullScreenButtonWidth(): number { - const { - hasFullScreenButton, - showButtonLabels, - fullScreenButtonWithLabelWidth, - } = this - if (!hasFullScreenButton) return 0 - if (!showButtonLabels) return BUTTON_WIDTH_ICON_ONLY - return fullScreenButtonWithLabelWidth - } - - @computed private get donateButtonWidth(): number { - const { - hasDonateButton, - showButtonLabels, - donateButtonWithLabelWidth, - } = this - if (!hasDonateButton) return 0 - if (!showButtonLabels) return BUTTON_WIDTH_ICON_ONLY - return donateButtonWithLabelWidth - } - - // the "Explore the data" button is never shown without a label - @computed private get exploreTheDataButtonWidth(): number { - const { hasExploreTheDataButton, exploreTheDataButtonWithLabelWidth } = - this - if (!hasExploreTheDataButton) return 0 - return exploreTheDataButtonWithLabelWidth - } - @action.bound toggleShareMenu(): void { if (shouldShareUsingShareApi(this.manager)) { void shareUsingShareApi(this.manager) @@ -268,29 +109,12 @@ export class ActionButtons extends React.Component { return !manager.hideExploreTheDataButton || !!manager.isInIFrame } - @computed private get buttonCount(): number { - let count = 0 - if (this.hasDownloadButton) count += 1 - if (this.hasShareButton) count += 1 - if (this.hasFullScreenButton) count += 1 - if (this.hasDonateButton) count += 1 - if (this.hasExploreTheDataButton) count += 1 - return count - } - private renderShareMenu(): React.ReactElement { - // distance between the right edge of the share button and the inner border of the frame - let right = 0 - if (this.hasFullScreenButton) - right += PADDING_BETWEEN_BUTTONS + this.fullScreenButtonWidth - if (this.hasExploreTheDataButton) - right += PADDING_BETWEEN_BUTTONS + this.exploreTheDataButtonWidth - return ( ) } @@ -300,17 +124,14 @@ export class ActionButtons extends React.Component { const { isShareMenuActive } = manager return ( -
+
    {this.hasDownloadButton && ( -
  • +
  • { this.openDownloadModal() @@ -320,11 +141,11 @@ export class ActionButtons extends React.Component {
  • )} {this.hasShareButton && ( -
  • +
  • { this.toggleShareMenu() @@ -336,11 +157,11 @@ export class ActionButtons extends React.Component {
  • )} {this.hasFullScreenButton && ( -
  • +
  • {
  • )} {this.hasDonateButton && ( -
  • +
  • )} {this.hasExploreTheDataButton && ( -
  • +
  • - maxWidth - actionButtons.width + maxWidth - ESTIMATED_ACTION_BUTTONS_WIDTH ) return undefined @@ -230,47 +229,35 @@ abstract class AbstractFooter< return !this.manager.hideNote && !!this.noteText } - @computed private get actionButtonsWidthWithIconsOnly(): number { - return new ActionButtons({ - manager: this.manager, - maxWidth: this.maxWidth, - }).widthWithIconsOnly - } - @computed private get useFullWidthSources(): boolean { - const { - showNote, - sourcesFontSize, - maxWidth, - sourcesText, - actionButtonsWidthWithIconsOnly, - } = this + const { showNote, sourcesFontSize, maxWidth, sourcesText } = this if (showNote) return true const sourcesWidth = Bounds.forText(sourcesText, { fontSize: sourcesFontSize, }).width - return sourcesWidth > 2 * (maxWidth - actionButtonsWidthWithIconsOnly) + return ( + sourcesWidth > 2 * (maxWidth - ESTIMATED_ACTION_BUTTONS_WIDTH) + ) } @computed private get useFullWidthNote(): boolean { - const { - fontSize, - maxWidth, - noteText, - actionButtonsWidthWithIconsOnly, - } = this + const { fontSize, maxWidth, noteText } = this const noteWidth = Bounds.forText(noteText, { fontSize }).width - return noteWidth > 2 * (maxWidth - actionButtonsWidthWithIconsOnly) + return noteWidth > 2 * (maxWidth - ESTIMATED_ACTION_BUTTONS_WIDTH) } @computed protected get sourcesMaxWidth(): number { if (this.useFullWidthSources) return this.maxWidth - return this.maxWidth - this.actionButtons.width - HORIZONTAL_PADDING + return ( + this.maxWidth - ESTIMATED_ACTION_BUTTONS_WIDTH - HORIZONTAL_PADDING + ) } @computed protected get noteMaxWidth(): number { if (this.useFullWidthNote) return this.maxWidth - return this.maxWidth - this.actionButtons.width - HORIZONTAL_PADDING + return ( + this.maxWidth - ESTIMATED_ACTION_BUTTONS_WIDTH - HORIZONTAL_PADDING + ) } @computed protected get licenseAndOriginUrlMaxWidth(): number { @@ -326,60 +313,6 @@ abstract class AbstractFooter< }) } - @computed private get actionButtonsMaxWidth(): number { - const { - correctedUrlText, - licenseText, - maxWidth, - fontSize, - sourcesFontSize, - useFullWidthSources, - sourcesText, - noteText, - showNote, - useFullWidthNote, - } = this - - const sourcesWidth = Bounds.forText(sourcesText, { - fontSize: sourcesFontSize, - }).width - const noteWidth = Bounds.forText(noteText, { fontSize }).width - - // text next to the action buttons - const leftTextWidth = !useFullWidthSources - ? sourcesWidth - : showNote && !useFullWidthNote - ? noteWidth - : 0 - // text above the action buttons - // (taken into account to ensure the action buttons are not too close to clickable text) - const topTextWidth = useFullWidthSources - ? useFullWidthNote - ? noteWidth - : sourcesWidth - : 0 - const licenseAndOriginUrlWidth = Bounds.forText( - AbstractFooter.constructLicenseAndOriginUrlText( - correctedUrlText, - licenseText - ), - { fontSize } - ).width - - return ( - maxWidth - - Math.max(topTextWidth, leftTextWidth, licenseAndOriginUrlWidth) - - HORIZONTAL_PADDING - ) - } - - @computed private get actionButtons(): ActionButtons { - return new ActionButtons({ - manager: this.manager, - maxWidth: this.actionButtonsMaxWidth, - }) - } - @computed get height(): number { return this.topContentHeight + this.bottomContentHeight } @@ -555,7 +488,7 @@ abstract class AbstractFooter< } @computed private get bottomContentHeight(): number { - const { actionButtons, sources, note } = this + const { sources, note } = this const renderSources = !this.useFullWidthSources const renderNote = this.showNote && !this.useFullWidthNote @@ -567,7 +500,7 @@ abstract class AbstractFooter< (renderPadding ? this.verticalPadding : 0) + (renderLicense ? this.licenseAndOriginUrl.height : 0) - return Math.max(textHeight, actionButtons.height) + return Math.max(textHeight, ACTION_BUTTONS_HEIGHT) } // renders the action buttons and the content next to it @@ -600,10 +533,7 @@ abstract class AbstractFooter< {renderPadding && this.renderVerticalSpace()} {renderLicense && this.renderLicense()}
- +
) } diff --git a/packages/charts/src/grapher/modal/Modal.scss b/packages/charts/src/grapher/modal/Modal.scss index 9646a835925..8a0c8a480d3 100644 --- a/packages/charts/src/grapher/modal/Modal.scss +++ b/packages/charts/src/grapher/modal/Modal.scss @@ -18,8 +18,9 @@ .modal-content { position: absolute; - border-radius: 4px; + border-radius: 0; background: #fff; + border: 1px solid $gray-20; box-shadow: 0px 4px 30px 0px rgba(0, 0, 0, 0.15); min-height: 150px; } diff --git a/packages/charts/src/grapher/noDataModal/NoDataModal.tsx b/packages/charts/src/grapher/noDataModal/NoDataModal.tsx index 475e06fc670..bcf4b580838 100644 --- a/packages/charts/src/grapher/noDataModal/NoDataModal.tsx +++ b/packages/charts/src/grapher/noDataModal/NoDataModal.tsx @@ -69,14 +69,12 @@ export class NoDataModal extends React.Component { const helpText = this.props.helpText ?? defaultHelpText const center = bounds.centerPos - const padding = 0.75 * this.fontSize + const padding = 1.25 * this.fontSize const showHelpText = !isStatic && !!helpText - const helpTextFontSize = 0.9 * this.fontSize + const helpTextFontSize = 0.85 * this.fontSize return ( - - { .icon { height: $handle-diameter; width: $handle-diameter; - border-radius: 100%; + border-radius: 0; background: $default-knob; - border: 2px solid #fff; + border: 2px solid $white; z-index: 1; pointer-events: none; transform: scale(1); - transition: transform 0.1s ease-out; + transition: transform 0.15s ease-out, background 0.15s ease; } } @@ -129,7 +146,7 @@ $timelineHeight: 32px; &.hover { .handle > .icon { - transform: scale(1.3); + transform: scale(1.2); } .handle:not(.hoverMarker) > .icon { @@ -137,3 +154,40 @@ $timelineHeight: 32px; } } } + +/******************************************************************************* + * Play/Pause Button + ******************************************************************************/ + +.timeline-play-button { + display: flex; + align-items: center; + justify-content: center; + width: $timelineHeight; + height: $timelineHeight; + background: $white; + border: 1px solid $gray-20; + border-radius: 0; + cursor: pointer; + color: $charcoal; + transition: all 150ms ease; + + &:hover { + background: $gray-20; + } + + &:active { + background: $cerulean-100; + border-color: $cerulean-500; + color: $cerulean-900; + } + + &:focus-visible { + outline: 2px solid $auburn; + outline-offset: 2px; + } + + svg { + font-size: 12px; + } +} diff --git a/packages/charts/src/grapher/tooltip/Tooltip.scss b/packages/charts/src/grapher/tooltip/Tooltip.scss index e6f4bd3347f..32a7cdb872e 100644 --- a/packages/charts/src/grapher/tooltip/Tooltip.scss +++ b/packages/charts/src/grapher/tooltip/Tooltip.scss @@ -34,7 +34,7 @@ } > .Tooltip { - border-radius: 4px; + border-radius: 0; border: 1px solid $background-stroke; box-shadow: 0px 4px 40px rgba(0, 0, 0, 0.2); background: white; @@ -57,7 +57,7 @@ background: $background-fill; color: black; padding: 8px 12px; - border-radius: 3px 3px 0 0; + border-radius: 0; .title, .subtitle { @@ -93,7 +93,7 @@ } &.plain header { - border-radius: 3px; + border-radius: 0; background: white; } @@ -383,7 +383,7 @@ position: relative; color: $grey; padding: 4px 12px; - border-radius: 0 0 3px 3px; + border-radius: 0; border-top: 1px solid $light-grey; .line { diff --git a/packages/charts/src/styles/charts.scss b/packages/charts/src/styles/charts.scss index f785b6a0aa6..c969fba9528 100644 --- a/packages/charts/src/styles/charts.scss +++ b/packages/charts/src/styles/charts.scss @@ -7,6 +7,9 @@ * import '@buildcanada/charts/styles.css' */ +// Import Build Canada design system fonts +@use "@buildcanada/components/src/styles/fonts"; + // Import the main grapher styles which include all component styles @import "../grapher/core/grapher.scss"; diff --git a/packages/colours/package.json b/packages/colours/package.json index 8433f136e6b..f009edb4f51 100644 --- a/packages/colours/package.json +++ b/packages/colours/package.json @@ -1,6 +1,6 @@ { "name": "@buildcanada/colours", - "version": "0.2.2", + "version": "0.3.0", "description": "Canadian colour tokens for design systems", "type": "module", "main": "./dist/index.js", diff --git a/packages/components/package.json b/packages/components/package.json index 4885ca8fd40..5d878928764 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@buildcanada/components", - "version": "0.2.2", + "version": "0.3.0", "description": "Build Canada design system components", "type": "module", "main": "src/index.ts",