Skip to content

Commit 5db01a9

Browse files
authored
feat: add switch to manually change theme from light to dark (#291)
This requires `auto` default theme
2 parents 2dce587 + a9fd1a2 commit 5db01a9

File tree

5 files changed

+48
-6
lines changed

5 files changed

+48
-6
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"node-sass": "^8.0.0",
3535
"prettier": "^2.8.1",
3636
"riot": "^7.1.0",
37-
"riot-mui": "github:joxit/riot-5-mui#a9b0ce4",
37+
"riot-mui": "github:joxit/riot-5-mui#a97f2d3",
3838
"rollup": "^3.9.0",
3939
"rollup-plugin-app-utils": "^1.0.6",
4040
"rollup-plugin-copy": "^3.4.0",

src/components/docker-registry-ui.riot

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,19 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
101101
<li>
102102
<a href="https://github.com/Joxit/docker-registry-ui/blob/main/LICENSE">License AGPL-3.0</a>
103103
</li>
104+
<li if="{ props.theme === 'auto' }">
105+
<material-switch
106+
on-change="{ onThemeChange }"
107+
checked="{ state.themeSwitch }"
108+
track-selected-color="var(--accent-text)"
109+
outline-selected-color="var(--accent-text)"
110+
>
111+
<i slot="thumb-icon" class="material-icons" style="color: white; font-size: 0.75em">wb_sunny</i>
112+
<i slot="thumb-selected-icon" class="material-icons" style="color: #79747e; font-size: 0.75em">
113+
brightness_2
114+
</i>
115+
</material-switch>
116+
</li>
104117
</ul>
105118
</material-footer>
106119
</footer>
@@ -156,7 +169,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
156169
this.state.catalogElementsLimit = props.catalogElementsLimit || 100000;
157170
this.state.pullUrl = this.pullUrl(this.state.registryUrl, props.pullUrl);
158171
this.state.useControlCacheHeader = props.useControlCacheHeader;
159-
loadTheme(props, this.root.parentNode.style);
172+
const theme = loadTheme(props, this.root.parentNode.style);
173+
this.state.themeSwitch = theme === 'dark';
160174
},
161175
onServerChange(registryUrl) {
162176
this.update({
@@ -216,6 +230,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
216230
filter: value,
217231
});
218232
},
233+
onThemeChange(e) {
234+
const theme = e.target.checked ? 'dark' : 'light';
235+
loadTheme({ ...this.props, theme }, this.root.parentNode.style);
236+
this.update({ themeSwitch: e.target.checked });
237+
},
219238
baseRoute: '([^#]*?)/(\\?[^#]*?)?(#!)?(/?)',
220239
router,
221240
version,
@@ -245,5 +264,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
245264
material-footer .material-footer-logo {
246265
color: var(--footer-text);
247266
}
267+
268+
material-switch i {
269+
user-select: none;
270+
}
248271
</style>
249272
</docker-registry-ui>

src/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
MaterialDropdown,
1414
MaterialPopup,
1515
MaterialInput,
16+
MaterialSwitch,
1617
} from 'riot-mui';
1718

1819
import DockerRegistryUI from './components/docker-registry-ui.riot';
@@ -31,6 +32,7 @@ register('material-tabs', MaterialTabs);
3132
register('material-dropdown', MaterialDropdown);
3233
register('material-popup', MaterialPopup);
3334
register('material-input', MaterialInput);
35+
register('material-switch', MaterialSwitch);
3436

3537
const createApp = component(DockerRegistryUI);
3638
const tags = document.getElementsByTagName('docker-registry-ui');

src/scripts/theme.js

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ const DARK_THEME = {
2323
'footer-background': '#555',
2424
};
2525

26+
const LOCAL_STORAGE_THEME = 'registryUiTheme';
27+
2628
let THEME;
2729

2830
const normalizeKey = (k) =>
@@ -33,19 +35,30 @@ const normalizeKey = (k) =>
3335

3436
const preferDarkMode = ({ theme }) => {
3537
if (theme === 'auto') {
36-
if (typeof window.matchMedia === 'function') {
37-
const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)');
38-
return prefersDarkScheme && prefersDarkScheme.matches;
38+
switch (localStorage.getItem(LOCAL_STORAGE_THEME)) {
39+
case 'dark':
40+
return true;
41+
case 'light':
42+
return false;
43+
default:
44+
if (typeof window.matchMedia === 'function') {
45+
const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)');
46+
return prefersDarkScheme && prefersDarkScheme.matches;
47+
}
3948
}
4049
}
4150
return theme === 'dark';
4251
};
4352

4453
export const loadTheme = (props, style) => {
45-
THEME = preferDarkMode(props) ? DARK_THEME : LIGHT_THEME;
54+
const isDarkMode = preferDarkMode(props);
55+
THEME = isDarkMode ? { ...DARK_THEME } : { ...LIGHT_THEME };
4656
Object.entries(props)
4757
.filter(([k, v]) => v && /^theme[A-Z]/.test(k))
4858
.map(([k, v]) => [normalizeKey(k), v])
4959
.forEach(([k, v]) => (THEME[k] = v));
5060
Object.entries(THEME).forEach(([k, v]) => style.setProperty(`--${k}`, v));
61+
const theme = isDarkMode ? 'dark' : 'light';
62+
localStorage.setItem(LOCAL_STORAGE_THEME, theme);
63+
return theme;
5164
};

src/style.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
@import 'riot-mui/src/material-elements/material-dropdown/material-dropdown.scss';
2727
@import 'riot-mui/src/material-elements/material-popup/material-popup.scss';
2828
@import 'riot-mui/src/material-elements/material-input/material-input.scss';
29+
@import 'riot-mui/src/material-elements/material-switch/material-switch.scss';
2930

3031
@import './roboto.scss';
3132
@import './material-icons.scss';
@@ -340,6 +341,9 @@ main {
340341

341342
material-footer {
342343
padding: 0.5em 1em;
344+
li {
345+
align-self: center;
346+
}
343347
}
344348

345349
.copy-to-clipboard {

0 commit comments

Comments
 (0)