From ddc6ef90ae16d780b06bddb031271bd430d93e6c Mon Sep 17 00:00:00 2001 From: Juano Date: Mon, 22 Jan 2024 21:43:12 -0500 Subject: [PATCH] encapsulate styles to shadow dom only --- src/app/index.ts | 2 +- src/components/styles/common-styles.scss | 250 +++++++++++++++++++ src/components/styles/custom-pico-theme.scss | 187 +++++++++++++- src/components/styles/custom-pico.scss | 8 +- src/components/styles/document.scss | 48 ++++ src/components/styles/shadow-dom.css | 13 +- 6 files changed, 487 insertions(+), 21 deletions(-) create mode 100644 src/components/styles/common-styles.scss create mode 100644 src/components/styles/document.scss diff --git a/src/app/index.ts b/src/app/index.ts index 8916121..5bdc083 100644 --- a/src/app/index.ts +++ b/src/app/index.ts @@ -1,7 +1,7 @@ import { State, stateProvider } from '../models/state'; import '../components/UsgApp.mjs'; import { TDataEntries } from '../models/types'; -import 'style-loader!../components/styles/light-dom.css'; +// import '../components/styles/shadow-dom.css'; async function start() { const usgData = (await import('../data/usaid_data.csv')) diff --git a/src/components/styles/common-styles.scss b/src/components/styles/common-styles.scss new file mode 100644 index 0000000..4488029 --- /dev/null +++ b/src/components/styles/common-styles.scss @@ -0,0 +1,250 @@ +// Commons Styles +:host { + // Typography + --font-family: system-ui, -apple-system, "Segoe UI", "Roboto", "Ubuntu", + "Cantarell", "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", + "Segoe UI Symbol", "Noto Color Emoji"; + --line-height: 1.5; + --font-weight: 400; + --font-size: 16px; + + // Responsive typography + @if $enable-responsive-typography { + @if map-get($breakpoints, "sm") { + @media (min-width: map-get($breakpoints, "sm")) { + --font-size: 17px; + } + } + + @if map-get($breakpoints, "md") { + @media (min-width: map-get($breakpoints, "md")) { + --font-size: 18px; + } + } + + @if map-get($breakpoints, "lg") { + @media (min-width: map-get($breakpoints, "lg")) { + --font-size: 19px; + } + } + + @if map-get($breakpoints, "xl") { + @media (min-width: map-get($breakpoints, "xl")) { + --font-size: 20px; + } + } + } + + // Borders + --border-radius: 0.25rem; + --border-width: 1px; + --outline-width: 3px; + + // Spacings + --spacing: 1rem; + + // Spacings for typography elements + --typography-spacing-vertical: 1.5rem; + + // Spacings for body > header, body > main, body > footer, section, article + --block-spacing-vertical: calc(var(--spacing) * 2); + --block-spacing-horizontal: var(--spacing); + + @if ($enable-classes and $enable-grid) { + --grid-spacing-vertical: 0; + --grid-spacing-horizontal: var(--spacing); + } + + // Spacings for form elements and button + --form-element-spacing-vertical: 0.75rem; + --form-element-spacing-horizontal: 1rem; + + // Spacings for nav component + --nav-element-spacing-vertical: 1rem; + --nav-element-spacing-horizontal: 0.5rem; + --nav-link-spacing-vertical: 0.5rem; + --nav-link-spacing-horizontal: 0.5rem; + + // Font weight for form labels & fieldsets legend + --form-label-font-weight: var(--font-weight); + + // Transitions + --transition: 0.2s ease-in-out; + + // Modal () + --modal-overlay-backdrop-filter: blur(0.25rem); +} + +// Responsives spacings +@if $enable-responsive-spacings { + + // Sectioning + #{$semantic-root-element}>header, + #{$semantic-root-element}>main, + #{$semantic-root-element}>footer, + section { + @if map-get($breakpoints, "sm") { + @media (min-width: map-get($breakpoints, "sm")) { + --block-spacing-vertical: calc(var(--spacing) * 2.5); + } + } + + @if map-get($breakpoints, "md") { + @media (min-width: map-get($breakpoints, "md")) { + --block-spacing-vertical: calc(var(--spacing) * 3); + } + } + + @if map-get($breakpoints, "lg") { + @media (min-width: map-get($breakpoints, "lg")) { + --block-spacing-vertical: calc(var(--spacing) * 3.5); + } + } + + @if map-get($breakpoints, "xl") { + @media (min-width: map-get($breakpoints, "xl")) { + --block-spacing-vertical: calc(var(--spacing) * 4); + } + } + } + + // Card (
) + article { + @if map-get($breakpoints, "sm") { + @media (min-width: map-get($breakpoints, "sm")) { + --block-spacing-horizontal: calc(var(--spacing) * 1.25); + } + } + + @if map-get($breakpoints, "md") { + @media (min-width: map-get($breakpoints, "md")) { + --block-spacing-horizontal: calc(var(--spacing) * 1.5); + } + } + + @if map-get($breakpoints, "lg") { + @media (min-width: map-get($breakpoints, "lg")) { + --block-spacing-horizontal: calc(var(--spacing) * 1.75); + } + } + + @if map-get($breakpoints, "xl") { + @media (min-width: map-get($breakpoints, "xl")) { + --block-spacing-horizontal: calc(var(--spacing) * 2); + } + } + } + + // Modal + dialog>article { + + --block-spacing-vertical: calc(var(--spacing) * 2); + --block-spacing-horizontal: var(--spacing); + + @if map-get($breakpoints, "sm") { + @media (min-width: map-get($breakpoints, "sm")) { + --block-spacing-vertical: calc(var(--spacing) * 2.5); + --block-spacing-horizontal: calc(var(--spacing) * 1.25); + } + } + + @if map-get($breakpoints, "md") { + @media (min-width: map-get($breakpoints, "md")) { + --block-spacing-vertical: calc(var(--spacing) * 3); + --block-spacing-horizontal: calc(var(--spacing) * 1.5); + } + } + } +} + +// Link +a { + --text-decoration: none; + + // Secondary & Contrast + @if $enable-classes { + + &.secondary, + &.contrast { + --text-decoration: underline; + } + } +} + +// Small +small { + --font-size: 0.875em; +} + +// Headings +h1, +h2, +h3, +h4, +h5, +h6 { + --font-weight: 700; +} + +h1 { + --font-size: 2rem; + --typography-spacing-vertical: 3rem; +} + +h2 { + --font-size: 1.75rem; + --typography-spacing-vertical: 2.625rem; +} + +h3 { + --font-size: 1.5rem; + --typography-spacing-vertical: 2.25rem; +} + +h4 { + --font-size: 1.25rem; + --typography-spacing-vertical: 1.874rem; +} + +h5 { + --font-size: 1.125rem; + --typography-spacing-vertical: 1.6875rem; +} + +// Forms elements +[type="checkbox"], +[type="radio"] { + --border-width: 2px; +} + +[type="checkbox"][role="switch"] { + --border-width: 3px; +} + +// Table +thead, +tfoot { + + th, + td { + --border-width: 3px; + } +} + +:not(thead, tfoot)>*>td { + --font-size: 0.875em; +} + +// Code +pre, +code, +kbd, +samp { + --font-family: "Menlo", "Consolas", "Roboto Mono", "Ubuntu Monospace", + "Noto Mono", "Oxygen Mono", "Liberation Mono", monospace, + "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; +} + +kbd { + --font-weight: bolder; +} \ No newline at end of file diff --git a/src/components/styles/custom-pico-theme.scss b/src/components/styles/custom-pico-theme.scss index 92be66d..40b6b49 100644 --- a/src/components/styles/custom-pico-theme.scss +++ b/src/components/styles/custom-pico-theme.scss @@ -7,11 +7,190 @@ @import "~@picocss/pico/scss/themes/default/colors"; // Commons styles -@import "~@picocss/pico/scss/themes/default/styles"; +@import "./common-styles.scss"; -// Light theme (Default) -// Can be forced with data-theme="light" -@import "~@picocss/pico/scss/themes/default/light"; +@import "~@picocss/pico/scss/functions"; + +:host { + --font-family: 'Source Sans Pro', + sans-serif; + --usaid-blue: #002F6C; + --usaid-red: #BA0C2F; + --rich-black: #212721; + --medium-blue: #0067B9; + --light-blue: #A7C6ED; + --ultralight-blue: #a7c6ed73; + --web-blue: #205493; + --dark-red: #651D32; + --dark-gray: #6C6463; + --medium-gray: #8C8985; + --light-gray: #CFCDC9; + + --h2-color: var(--usaid-blue); + + --color: var(--rich-black); + + --primary: var(--light-gray); + --primary-hover: var(--medium-gray); + --primary-inverse: var(--usaid-blue); + + --table-border-color: var(--rich-black); + + --font-size: 100%; + + // + + --background-color: #{$white}; + + // Texts colors + // --color: #{$grey-700}; + --h1-color: #{$grey-900}; + // --h2-color: #{mix($grey-900, $grey-800)}; + --h3-color: #{$grey-800}; + --h4-color: #{mix($grey-800, $grey-700)}; + --h5-color: #{$grey-700}; + --h6-color: #{mix($grey-700, $grey-600)}; + + // Muted colors + --muted-color: #{$grey-500}; + --muted-border-color: #{$grey-50}; + + // Primary colors + // --primary: #{$primary-600}; + // --primary-hover: #{$primary-700}; + --primary-focus: #{rgba($primary-600, 0.125)}; + // --primary-inverse: #{$white}; + + // Secondary colors + --secondary: #{$grey-600}; + --secondary-hover: #{$grey-700}; + --secondary-focus: #{rgba($grey-600, 0.125)}; + --secondary-inverse: #{$white}; + + // Contrast colors + --contrast: #{$grey-900}; + --contrast-hover: #{$black}; + --contrast-focus: #{rgba($grey-600, 0.125)}; + --contrast-inverse: #{$white}; + + // Highlighted text () + --mark-background-color: #{mix($amber-100, $amber-50)}; + --mark-color: #{mix($grey-900, $amber-900, 75%)}; + + // Inserted () & Deleted () + --ins-color: #{$green-700}; + --del-color: #{$red-800}; + + // Blockquote + --blockquote-border-color: var(--muted-border-color); + --blockquote-footer-color: var(--muted-color); + + // Button + // To disable box-shadow, remove the var or set to '0 0 0 rgba(0, 0, 0, 0)' + // Don't use, 'none, 'false, 'null', '0', etc. + --button-box-shadow: 0 0 0 rgba(0, 0, 0, 0); + --button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0); + + // Form elements + --form-element-background-color: transparent; + --form-element-border-color: #{$grey-300}; + --form-element-color: var(--color); + --form-element-placeholder-color: var(--muted-color); + --form-element-active-background-color: transparent; + --form-element-active-border-color: var(--primary); + --form-element-focus-color: var(--primary-focus); + --form-element-disabled-background-color: #{$grey-100}; + --form-element-disabled-border-color: #{$grey-300}; + --form-element-disabled-opacity: 0.5; + --form-element-invalid-border-color: #{$red-800}; + --form-element-invalid-active-border-color: #{$red-700}; + --form-element-invalid-focus-color: #{rgba($red-700, 0.125)}; + --form-element-valid-border-color: #{$green-700}; + --form-element-valid-active-border-color: #{$green-600}; + --form-element-valid-focus-color: #{rgba($green-600, 0.125)}; + + // Switch (input[type="checkbox"][role="switch"]) + --switch-background-color: #{$grey-200}; + --switch-color: var(--primary-inverse); + --switch-checked-background-color: var(--primary); + + // Range (input[type="range"]) + --range-border-color: #{$grey-100}; + --range-active-border-color: #{$grey-200}; + --range-thumb-border-color: var(--background-color); + --range-thumb-color: var(--secondary); + --range-thumb-hover-color: var(--secondary-hover); + --range-thumb-active-color: var(--primary); + + // Table + // --table-border-color: var(--muted-border-color); + --table-row-stripped-background-color: #{mix($grey-50, $white)}; + + // Code + --code-background-color: #{$grey-50}; + --code-color: var(--muted-color); + --code-kbd-background-color: var(--contrast); + --code-kbd-color: var(--contrast-inverse); + --code-tag-color: #{hsl(330, 40%, 50%)}; + --code-property-color: #{hsl(185, 40%, 40%)}; + --code-value-color: #{hsl(40, 20%, 50%)}; + --code-comment-color: #{$grey-300}; + + // Accordion (
) + --accordion-border-color: var(--muted-border-color); + --accordion-close-summary-color: var(--color); + --accordion-open-summary-color: var(--muted-color); + + // Card (
) + $box-shadow-elevation: 1rem; + $box-shadow-blur-strengh: 6rem; + $box-shadow-opacity: 0.06; + --card-background-color: var(--background-color); + --card-border-color: var(--muted-border-color); + --card-box-shadow: #{($box-shadow-elevation * 0.5 * 0.029)} #{($box-shadow-elevation * 0.029)} #{($box-shadow-blur-strengh * 0.029)} #{rgba($grey-900, ($box-shadow-opacity * 0.283))}, + #{($box-shadow-elevation * 0.5 * 0.067)} #{($box-shadow-elevation * 0.067)} #{($box-shadow-blur-strengh * 0.067)} #{rgba($grey-900, ($box-shadow-opacity * 0.4))}, + #{($box-shadow-elevation * 0.5 * 0.125)} #{($box-shadow-elevation * 0.125)} #{($box-shadow-blur-strengh * 0.125)} #{rgba($grey-900, ($box-shadow-opacity * 0.5))}, + #{($box-shadow-elevation * 0.5 * 0.225)} #{($box-shadow-elevation * 0.225)} #{($box-shadow-blur-strengh * 0.225)} #{rgba($grey-900, ($box-shadow-opacity * 0.6))}, + #{($box-shadow-elevation * 0.5 * 0.417)} #{($box-shadow-elevation * 0.417)} #{($box-shadow-blur-strengh * 0.417)} #{rgba($grey-900, ($box-shadow-opacity * 0.717))}, + #{($box-shadow-elevation * 0.5)} #{$box-shadow-elevation} #{$box-shadow-blur-strengh} #{rgba($grey-900, $box-shadow-opacity)}, + 0 0 0 0.0625rem #{rgba($grey-900, ($box-shadow-opacity * 0.25) )}; + --card-sectionning-background-color: #{mix($grey-50, $white, 25%)}; + + // Dropdown (
) + --dropdown-background-color: #{mix($grey-50, $white, 25%)}; + --dropdown-border-color: #{mix($grey-100, $grey-50)}; + --dropdown-box-shadow: var(--card-box-shadow); + --dropdown-color: var(--color); + --dropdown-hover-background-color: #{$grey-50}; + + // Modal () + --modal-overlay-background-color: #{rgba($grey-100, 0.7)}; + + // Progress + --progress-background-color: #{$grey-100}; + --progress-color: var(--primary); + + // Loading ([aria-busy=true]) + --loading-spinner-opacity: 0.5; + + // Tooltip ([data-tooltip]) + --tooltip-background-color: var(--contrast); + --tooltip-color: var(--contrast-inverse); + + // Icons + --icon-checkbox: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($white)}' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E"); + --icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($grey-700)}' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); + --icon-chevron-button: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($white)}' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); + --icon-chevron-button-inverse: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($white)}' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); + --icon-close: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($grey-500)}' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E"); + --icon-date: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($grey-700)}' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E"); + --icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($red-800)}' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E"); + --icon-minus: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($white)}' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'%3E%3C/line%3E%3C/svg%3E"); + --icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($grey-700)}' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E"); + --icon-time: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($grey-700)}' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E"); + --icon-valid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($green-700)}' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E"); + +} // Accent-color progress, diff --git a/src/components/styles/custom-pico.scss b/src/components/styles/custom-pico.scss index 62db74c..e08281c 100644 --- a/src/components/styles/custom-pico.scss +++ b/src/components/styles/custom-pico.scss @@ -24,16 +24,16 @@ $enable-important: false; // Config @import "~@picocss/pico/scss/variables"; -// Theming -@import "./custom-pico-theme.scss"; - // Modules @import '~@picocss/pico/scss/components/modal'; @import '~@picocss/pico/scss/components/accordion'; @import '~@picocss/pico/scss/components/card'; +// Theming +@import "./custom-pico-theme.scss"; + // // Layout -@import "~@picocss/pico/scss/layout/document"; // html +@import "./document.scss"; // html @import "~@picocss/pico/scss/layout/sectioning"; // body, header, main, footer @import "~@picocss/pico/scss/layout/container"; // .container, .container-fluid @import "~@picocss/pico/scss/layout/section"; // section diff --git a/src/components/styles/document.scss b/src/components/styles/document.scss new file mode 100644 index 0000000..551ac76 --- /dev/null +++ b/src/components/styles/document.scss @@ -0,0 +1,48 @@ +/** + * Document + * Content-box & Responsive typography + */ + +// Reboot based on : +// - normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css +// - sanitize.css v13.0.0 | CC0 1.0 Universal | github.com/csstools/sanitize.css +// –––––––––––––––––––– + +// 1. Add border box sizing in all browsers (opinionated) +// 2. Backgrounds do not repeat by default (opinionated) +*, +*::before, +*::after { + box-sizing: border-box; // 1 + background-repeat: no-repeat; // 2 +} + +// 1. Add text decoration inheritance in all browsers (opinionated) +// 2. Add vertical alignment inheritance in all browsers (opinionated) +::before, +::after { + text-decoration: inherit; // 1 + vertical-align: inherit; // 2 +} + +// 1. Use the default cursor in all browsers (opinionated) +// 2. Change the line height in all browsers (opinionated) +// 3. Breaks words to prevent overflow in all browsers (opinionated) +// 4. Use a 4-space tab width in all browsers (opinionated) +// 5. Remove the grey highlight on links in iOS (opinionated) +// 6. Prevent adjustments of font size after orientation changes in iOS +:host { + -webkit-tap-highlight-color: transparent; // 5 + -webkit-text-size-adjust: 100%; // 6 + text-size-adjust: 100%; // 6 + background-color: var(--background-color); + color: var(--color); + font-weight: var(--font-weight); + font-size: var(--font-size); + line-height: var(--line-height); // 2 + font-family: var(--font-family); + text-rendering: optimizeLegibility; + overflow-wrap: break-word; // 3 + cursor: default; // 1 + tab-size: 4; // 4 +} \ No newline at end of file diff --git a/src/components/styles/shadow-dom.css b/src/components/styles/shadow-dom.css index 9fd486f..12b1f8d 100644 --- a/src/components/styles/shadow-dom.css +++ b/src/components/styles/shadow-dom.css @@ -1,17 +1,5 @@ @import './custom-pico.scss'; -:host { - --h2-color: var(--usaid-blue); - - --color: var(--rich-black); - - --primary: var(--light-gray); - --primary-hover: var(--medium-gray); - --primary-inverse: var(--usaid-blue); - - --table-border-color: var(--rich-black); -} - .info { font-size: 90%; } @@ -31,6 +19,7 @@ button.link { cursor: pointer; width: unset; } + button.link:hover { text-decoration: underline; }