Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example color theme improvements #5087

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 0 additions & 15 deletions scss/_utilities_baseline-grid.scss
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,4 @@
}
}
// stylelint-enable selector-max-type

.u-baseline-grid__toggle {
bottom: $spv--x-large;
color: $colors--light-theme--text-default; // Force light theme colour because of baseline grid background
position: fixed;
right: $sp-unit * 3;
z-index: 201;
}

// hide the theme toggle in Percy
@media only percy {
.u-baseline-grid__toggle {
visibility: hidden !important;
}
}
}
39 changes: 0 additions & 39 deletions scss/_utilities_theme-toggle.scss

This file was deleted.

2 changes: 0 additions & 2 deletions scss/_vanilla.scss
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@
@import 'utilities_no-print';
@import 'utilities_text-max-width';
@import 'utilities_text-figures';
@import 'utilities_theme-toggle';

// Include all the CSS
@mixin vanilla {
Expand Down Expand Up @@ -183,5 +182,4 @@
@include vf-u-no-print;
@include vf-u-text-max-width;
@include vf-u-text-figures;
@include vf-u-theme-toggle;
}
27 changes: 26 additions & 1 deletion scss/docs/example.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,35 @@

@import '../vanilla';
@include vf-u-baseline-grid;
@include vf-u-theme-toggle;
@include vf-b-button;
@include vf-p-segmented-control;
@include vf-p-forms-inline;

// stylelint-disable selector-max-type -- examples can use type selectors
body {
margin: 1rem;
}
// stylelint-enable selector-max-type

.p-example-controls {
@include vf-transition($property: #{transform, box-shadow, visibility}, $duration: snap);
align-items: center;
background-color: var(--vf-color-background-alt);
bottom: 0;
box-shadow: $box-shadow--deep;
display: flex;
flex-flow: row wrap;
gap: $sp-unit;
justify-content: space-between;
left: 0;
padding: $spv--x-small $sph--x-small;
position: fixed;
right: 0;

// Above *all* other elements.
z-index: 1000000;

@media only percy {
visibility: hidden !important;
}
}
170 changes: 139 additions & 31 deletions templates/static/js/example-tools.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
const SUPPORTED_THEMES = ['light', 'dark', 'paper'];
const [DEFAULT_COLOR_THEME] = SUPPORTED_THEMES;
const COLOR_THEME_QUERY_PARAM_NAME = 'theme';
var activeTheme = DEFAULT_COLOR_THEME;

(function () {
function inIframe() {
try {
Expand All @@ -13,51 +18,154 @@
return temp.content;
}

/**
* Gets the current query parameters
* @returns {URLSearchParams}
*/
function getQueryParameters() {
return new URLSearchParams(window.location.search);
}

/**
* Sets the query parameter value of `key` to `value`
* @param {String} key
* @param {String} value
* @param {Boolean} reload Whether to cause a page load after updating the query parameter
* @returns {URLSearchParams} Query parameters after update
*/
function setQueryParameter(key, value, reload = false) {
var currentQueryParams = getQueryParameters();

if (reload && currentQueryParams.get(key) !== value) {
currentQueryParams.set(key, value);
window.location.search = currentQueryParams.toString();
} else {
var url = new URL(window.location.href);
if (value) {
url.searchParams.set(key, value);
} else {
url.searchParams.delete(key);
}
if (window.location.href !== url.toString()) {
window.history.replaceState(null, null, url.toString());
}
}
return getQueryParameters();
}

/**
* Converts a theme name to its document class name, used for applying that color theme to the body
* @param {String} themeName
* @returns {string}
*/
function convertThemeNameToClassName(themeName) {
return `is-${themeName}`;
}

/**
* Converts a theme name to its JS toggler identifier name, used for targeting it with JS events
* @param {String} themeName
* @returns {string}
*/
function convertThemeNameToButtonIdentifier(themeName) {
return `js-${themeName}-theme-toggle`;
bartaz marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Converts a string to titlecase (first letter capitalized & subsequent letters lowercase)
* @param {String} str
* @returns {string}
*/
function titleCase(str) {
return `${str.charAt(0).toUpperCase()}${str.slice(1).toLowerCase()}`;
}

/**
* Sets a color theme as active; removes all other color themes from active status
* @param {String} themeToSelect
*/
function selectColorTheme(themeToSelect) {
// Apply the color theme to the document body
document.body.classList.add(convertThemeNameToClassName(themeToSelect));
// Remove the old color theme from the document body
if (themeToSelect !== activeTheme) document.body.classList.remove(convertThemeNameToClassName(activeTheme));

// Update address bar to reflect the newly selected color theme
setQueryParameter(COLOR_THEME_QUERY_PARAM_NAME, themeToSelect.toLowerCase());

// Update theme selector button states to reflect which one is currently active
var themeButtonToSelect = document.getElementById(convertThemeNameToButtonIdentifier(themeToSelect));
themeButtonToSelect?.setAttribute('aria-selected', 'true');
if (activeTheme) {
var themeButtonToDeselect = document.getElementById(convertThemeNameToButtonIdentifier(activeTheme));
themeButtonToDeselect?.setAttribute('aria-selected', 'false');
}

activeTheme = themeToSelect;
}

if (!inIframe()) {
document.documentElement.classList.add('u-baseline-grid');

document.addEventListener('DOMContentLoaded', function () {
var body = document.body;
var controls = fragmentFromString(
'<div class="u-baseline-grid__toggle"><label class="p-switch"><input type="checkbox" class="p-switch__input js-baseline-toggle" /><span class="p-switch__slider"></span><span class="p-switch__label">Toggle baseline grid</span></label></div>',
);
var themes = fragmentFromString(
'<div class="u-theme-toggle is-light"><button class="u-theme-toggle__button u-theme-toggle__dark js-dark-theme-toggle">Dark</button><button class="u-theme-toggle__button u-theme-toggle__light js-light-theme-toggle">Light</button><button class="u-theme-toggle__button u-theme-toggle__paper js-paper-theme-toggle">Paper</button></div>',
);
var controls = document.createElement('div');
controls.classList.add('p-example-controls', 'p-form');
var queryParameters = getQueryParameters();
var requestedTheme = queryParameters.get(COLOR_THEME_QUERY_PARAM_NAME);
if (SHOW_THEME_SWITCH) {
// Some examples (i.e., button / dark) are pre-themed by their jinja template.
// if this is the case we don't modify the body class (it's already set); we just mark that theme as active.
var preExistingClassFromTemplate = SUPPORTED_THEMES.find((themeName) => body.classList.contains(convertThemeNameToClassName(themeName)));

body.appendChild(themes);
body.appendChild(controls);
if (preExistingClassFromTemplate) {
activeTheme = preExistingClassFromTemplate;
} else if (!requestedTheme) {
// No template-defined theme & no query-param-requested theme; fallback to default
selectColorTheme(DEFAULT_COLOR_THEME);
}

var toggle = document.querySelector('.js-baseline-toggle');
toggle.addEventListener('click', function (event) {
body.classList.toggle('u-baseline-grid');
});
if (requestedTheme) {
if (SUPPORTED_THEMES.includes(requestedTheme)) {
selectColorTheme(requestedTheme);
} else {
// Query param used to request a theme that is not supported
selectColorTheme(DEFAULT_COLOR_THEME);
}
}

var themeToggles = document.querySelector('.u-theme-toggle');
if (SUPPORTED_THEMES?.length > 1) {
var themeSwitcherControls = SUPPORTED_THEMES.map(
(themeName) =>
`<button id="${convertThemeNameToButtonIdentifier(themeName)}" class="p-segmented-control__button p-theme-toggle__button is-dense" role="button" aria-selected="${body.classList.contains(convertThemeNameToClassName(themeName))}" data-color-theme-name="${themeName}">${titleCase(themeName)}</button>`,
);
var themeSwitcherSegmentedControl = fragmentFromString(
`<div class="p-segmented-control u-theme-toggle"><div class="p-segmented-control__list">${themeSwitcherControls.join('')}</div></div>`,
);

if (!SHOW_THEME_SWITCH) {
themeToggles.classList.add('u-hide');
controls.appendChild(themeSwitcherSegmentedControl);
}
} else if (requestedTheme) {
setQueryParameter(COLOR_THEME_QUERY_PARAM_NAME, null);
}
var baselineGridControl = fragmentFromString(
'<div class="u-baseline-grid__toggle"><label class="p-switch"><input type="checkbox" class="p-switch__input js-baseline-toggle" /><span class="p-switch__slider"></span><span class="p-switch__label">Toggle baseline grid</span></label></div>',
);
controls.appendChild(baselineGridControl);

var darkTheme = document.querySelector('.js-dark-theme-toggle');
darkTheme.addEventListener('click', function (event) {
body.classList.add('is-dark');
body.classList.remove('is-paper');
body.classList.remove('is-light');
});
body.appendChild(controls);

var lightTheme = document.querySelector('.js-light-theme-toggle');
lightTheme.addEventListener('click', function (event) {
body.classList.add('is-light');
body.classList.remove('is-dark');
body.classList.remove('is-paper');
// Below code relies on the controls already existing in the DOM, so must come after `body.appendChild`.
var themeToggleButtons = document.querySelectorAll('.p-theme-toggle__button');
themeToggleButtons.forEach((themeToggleButton) => {
themeToggleButton.addEventListener('click', () => {
selectColorTheme(themeToggleButton.getAttribute('data-color-theme-name'));
});
});

var paperTheme = document.querySelector('.js-paper-theme-toggle');
paperTheme.addEventListener('click', function (event) {
body.classList.add('is-paper');
body.classList.remove('is-dark');
body.classList.remove('is-light');
var toggle = document.querySelector('.js-baseline-toggle');
toggle.addEventListener('click', function (event) {
body.classList.toggle('u-baseline-grid');
});
});
}
Expand Down
2 changes: 1 addition & 1 deletion webapp/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,4 +319,4 @@ def contribute_index():
document_template="/_layouts/docs_discourse.html",
url_prefix="/design",
)
discourse_docs.init_app(app)
discourse_docs.init_app(app)
Loading