Closed christopherGdynia closed 2 years ago
Hello @christopherGdynia, nice to hear from you.
I would say the easiest way to accomplish this would be using a CSS class in the body
(or the "root" element of your app).
Your dark mode theme would live in a CSS file that you load in your app entry file (like main.js
), or in the "global" API of any CSS-in-JS solution, like createGlobalStyle
from styled-components.
It's important that you load your theme after you load the Scale library's CSS file.
The structure of the theme would be something like:
::part
(where you change a component's CSS directly)Here's a very brief example taken from the Customization and Themes section in Storybook, just to give you an idea of how it would look:
/* your theme.css file */
/* maybe some global styles? */
body {
background-color: #333;
}
/* (1) overwrite design tokens */
.theme-dark {
--scl-color-primary: limegreen;
--scl-color-primary-hover: seagreen;
--scl-color-primary-active: green;
}
/* (2) overwrite component (scoped) tokens */
.theme-dark scale-button {
--background-secondary: gold;
--color-secondary: white;
}
/* (3) add some custom CSS */
.theme-dark scale-button[variant="secondary"]::part(base) {
background: transparent;
border: 2px solid currentColor;
}
You can activate the theme by using the .theme-dark
class:
<body class="theme-dark">
These are the color design tokens I would overwrite and hopefully should get you pretty far. I wouldn't do --scl-color-black: white
!
:root {
--scl-color-text-standard: hsl(0, 0%, 9.8%);
--scl-color-text-additional: hsl(0, 0%, 40%);
--scl-color-text-link: hsl(227.39999999999998, 89%, 46.3%);
--scl-color-text-link-hover: hsl(236.5, 100%, 37.5%);
--scl-color-text-link-active: hsl(220, 100%, 56.5%);
--scl-color-text-link-visited: hsl(227.39999999999998, 89%, 46.3%);
--scl-color-text-info: hsl(227.39999999999998, 89%, 46.3%);
--scl-color-text-disabled: hsl(0, 0%, 49.8%);
--scl-color-text-success: hsl(136.3, 65.7%, 27.5%);
--scl-color-text-error: hsl(349.70000000000005, 69%, 50.6%);
--scl-color-background-standard: hsl(0, 0%, 100%);
--scl-color-background-light: hsl(0, 0%, 94.9%);
--scl-color-background-darker: hsl(0, 0%, 80%);
--scl-color-background-overlay: hsla(0, 0%, 42.4%, 0.7);
--scl-color-background-disabled: hsl(0, 0%, 80%);
--scl-color-background-success: hsl(136.3, 65.7%, 27.5%);
--scl-color-background-error: hsl(351.20000000000005, 82.6%, 59.4%);
}
You can find the full list in the scale-components.css
file (or here in the docs).
I'm guessing you will find some inconsistencies (where some component is not reacting to a design token change), please let us know.
I hope this helps. I'm looking forward to more feedback.
@acstll thank you very much!
I will implement a first prototyp this week and will post the result below.
@acstll thanks for your detailed answer,
I have tried some stuff now:
my dark theme
--scl-color-text-standard: hsl(0, 0%, 94%);
--scl-color-text-additional: hsl(0, 0%, 50%);
--scl-color-text-link: hsl(227, 100%, 68%);
--scl-color-text-link-hover: hsl(227, 100%, 73%);
--scl-color-text-link-active: hsl(227, 100%, 78%);
--scl-color-text-link-visited: hsl(227, 100%, 68%);
--scl-color-text-info: hsl(227, 100%, 68%);
--scl-color-text-disabled: hsl(0, 0%, 50%);
--scl-color-text-success: hsl(136, 70%, 34%);
--scl-color-text-error: hsl(350, 78%, 50%);
--scl-color-background-standard: hsl(0, 0%, 15%);
--scl-color-background-light: hsl(0, 0%, 20%);
--scl-color-background-darker: hsl(0, 0%, 25%);
--scl-color-background-overlay: hsla(0, 0%, 46%, 0.603);
--scl-color-background-disabled: hsl(0, 0%, 27%);
--scl-color-background-success: hsl(136, 66%, 24%);
--scl-color-background-error: hsl(0, 93%, 38%);
I have some issues that the some css variables don't initialize, thats why, there are some duplicates
ScaleAppHeader:
There needs to be variables for color and background-color for the complete app header component.
.mega-menu > .mega-menu__wrapper{
background-color: var(--scl-color-background-standard);
}
.header__nav__mobile-menu.header__nav__mobile-menu--opened,.main-navigation-mobile__child-menu{
background-color: var(--scl-color-background-standard);
}
.header.menu--open, scale-app-header {
--header-border-radius: var(---scl-radius-8, 8px)
}
.header.sticky .header__nav-before, .header.sticky .header__nav-after, .header.menu--open .header__nav-before, .header.menu--open .header__nav-after{
box-shadow: 0 calc(-1 * var(--header-border-radius)) 0 0 var(--scl-color-background-standard);
}
// this renders only in darkmode
scale-app-header,
.header.menu--open {
--border: 1px solid var(--scl-color-background-light, #363636);
}
app-navigation-main-mobile,
app-navigation-sector-mobile {
--border-bottom: 1px solid #363636;
}
ScaleTag:
ScaleTag variant="secondary" dismissable button:hover is black (default color), is this intended? And the variables have some logic mistake:
// do booth as standard colors or set booth as fixed, but this is confusing
--background: var(--scl-color-text-standard);
--color: var(--scl-color-white);
//my fix
scale-tag {
--background: var(--scl-color-black);
}
ScaleMenuFlyout
There are no variables for color and background
scale-menu-flyout-list {
background-color: transparent;
}
scale-menu-flyout-list::part(base){
background-color: var(--scl-color-background-light);
}
scale-menu-flyout-item::part(base){
color: var(--scl-color-text-standard);
}
Edit: forgot to close the code I am currently working on input fields, but handling the readonly and disabled state needs some more work. I will post any updates below
Add: I forgot about my other css file 🤦♂️
scale-app-header {
--background-nav: var(--scl-color-background-standard);
}
@acstll I have some troubles with the css variables, devtools says: {variable} is not defined, but if I am looking at the html root tag, they are defined (like --scl-color-grey-10)
do you have any idea, why this is happening?
have some troubles with the css variables, devtools says: {variable} is not defined, but if I am looking at the html root tag, they are defined (like --scl-color-grey-10)
where in devtools are you getting that warning? If you could share a screenshot it would be great. I didn't know you could get warned about CSS variables not being defined (which is great).
Thank you for sharing your progress. Do you think I can already try testing it?
There are no warnings
have some troubles with the css variables, devtools says: {variable} is not defined, but if I am looking at the html root tag, they are defined (like --scl-color-grey-10)
where in devtools are you getting that warning? If you could share a screenshot it would be great. I didn't know you could get warned about CSS variables not being defined (which is great).
Thank you for sharing your progress. Do you think I can already try testing it?
@acstll
I get the error in the chrome style devtools, I am inspecting the elements and I see the css variables as shown above, but they don't have a value, thats why they have a disabled style.
Do you mean you would try test the darkmode? This would be nice, but its not finished. I would like to fix the css variables bug and then do it.
By the way, I think, that we should change the box-shadows for dark mode
Maybe something like that:
--scl-shadow-level-0: 0px 2px 8px 0px hsl(0deg 0% 50% / 10%), 0px 1px 2px 0px hsl(0deg 0% 50% / 10%);
Hello there,
sorry for my spamming last week, but this bug made me furious. I think i found the problem.
The css variables have some display bugs in chrome dev-tools, the styling applies, but the elment stylings looks like the screenshots above The applied styling is only shown in the computed tab, but the origin . It was still tricky to get the dark mode to work.
The reason why i thought some css variables aren't working is because of the scale-textarea component. It didn't have the same styling in react as in your storybook, because of the scale-textare with props readonly doesn't set the class textarea--readonly to the div.textarea
booth of the component calls result in the screenshot below
<ScaleTextarea label="Label" readonly />
<ScaleTextarea label="Label" readonly={true} value="asdsadas" />
results in:
What i forgot to mention is that, the readonly class works in a second project
No worries about the spamming ✌️
Nice to know the problem with the CSS vars is in devtools. I'm sorry you had to deal with it anyways.
If I remember correctly, the readonly
attribute was added rather recently. Are you using the same version of @telekom/scale-components
in both projects?
I used beta-13 in two apps but in my testing app, it bugged, but in the second one it didn't. I updated to beta 16 and it works fine
Hi with beta 20 I get you need to update your gloabalStyles
// old
.header.sticky .header__nav-before, .header.sticky .header__nav-after, .header.menu--open .header__nav-before,
.header.menu--open .header__nav-after{
box-shadow: 0 calc(-1 * var(--header-border-radius)) 0 0 var(--scl-color-background-standard);
}
// new
.header.header--sticky .header__nav-before,
.header.header--sticky .header__nav-after,
.header.menu--open .header__nav-before,
.header.menu--open .header__nav-after {
box-shadow: 0 calc(-1 * var(--header-border-radius)) 0 0 var(--scl-color-background-standard);
}
Hi,
Is there a plan to add support for official dark theme?
I think this is very common requirement...
A class like scl-dark-theme
could be predefined by Scale that would conform to accessibility standards (contrast).
I am working on dark theme also in Angular based app.... there are some issues... I will share it here when it's ready.
After reading my responses, there is no complete documention of my styles for darkmode
const dark = css`
body {
--scl-color-text-standard: hsl(0, 0%, 94%);
--scl-color-text-additional: hsl(0, 0%, 50%);
--scl-color-text-link: hsl(227, 100%, 68%);
--scl-color-text-link-hover: hsl(227, 100%, 73%);
--scl-color-text-link-active: hsl(227, 100%, 78%);
--scl-color-text-link-visited: hsl(227, 100%, 68%);
--scl-color-text-info: hsl(227, 100%, 68%);
--scl-color-text-disabled: hsl(0, 0%, 50%);
--scl-color-text-success: hsl(136, 70%, 34%);
--scl-color-text-error: hsl(350, 78%, 50%);
--scl-color-background-standard: hsl(0, 0%, 15%);
--scl-color-background-light: hsl(0, 0%, 20%);
--scl-color-background-darker: hsl(0, 0%, 25%);
--scl-color-background-overlay: hsla(0, 0%, 46%, 0.603);
--scl-color-background-disabled: hsl(0, 0%, 27%);
--scl-color-background-success: hsl(136, 66%, 24%);
--scl-color-background-error: hsl(0, 93%, 38%);
--scl-shadow-level-0: 0px 2px 8px 0px hsla(0deg 0% 100% / 5%),
0px 1px 2px 0px hsla(0deg 0% 100% / 5%);
--scl-shadow-level-1: 0px 4px 16px 0px hsla(0deg 0% 100% / 5%),
0px 2px 4px 0px hsla(0deg 0% 100% / 5%);
--scl-shadow-level-2: 0px 8px 32px 0px hsla(0deg 0% 100% / 5%),
0px 4px 8px 0px hsla(0deg 0% 100% / 5%);
--scl-shadow-level-3: 0px 12px 48px 0px hsla(0deg 0% 100% / 5%),
0px 6px 12px 0px hsla(0deg 0% 100% / 5%);
--scl-shadow-level-4: 0px 16px 64px 0px hsla(0deg 0% 100% / 5%),
0px 8px 16px 0px hsla(0deg 0% 100% / 5%);
--scl-shadow-level-5: 0px 20px 80px 0px hsla(0deg 0% 100% / 5%),
0px 10px 20px 0px hsla(0deg 0% 100% / 5%);
--scl-shadow-level-1-hover: 0px 6px 24px 0px hsla(0deg 0% 100% / 5%),
0px 3px 6px 0px hsla(0deg 0% 100% / 5%);
--scl-shadow-level-1-active: 0px 2px 8px 0px hsla(0deg 0% 100% / 5%),
0px 1px 2px 0px hsla(0deg 0% 100% / 5%);
--scl-shadow-level-2-hover: 0px 10px 40px 0px hsla(0deg 0% 100% / 5%),
0px 5px 10px 0px hsla(0deg 0% 100% / 5%);
--scl-shadow-level-2-active: 0px 6px 24px 0px hsla(0deg 0% 100% / 5%),
0px 3px 6px 0px hsla(0deg 0% 100% / 5%);
--scl-shadow-level-3-hover: 0px 14px 56px 0px hsla(0deg 0% 100% / 5%),
0px 7px 14px 0px hsla(0deg 0% 100% / 5%);
--scl-shadow-level-3-active: 0px 10px 40px 0px hsla(0deg 0% 100% / 5%),
0px 5px 10px 0px hsla(0deg 0% 100% / 5%);
--scl-shadow-level-4-hover: 0px 18px 72px 0px hsla(0deg 0% 100% / 5%),
0px 9px 18px 0px hsla(0deg 0% 100% / 5%);
--scl-shadow-level-4-active: 0px 14px 56px 0px hsla(0deg 0% 100% / 5%),
0px 7px 14px 0px hsla(0deg 0% 100% / 5%);
--scl-shadow-level-5-hover: 0px 22px 88px 0px hsla(0deg 0% 100% / 5%),
0px 11px 22px 0px hsla(0deg 0% 100% / 5%);
--scl-shadow-level-5-active: 0px 18px 72px 0px hsla(0deg 0% 100% / 5%),
0px 9px 18px 0px hsla(0deg 0% 100% / 5%);
}
`;
export const GlobalStyles = createGlobalStyle<{ isDarkMode: boolean }>`
${(props) => props.isDarkMode && dark}
${(p) =>
p.isDarkMode &&
css`
scale-textarea,
scale-text-field {
--background-disabled: var(--scl-color-white);
--border-color-readonly: var(--scl-color-grey-0);
--background-readonly: var(--scl-color-grey-0);
}
scale-textarea div.textarea--readonly textarea.textarea__control {
color: var(--color-label-readonly);
border-color: var(--border-color-readonly);
background: var(--background-readonly);
}
scale-menu-flyout-list {
background-color: transparent;
}
/* scale-tag {
--color: var(--scl-component-tag-color);
--icon-color: var(--color);
--background-button-dismissable-hover: var(--background);
--background: var(--scl-color-black);
} */
scale-tag {
--background: var(--scl-color-black);
}
scale-menu-flyout-list::part(base) {
background-color: var(--scl-color-background-light);
}
scale-menu-flyout-item::part(base) {
color: var(--scl-color-text-standard);
}
.mega-menu > .mega-menu__wrapper {
background-color: var(--scl-color-background-standard);
}
.header__nav__mobile-menu.header__nav__mobile-menu--opened,
.main-navigation-mobile__child-menu {
background-color: var(--scl-color-background-standard);
}
.header.menu--open,
scale-app-header {
--header-border-radius: var(---scl-radius-8, 8px);
}
.header.header--sticky .header__nav-before,
.header.header--sticky .header__nav-after,
.header.menu--open .header__nav-before,
.header.menu--open .header__nav-after {
box-shadow: 0 calc(-1 * var(--header-border-radius)) 0 0 var(--scl-color-background-standard);
}
scale-divider {
--color: var(--scl-color-background-disabled);
}
scale-app-header {
--background-nav: var(--scl-color-background-standard);
}
scale-app-header,
.header.menu--open {
--border: 1px solid var(--scl-color-background-light, #363636);
}
app-navigation-main-mobile,
app-navigation-sector-mobile {
--border-bottom: 1px solid #363636;
}
scale-table {
--background-tbody-tr-hover: #303030;
--background-th-sortable-hover: #303030;
--background-th-sortable-active: #363636;
}
scale-tag {
--background: var(--scl-color-background-overlay);
}
scale-app-footer {
--background: #151515;
}
scale-breadcrumb {
--color-link: var(--scl-color-text-additional);
}
scale-text-field
div:not(.text-field--readonly):not(.text-field--disabled)
input.text-field__control,
scale-textarea div:not(.textarea--readonly):not(.textarea--disabled) textarea.textarea__control,
scale-dropdown div:not(.dropdown--disabled) select.input__dropdown {
color: var(--scl-color-text-standard);
background-color: var(--scl-color-background-standard);
}
scale-text-field div.text-field > label.text-field__label,
scale-textarea div.textarea > label.textarea__label,
scale-dropdown div.dropdown label.input__label {
background-color: transparent;
color: var(--scl-color-grey-40);
}
scale-text-field div.text-field.text-field--disabled input.text-field__control:disabled,
scale-textarea div.textarea.textarea--disabled textarea.textarea__control:disabled,
scale-dropdown div.dropdown.dropdown--disabled select.input__dropdown {
color: var(--scl-color-text-disabled);
background-color: var(--scl-color-background-standard);
}
scale-text-field div.text-field.text-field--disabled > label.text-field__label,
scale-dropdown div.dropdown.dropdown--disabled label.input__label {
color: var(--scl-color-text-disabled);
}
scale-textarea,
scale-text-field,
scale-dropdown {
--border-color-readonly: var(--scl-color-grey-80);
--background-readonly: var(--scl-color-grey-80);
--color-helper-text: var(--scl-color-blue-50);
}
`}
`;
Hi,
Here is my solution in Angular app, using Scale beta 20. We use only small number of components in our app and this solution only support those. (possibly more, but it wasn't tested) Contrast was checked using Firefox accessibility dev tools and manaul testing.
in styles.css
:
/**
* Themes:
* - Scale theme light (default Scale theme) class: `scl-theme scl-theme-light`
* - Scale theme dark (custom theme) class: `scl-theme scl-theme-dark`
**/
/* Desing tokens - light */
.scl-theme.scl-theme-light {
/* default */
--scl-color-text-standard: hsl(0, 0%, 9.8%);
--scl-color-text-additional: hsl(0, 0%, 40%);
--scl-color-background-standard: hsl(0, 0%, 100%);
--scl-color-background-light: hsl(0, 0%, 94.9%);
--scl-color-background-darker: hsl(0, 0%, 46%);
--scl-color-background-overlay: hsla(0, 0%, 42.4%, 0.7);
--scl-color-background-disabled: hsl(0, 0%, 50%);
--scl-color-focus: hsl(215.60000000000002, 100%, 62%);
/* custom */
--scl-color: var(--scl-color-black);
--scl-color-background: var(--scl-color-white);
--scl-color-background-selected: var(--scl-color-pigeon-10);
--scl-color-shadow: rgba(0, 0, 0, 0.1);
}
/* Desing tokens - dark */
.scl-theme.scl-theme-dark {
/* default, overridden */
--scl-color-text-standard: hsl(0, 0%, 90.2%);
--scl-color-text-additional: hsl(0, 0%, 60%);
--scl-color-background-standard: hsl(0, 0%, 15%);
--scl-color-background-light: hsl(0, 0%, 25%);
--scl-color-background-darker: hsl(0, 0%, 5%);
--scl-color-background-overlay: hsla(0, 0%, 42.4%, 0.7);
--scl-color-background-disabled: hsl(0, 0%, 50%);
--scl-color-focus: hsl(215.60000000000002, 100%, 86%);
/* custom */
--scl-color: var(--scl-color-white);
--scl-color-background: var(--scl-color-background-standard);
--scl-color-background-selected: var(--scl-color-pigeon-90);
--scl-color-shadow: rgba(0, 0, 0, 0.5);
}
/* Colors */
.scl-theme {
color: var(--scl-color);
background-color: var(--scl-color-background);
}
/* Shadows */
.scl-theme {
--scl-shadow-level-0: 0px 2px 8px 0px var(--scl-color-shadow),
0px 1px 2px 0px var(--scl-color-shadow);
--scl-shadow-level-1: 0px 4px 16px 0px var(--scl-color-shadow),
0px 2px 4px 0px var(--scl-color-shadow);
--scl-shadow-level-2: 0px 8px 32px 0px var(--scl-color-shadow),
0px 4px 8px 0px var(--scl-color-shadow);
--scl-shadow-level-3: 0px 12px 48px 0px var(--scl-color-shadow),
0px 6px 12px 0px var(--scl-color-shadow);
--scl-shadow-level-4: 0px 16px 64px 0px var(--scl-color-shadow),
0px 8px 16px 0px var(--scl-color-shadow);
--scl-shadow-level-5: 0px 20px 80px 0px var(--scl-color-shadow),
0px 10px 20px 0px var(--scl-color-shadow);
--scl-shadow-level-1-hover: 0px 6px 24px 0px var(--scl-color-shadow),
0px 3px 6px 0px var(--scl-color-shadow);
--scl-shadow-level-1-active: 0px 2px 8px 0px var(--scl-color-shadow),
0px 1px 2px 0px var(--scl-color-shadow);
--scl-shadow-level-2-hover: 0px 10px 40px 0px var(--scl-color-shadow),
0px 5px 10px 0px var(--scl-color-shadow);
--scl-shadow-level-2-active: 0px 6px 24px 0px var(--scl-color-shadow),
0px 3px 6px 0px var(--scl-color-shadow);
--scl-shadow-level-3-hover: 0px 14px 56px 0px var(--scl-color-shadow),
0px 7px 14px 0px var(--scl-color-shadow);
--scl-shadow-level-3-active: 0px 10px 40px 0px var(--scl-color-shadow),
0px 5px 10px 0px var(--scl-color-shadow);
--scl-shadow-level-4-hover: 0px 18px 72px 0px var(--scl-color-shadow),
0px 9px 18px 0px var(--scl-color-shadow);
--scl-shadow-level-4-active: 0px 14px 56px 0px var(--scl-color-shadow),
0px 7px 14px 0px var(--scl-color-shadow);
--scl-shadow-level-5-hover: 0px 22px 88px 0px var(--scl-color-shadow),
0px 11px 22px 0px var(--scl-color-shadow);
--scl-shadow-level-5-active: 0px 18px 72px 0px var(--scl-color-shadow),
0px 9px 18px 0px var(--scl-color-shadow);
}
/* Footer */
.scl-theme scale-app-footer {
--color-minimal: var(--scl-color-text-additional);
--color-link-minimal: var(--scl-color-text-additional);
}
/* Header */
.scl-theme scale-app-header,
.scl-theme scale-app-header .header__nav {
color: var(--scl-color-text-standard);
background-color: var(--scl-color-background-standard);
}
/* Modal */
.scl-theme scale-modal::part(window) {
background-color: var(--scl-color-background-standard);
}
.scl-theme scale-modal::part(close-button) {
color: var(--scl-color-text-standard);
}
/* Table */
.scl-theme scale-table {
--background-tbody-tr-hover: var(--scl-color-background-light);
}
/* Textarea */
.scl-theme scale-textarea textarea {
--color-label: var(--scl-color-text-standard);
--color-placeholder: var(--scl-color-text-additional);
color: var(--scl-color);
background-color: var(--scl-color-background-standard);
}
in angular.json
:
"styles": [
"node_modules/@telekom/scale-components/dist/scale-components/scale-components.css",
"node_modules/@fortawesome/fontawesome-free/css/all.css",
"node_modules/bootstrap/dist/css/bootstrap-grid.min.css",
"src/styles.css"
],
in index.html
:
<body class="m-0 scl-theme">
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
let theme;
try {
theme = localStorage.getItem("theme");
} catch (e) {}
if (!theme) {
theme = window.matchMedia("(prefers-color-scheme: dark)").matches
? "scl-theme-dark"
: "scl-theme-light";
localStorage.setItem("theme", theme);
}
document.body.classList.add(theme);
</script>
<app-root></app-root>
</body>
The "ScaleFlyoutMenuDivider" needs a new border color for dark mode, like:
scale-menu-flyout-divider::part(base) {
border-top-color: rgba(255, 255, 255, 0.15) !important;
}
Hi @christopherGdynia @acstll, I am working on dark mode for a React based application.
I am using scale-app-shell
which hold the main-container
for my application.
How do I get access to the main
element just below the scale-app-header
(shown in the screenshot below) so that I can change its background color to transparent or app specific color.
Please find a screenshot below:
I am using ^3.0.0-beta.17 version of the scaled-components.
Hi @gaurishkamat
You shouldn't use a main
tag inside the scale-app-shell, because of the html syntax.
I am putting section
and aside
into the main
container
You can't access it, because it doesn't have a part
property.
@acstll or @marvinLaubenstein can you give the main
element a part
property, maybe called "main"
Hi @christopherGdynia
The main
tag, one highlighted above is used internally by the scale-app-shell
.
Agree with your input,I will change the main
tag added by me to a section
.
Also adding a part
property to the main
would be of great help @acstll @marvinLaubenstein.
A release featuring dark mode in imminent. Thank you very much 💯 for all the input 🙏
awesome @acstll 🎊🎉
Hello there,
I want to implement a dark mode later to my application, but I am not sure how to implement it. BTW, I am using React, if it helps you to answer me.
I am thinking about setting some css Variables and overriding them on dark mode.
Can you give me some advice or examples?