diff --git a/src/app/app.component.scss b/src/app/app.component.scss index ea54345a..e956325f 100644 --- a/src/app/app.component.scss +++ b/src/app/app.component.scss @@ -1,4 +1,4 @@ -@import '@igo2/core/style/partial/core.variables'; +@import '@igo2/core/partial/core.variables'; @import './pages/portal/portal.variables.scss'; $header-height: 72px; diff --git a/src/app/pages/header/header.component.scss b/src/app/pages/header/header.component.scss index 9c9bd55e..8fa7abe8 100644 --- a/src/app/pages/header/header.component.scss +++ b/src/app/pages/header/header.component.scss @@ -1,4 +1,4 @@ -@use '@igo2/core/theming/prebuilt-themes/qcca'; +@use '../../../theme/qcca'; @import '../portal/portal.variables.scss'; :host { diff --git a/src/app/pages/menu/menu-pages/map/map.variables.scss b/src/app/pages/menu/menu-pages/map/map.variables.scss index 81895b70..e9691dfc 100644 --- a/src/app/pages/menu/menu-pages/map/map.variables.scss +++ b/src/app/pages/menu/menu-pages/map/map.variables.scss @@ -1,5 +1,5 @@ @use 'variables'; -@import '~@igo2/core/style/partial/media'; +@import '~@igo2/core/partial/media'; $app-map-footer-height: 48px; $app-map-mobile-min-space-right: 40px; diff --git a/src/app/pages/menu/menu.component.scss b/src/app/pages/menu/menu.component.scss index 2dffe8ee..a4095515 100644 --- a/src/app/pages/menu/menu.component.scss +++ b/src/app/pages/menu/menu.component.scss @@ -1,5 +1,5 @@ @use 'sass:map'; -@use '@igo2/core/theming/prebuilt-themes/qcca'; +@use '../../../theme/qcca'; @import '../portal/portal.variables.scss'; :host { diff --git a/src/app/pages/portal/panels/feature/feature-custom-details/feature-custom-details.component.scss b/src/app/pages/portal/panels/feature/feature-custom-details/feature-custom-details.component.scss index de57d594..2dc319ca 100644 --- a/src/app/pages/portal/panels/feature/feature-custom-details/feature-custom-details.component.scss +++ b/src/app/pages/portal/panels/feature/feature-custom-details/feature-custom-details.component.scss @@ -1,4 +1,4 @@ -@import '@igo2/core/style/partial/core.variables'; +@import '@igo2/core/partial/core.variables'; div { box-sizing: border-box; diff --git a/src/app/pages/portal/portal.component.scss b/src/app/pages/portal/portal.component.scss index 4aa14f76..ac3d7f4b 100644 --- a/src/app/pages/portal/portal.component.scss +++ b/src/app/pages/portal/portal.component.scss @@ -84,8 +84,13 @@ } igo-search-bar, - igo-search-results igo-list, - .baselayers { + igo-search-results igo-list { + left: $portal-left !important; + } + + igo-baselayers-switcher { + position: absolute; + bottom: 8px; left: $portal-left !important; } diff --git a/src/app/pages/portal/portal.variables.scss b/src/app/pages/portal/portal.variables.scss index 195c0423..7305fc9d 100644 --- a/src/app/pages/portal/portal.variables.scss +++ b/src/app/pages/portal/portal.variables.scss @@ -1,4 +1,4 @@ -@import '@igo2/core/style/partial/media'; +@import '@igo2/core/partial/media'; @import 'variables'; $app-mobile-min-space-right: 40px; diff --git a/src/style/partial/variables.scss b/src/style/partial/variables.scss index 9bc4c761..de9f9ef9 100644 --- a/src/style/partial/variables.scss +++ b/src/style/partial/variables.scss @@ -1,4 +1,4 @@ -@import '@igo2/core/style/partial/core.variables'; +@import '@igo2/core/partial/core.variables'; /*** Generic ***/ $app-background-color: rgb(255, 255, 255); diff --git a/src/theme/qcca/_index.scss b/src/theme/qcca/_index.scss new file mode 100644 index 00000000..d4a447a0 --- /dev/null +++ b/src/theme/qcca/_index.scss @@ -0,0 +1,2 @@ +@forward './base'; +@forward './components'; diff --git a/src/theme/qcca/base/_index.scss b/src/theme/qcca/base/_index.scss new file mode 100644 index 00000000..43ff513c --- /dev/null +++ b/src/theme/qcca/base/_index.scss @@ -0,0 +1,4 @@ +@forward './breakpoints'; +@forward './colors' as colors-*; +@forward './palette'; +@forward './typography'; diff --git a/src/theme/qcca/base/breakpoints.scss b/src/theme/qcca/base/breakpoints.scss new file mode 100644 index 00000000..d99ff452 --- /dev/null +++ b/src/theme/qcca/base/breakpoints.scss @@ -0,0 +1,57 @@ +@use 'sass:map'; + +// There is no standard for breakpoints for the Quebec.ca theme +// This is the Material breakpoint design by devices +$device-breakpoints: ( + mobile: ( + max: 599px + ), + tablet: ( + min: 600px, + max: 1239px + ), + laptop: ( + min: 1240px, + max: 1439px + ), + desktop: ( + min: 1440px + ) +); + +// Source: https://github.com/twbs/bootstrap/blob/main/scss/mixins/_breakpoints.scss +@function breakpoint-min($name, $breakpoints: $device-breakpoints) { + $min: map.get($breakpoints, $name, min); + @return if($min != 0, $min, null); +} + +@function breakpoint-max($name, $breakpoints: $device-breakpoints) { + $max: map.get($breakpoints, $name, max); + @return if($max and $max > 0, $max, null); +} + +// Media of at least the minimum breakpoint width. No query for the smallest breakpoint. +// Makes the @content apply to the given breakpoint and wider. +@mixin media-breakpoint-up($name, $breakpoints: $device-breakpoints) { + $min: breakpoint-min($name, $breakpoints); + @if $min { + @media (min-width: $min) { + @content; + } + } @else { + @content; + } +} + +// Media of at most the maximum breakpoint width. No query for the largest breakpoint. +// Makes the @content apply to the given breakpoint and narrower. +@mixin media-breakpoint-down($name, $breakpoints: $device-breakpoints) { + $max: breakpoint-max($name, $breakpoints); + @if $max { + @media (max-width: $max) { + @content; + } + } @else { + @content; + } +} diff --git a/src/theme/qcca/base/colors.scss b/src/theme/qcca/base/colors.scss new file mode 100644 index 00000000..1598b2e6 --- /dev/null +++ b/src/theme/qcca/base/colors.scss @@ -0,0 +1,40 @@ +@use 'sass:map'; + +// https://design.quebec.ca/bases/couleurs#c118192 +$colors: ( + blue: ( + light: #dae6f0, + light-2: #4a98d9, + normal: #1472bf, + normal-piv: #095797, + medium: #19406c, + dark: #223654 + ), + grey: ( + light: #f1f1f2, + light-2: #c5cad2, + normal: #8893a2, + medium: #6b778a, + dark: #4e5662 + ), + red: ( + pink-light: #ffdbd6, + pink: #e58271, + normal: #cb381f, + dark: #692519 + ), + green: ( + light: #d7f0bb, + normal: #4f813d, + dark: #2c4024 + ), + yellow: ( + light: #f8e69a, + normal: #e0ad03, + dark: #ad781c + ) +); + +@function get($color, $name) { + @return map.get($colors, $color, $name); +} diff --git a/src/theme/qcca/base/palette.scss b/src/theme/qcca/base/palette.scss new file mode 100644 index 00000000..f8376293 --- /dev/null +++ b/src/theme/qcca/base/palette.scss @@ -0,0 +1,50 @@ +@use 'sass:map'; +@use 'sass:color'; +@use './colors'; + +$blue-light: colors.get(blue, light); +$blue-light-2: colors.get(blue, light-2); +$blue-normal: colors.get(blue, normal); +$blue-normal-piv: colors.get(blue, normal-piv); +$blue-medium: colors.get(blue, medium); +$blue-dark: colors.get(blue, dark); + +// Design Quebec colors +$primary: $blue-normal-piv; +$accent: colors.get(red, pink); + +$dark-primary-text: $blue-dark; +$light-primary-text: white; + +$palette: ( + 50: $blue-light, + 100: color.adjust($blue-light-2, $lightness: 20%), + 200: color.adjust($blue-light-2, $lightness: 10%), + 300: $blue-light-2, + 400: $blue-normal, + 500: $primary, + 600: color.adjust($primary, $lightness: -10%), + 700: $blue-medium, + 800: color.adjust($blue-medium, $lightness: -10%), + 900: $blue-dark, + A100: $blue-normal, + A200: color.adjust($blue-normal, $lightness: 10%), + A400: colors.get(grey, light-2), + A700: colors.get(grey, light), + contrast: ( + 50: $dark-primary-text, + 100: $dark-primary-text, + 200: $dark-primary-text, + 300: $dark-primary-text, + 400: $dark-primary-text, + 500: $light-primary-text, + 600: $light-primary-text, + 700: $light-primary-text, + 800: $light-primary-text, + 900: $light-primary-text, + A100: $dark-primary-text, + A200: $light-primary-text, + A400: $light-primary-text, + A700: $light-primary-text + ) +); diff --git a/src/theme/qcca/base/typography/_index.scss b/src/theme/qcca/base/typography/_index.scss new file mode 100644 index 00000000..51c81c87 --- /dev/null +++ b/src/theme/qcca/base/typography/_index.scss @@ -0,0 +1,2 @@ +@forward './typography' as typo-*; +@forward './typography.utils'; diff --git a/src/theme/qcca/base/typography/typography.scss b/src/theme/qcca/base/typography/typography.scss new file mode 100644 index 00000000..3239e694 --- /dev/null +++ b/src/theme/qcca/base/typography/typography.scss @@ -0,0 +1,138 @@ +@use 'sass:map'; +@use '@angular/material' as mat; +@use '../palette'; +@use '../breakpoints'; +@use './typography.utils' as typo-utils; + +// https://design.quebec.ca/bases/polices-caracteres +// https://design.quebec.ca/bases/niveaux-titres +// https://material.angular.io/guide/typography +$typography: mat.define-typography-config( + $font-family: '"Open Sans", sans-serif', + $headline-1: mat.define-typography-level(110px, 110px, 500), + $headline-2: mat.define-typography-level(54px, 54px, 500), + $headline-3: mat.define-typography-level(43px, 46px, 500), + $headline-4: mat.define-typography-level(32px, 38px, 500), + // h1 + $headline-5: mat.define-typography-level(48px, 56px, bold), + // h2 + $headline-6: mat.define-typography-level(36px, 40px, bold), + // h3 + $subtitle-1: mat.define-typography-level(28px, 32px, bold), + // h4 + $subtitle-2: mat.define-typography-level(21px, 24px, bold), + $body-1: mat.define-typography-level(16px, 24px, 400), + $body-2: mat.define-typography-level(12px, 18px, 400), + $caption: mat.define-typography-level(12px, 18px, 400), + $button: mat.define-typography-level(13px, 13px, 500) +); + +$typography-mobile: mat.define-typography-config( + // h1 + $headline-5: mat.define-typography-level(36px, 40px, bold), + // h2 + $headline-6: mat.define-typography-level(28px, 32px, bold), + // h3 + $subtitle-1: mat.define-typography-level(25px, 32px, bold) +); + +$font-color: map.get(palette.$palette, 900); + +@mixin set-base-styles { + body { + color: $font-color; + } + + a { + word-break: break-word; + overflow-wrap: break-word; + cursor: pointer; + color: palette.$primary; + text-decoration: underline; + background-color: transparent; + } + + p, + ul, + li, + u, + .text { + color: $font-color; + font-size: 16px; + line-height: 24px; + } + + p { + margin-bottom: 24px; + } + + strong { + font-weight: 600; + } + + h1, + h2, + h3, + h4, + h5, + h6, + .h1, + .h2, + .h3, + .h4, + .h5, + .h6 { + font-family: Roboto, sans-serif !important; + color: $font-color; + } + + h1 { + margin-top: 72px !important; + margin-bottom: 32px !important; + + @include typo-utils.title-border; + + @include breakpoints.media-breakpoint-down(tablet) { + margin-top: 48px !important; + margin-bottom: 16px !important; + } + } + + h2 { + margin-top: 48px !important; + margin-bottom: 16px !important; + } + + h3 { + margin-top: 24px !important; + margin-bottom: 16px !important; + } + + // WORKAROUND, mat-typography area of intersection h4 is using mat-body-1 + // https://github.com/angular/components/issues/26351 + h4 { + @include typo-utils.title-level-4; + } + + h4 { + margin-top: 24px !important; + margin-bottom: 8px !important; + } + + h5 { + font-size: 19px !important; + line-height: 24px !important; + } + + h6 { + font-size: 16px !important; + line-height: 20px !important; + } + + h5, + h6 { + font-weight: bold !important; + margin-top: 16px !important; + margin-bottom: 0px !important; + } +} diff --git a/src/theme/qcca/base/typography/typography.utils.scss b/src/theme/qcca/base/typography/typography.utils.scss new file mode 100644 index 00000000..c08d4ff0 --- /dev/null +++ b/src/theme/qcca/base/typography/typography.utils.scss @@ -0,0 +1,18 @@ +@use '../palette'; + +@mixin title-border { + &:after { + content: ''; + display: block; + margin: 0; + width: 48px; + padding-top: 4px; + border-bottom: 4px solid palette.$accent; + } +} + +@mixin title-level-4 { + font-size: 21px !important; + line-height: 24px !important; + font-weight: bold !important; +} diff --git a/src/theme/qcca/components/_index.scss b/src/theme/qcca/components/_index.scss new file mode 100644 index 00000000..cd50619e --- /dev/null +++ b/src/theme/qcca/components/_index.scss @@ -0,0 +1,10 @@ +@use './button'; +@use './dialog'; +@use './form-field'; +@use './input'; +@use './list'; +@use './panel'; +@use './search-bar'; +@use './scrollbar'; + +@forward './_index.theme' as all-component-*; diff --git a/src/theme/qcca/components/_index.theme.scss b/src/theme/qcca/components/_index.theme.scss new file mode 100644 index 00000000..808aace8 --- /dev/null +++ b/src/theme/qcca/components/_index.theme.scss @@ -0,0 +1,5 @@ +@use './search-bar.theme' as search-bar; + +@mixin themes($theme) { + @include search-bar.theme($theme); +} diff --git a/src/theme/qcca/components/button.scss b/src/theme/qcca/components/button.scss new file mode 100644 index 00000000..29c63b56 --- /dev/null +++ b/src/theme/qcca/components/button.scss @@ -0,0 +1,24 @@ +@use 'sass:map'; +@use '@angular/material' as mat; +@use '../base'; + +$color-500: map.get(base.$palette, 500); + +.mdc-button { + font-size: mat.font-size(base.$typo-typography, body-1) !important; + line-height: mat.line-height(base.$typo-typography, body-1) !important; + font-weight: bold !important; +} + +.mat-mdc-outlined-button { + border: 2px solid currentColor; +} + +.mat-mdc-button-base { + border-radius: 0 !important; +} + +.mat-mdc-raised-button { + color: $color-500 !important; + border-color: $color-500 !important; +} diff --git a/src/theme/qcca/components/dialog.scss b/src/theme/qcca/components/dialog.scss new file mode 100644 index 00000000..53f07e86 --- /dev/null +++ b/src/theme/qcca/components/dialog.scss @@ -0,0 +1,36 @@ +@use '../base'; + +.mdc-dialog { + max-width: 600px; + + &__surface { + border-radius: 0 !important; + } + + &__title { + padding-top: 8px !important; // Workaround, this should be 32px but Material apply a default height for the title. + padding-bottom: 24px !important; + + @include base.title-level-4; + @include base.title-border; + } + + &__tile, + &__content, + &__actions { + padding-left: 32px !important; + padding-right: 32px !important; + } + + &__actions { + padding-top: 24px !important; + padding-bottom: 32px !important; + } + + .close-button { + $iconButtonPadding: 8px; + position: absolute; + top: 16px - $iconButtonPadding; + right: 16px - $iconButtonPadding; + } +} diff --git a/src/theme/qcca/components/form-field.scss b/src/theme/qcca/components/form-field.scss new file mode 100644 index 00000000..ae9a0959 --- /dev/null +++ b/src/theme/qcca/components/form-field.scss @@ -0,0 +1,5 @@ +.mat-mdc-text-field-wrapper, +.mdc-notched-outline__leading, +.mdc-notched-outline__trailing { + border-radius: 0 !important; +} diff --git a/src/theme/qcca/components/input.scss b/src/theme/qcca/components/input.scss new file mode 100644 index 00000000..505453a2 --- /dev/null +++ b/src/theme/qcca/components/input.scss @@ -0,0 +1,6 @@ +@use 'sass:map'; +@use '../base'; + +.mat-mdc-input-element { + color: base.colors-get(grey, medium) !important; +} diff --git a/src/theme/qcca/components/list.scss b/src/theme/qcca/components/list.scss new file mode 100644 index 00000000..612584b6 --- /dev/null +++ b/src/theme/qcca/components/list.scss @@ -0,0 +1,24 @@ +@use 'sass:map'; +@use '@angular/material' as mat; +@use '../base'; + +// TODO rework this style to be more generic + +igo-search-results-item { + .mdc-list-item__primary-text { + white-space: normal; + overflow: hidden; + text-overflow: ellipsis; + max-height: unset !important; + line-height: 18px !important; + } +} + +igo-list [igolistitem][color='accent'].igo-list-item-selected > mat-list-item { + background-color: map.get(base.$palette, 400); + + h4, + small { + color: map.get(base.$palette, contrast, 500) !important; + } +} diff --git a/src/theme/qcca/components/panel.scss b/src/theme/qcca/components/panel.scss new file mode 100644 index 00000000..3560fb6c --- /dev/null +++ b/src/theme/qcca/components/panel.scss @@ -0,0 +1,8 @@ +@use 'sass:map'; +@use '../base'; + +.igo-panel-header, +.igo-panel-header button, +.igo-panel-title { + color: map.get(base.$palette, contrast, 500) !important; +} diff --git a/src/theme/qcca/components/scrollbar.scss b/src/theme/qcca/components/scrollbar.scss new file mode 100644 index 00000000..60151fb7 --- /dev/null +++ b/src/theme/qcca/components/scrollbar.scss @@ -0,0 +1,15 @@ +@use '../base'; + +*::-webkit-scrollbar { + width: 6px; +} + +*::-webkit-scrollbar-track { + box-shadow: inset 0 0 5px base.$blue-light; + border-radius: 10px; +} + +*::-webkit-scrollbar-thumb { + background: base.$blue-normal-piv; + border-radius: 10px; +} diff --git a/src/theme/qcca/components/search-bar.scss b/src/theme/qcca/components/search-bar.scss new file mode 100644 index 00000000..9828ad01 --- /dev/null +++ b/src/theme/qcca/components/search-bar.scss @@ -0,0 +1,41 @@ +@use 'sass:map'; +@use '@angular/material' as mat; +@use '../base'; + +igo-search-bar { + // Workaroung, OPEN SANS font add a mysterious 1px for the height + .mat-mdc-form-field-infix { + max-height: 40px; + } + + button[mat-icon-button] { + background-color: map.get(base.$palette, 500); + + &:hover { + background-color: map.get(base.$palette, 400); + } + } + + mat-icon { + color: map.get(base.$palette, contrast, 500); + } +} + +igo-search-results { + igo-collapsible { + .mdc-list-item__primary-text { + color: base.$blue-dark; + font-weight: bold; + } + } + + igo-search-results-item { + .mdc-list-item__primary-text { + font-weight: normal; + } + } + + .mdc-list-item--with-leading-icon .mdc-list-item__start { + color: base.$blue-dark; + } +} diff --git a/src/theme/qcca/components/search-bar.theme.scss b/src/theme/qcca/components/search-bar.theme.scss new file mode 100644 index 00000000..55de6c27 --- /dev/null +++ b/src/theme/qcca/components/search-bar.theme.scss @@ -0,0 +1,29 @@ +@use 'sass:map'; +@use '@angular/material' as mat; + +@mixin theme($theme) { + @include density($theme); +} + +@mixin density($theme) { + $density: mat.get-density-config($theme); + + $theme4: map.merge( + $theme, + ( + density: $density - 4 + ) + ); + + $theme2: map.merge( + $theme, + ( + density: $density - 2 + ) + ); + + igo-search-bar { + @include mat.form-field-density($theme4); + @include mat.icon-button-density($theme2); + } +} diff --git a/src/theme/theme.scss b/src/theme/theme.scss index 8b651b6f..9ee18e4b 100644 --- a/src/theme/theme.scss +++ b/src/theme/theme.scss @@ -1,9 +1,58 @@ @use 'sass:map'; @use '@angular/material' as mat; -@use '@igo2/core/theming/prebuilt-themes/qcca-theme'; + +@use '@igo2/core' as core; +@use '@igo2/core/theming/all-theme' as igo-all-theme; + @use '../app/app.theming' as app; -@include app.themes(qcca-theme.$theme); +@use './qcca'; + +// https://design.quebec.ca/a-propos-systeme-design +$primary: mat.define-palette(qcca.$palette, 500, 400, 700); +$accent: mat.define-palette(qcca.$palette, 400, 100, 700); +$warn: mat.define-palette(qcca.$palette, 800); +$success: mat.define-palette(qcca.$palette, 900); +$background: mat.define-palette(qcca.$palette, 100, 100, 100); +$foreground: mat.define-palette(qcca.$palette, 700, 700, 700); + +$theme: mat.define-light-theme( + ( + color: ( + primary: $primary, + accent: $accent, + warn: $warn, + success: $success, + background: $background + ), + typography: qcca.$typo-typography, + density: 0 + ) +); +$theme: map.merge( + $theme, + ( + foreground: + core.theme-foreground(mat.define-palette(qcca.$palette, 500, 100, 700)) + ) +); + + +@include mat.core(); +@include mat.typography-hierarchy(qcca.$typo-typography); +@include mat.all-component-themes($theme); + +@include igo-all-theme.all-component-themes($theme); + +@include qcca.all-component-themes($theme); + +@media (max-width: 1200px) { + @include mat.typography-hierarchy(qcca.$typo-typography-mobile); +} + +@include qcca.typo-set-base-styles(); + +@include app.themes($theme); igo-rotation-button, igo-zoom-button button,