Skip to content

Commit dcdced8

Browse files
Turbo87eth3lbert
andcommitted
Implement color scheme toggle
Co-authored-by: eth3lbert <[email protected]>
1 parent 0c924f3 commit dcdced8

13 files changed

+131
-2
lines changed

app/components/color-scheme-menu.hbs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<Dropdown local-class="dropdown" data-test-dark-mode-menu ...attributes as |dd|>
2+
<dd.Trigger local-class="trigger" data-test-dark-mode-toggle>
3+
{{svg-jar this.icon local-class="icon"}}
4+
</dd.Trigger>
5+
6+
<dd.Menu local-class="menu" as |menu|>
7+
{{#each this.colorSchemes as |colorScheme|}}
8+
<menu.Item>
9+
<button
10+
local-class="menu-button {{if (eq colorScheme.mode this.colorScheme.scheme) 'selected'}}"
11+
type="button"
12+
{{on 'click' (fn this.colorScheme.set colorScheme.mode)}}
13+
>
14+
{{svg-jar colorScheme.svg local-class="icon"}} {{colorScheme.mode}}
15+
</button>
16+
</menu.Item>
17+
{{/each}}
18+
</dd.Menu>
19+
</Dropdown>

app/components/color-scheme-menu.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { inject as service } from '@ember/service';
2+
import Component from '@glimmer/component';
3+
4+
export default class Header extends Component {
5+
/** @type {import("../services/dark-mode").default} */
6+
@service colorScheme;
7+
8+
colorSchemes = [
9+
{ mode: 'light', svg: 'sun' },
10+
{ mode: 'dark', svg: 'moon' },
11+
{ mode: 'system', svg: 'color-mode' },
12+
];
13+
14+
get icon() {
15+
return this.colorSchemes.find(({ mode }) => mode === this.colorScheme.scheme)?.svg;
16+
}
17+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
.dropdown {
2+
line-height: 1rem;
3+
}
4+
5+
.icon {
6+
width: 1.4em;
7+
height: auto;
8+
}
9+
10+
.trigger {
11+
background: none;
12+
border: 0;
13+
padding: 0;
14+
15+
/* hide arrow */
16+
> span {
17+
display: none !important;
18+
}
19+
}
20+
21+
.menu {
22+
right: 0;
23+
min-width: max-content;
24+
}
25+
26+
.menu-button {
27+
composes: button-reset from '../styles/shared/buttons.module.css';
28+
align-items: center;
29+
gap: var(--space-2xs);
30+
cursor: pointer;
31+
text-transform: capitalize;
32+
}
33+
34+
.selected {
35+
background: light-dark(#e6e6e6, #404040);
36+
}

app/components/header.hbs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
</div>
1515

1616
<nav local-class='nav'>
17+
<ColorSchemeMenu local-class="color-scheme-menu" />
18+
1719
<LinkTo @route="crates" @query={{hash letter=null page=1}} data-test-all-crates-link>
1820
Browse All Crates
1921
</LinkTo>
@@ -81,6 +83,8 @@
8183
</nav>
8284

8385
<div local-class='menu'>
86+
<ColorSchemeMenu local-class="color-scheme-menu" />
87+
8488
<Dropdown as |dd|>
8589
<dd.Trigger local-class="dropdown-button">
8690
Menu

app/components/header.module.css

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@
101101
.nav {
102102
grid-area: nav;
103103
display: flex;
104-
align-items: stretch;
104+
align-items: center;
105105
justify-self: end;
106106

107107
@media only screen and (max-width: 900px) {
@@ -115,14 +115,19 @@
115115
display: none;
116116

117117
@media only screen and (max-width: 900px) {
118-
display: block;
118+
display: flex;
119+
align-items: center;
119120
}
120121
}
121122

122123
.menu-item-with-separator {
123124
border-top: 1px solid var(--gray-border);
124125
}
125126

127+
.color-scheme-menu {
128+
margin-right: var(--space-xs);
129+
}
130+
126131
.login-button {
127132
composes: button-reset from '../styles/shared/buttons.module.css';
128133
display: inline-flex;

app/controllers/application.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import Controller from '@ember/controller';
22
import { inject as service } from '@ember/service';
33

44
export default class ApplicationController extends Controller {
5+
@service colorScheme;
56
@service design;
67
@service progress;
78
@service router;

app/helpers/set-color-scheme.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { helper } from '@ember/component/helper';
2+
3+
export default helper(function ([mode]) {
4+
if (mode) {
5+
window.document.documentElement.dataset.colorScheme = mode;
6+
} else {
7+
delete window.document.documentElement.dataset.colorScheme;
8+
}
9+
});

app/services/color-scheme.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { action } from '@ember/object';
2+
import Service from '@ember/service';
3+
import { tracked } from '@glimmer/tracking';
4+
5+
import * as localStorage from '../utils/local-storage';
6+
7+
const DEFAULT_SCHEME = 'light';
8+
const VALID_SCHEMES = new Set(['light', 'dark', 'system']);
9+
const LS_KEY = 'color-scheme';
10+
11+
export default class DesignService extends Service {
12+
@tracked _scheme = localStorage.getItem(LS_KEY);
13+
14+
get scheme() {
15+
return VALID_SCHEMES.has(this._scheme) ? this._scheme : DEFAULT_SCHEME;
16+
}
17+
18+
@action set(scheme) {
19+
this._scheme = scheme;
20+
localStorage.setItem(LS_KEY, scheme);
21+
}
22+
}

app/styles/application.module.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,14 @@
7777
color-scheme: light dark;
7878
}
7979

80+
[data-color-scheme="light"] {
81+
color-scheme: light;
82+
}
83+
84+
[data-color-scheme="dark"] {
85+
color-scheme: dark;
86+
}
87+
8088
[data-theme="new-design"] {
8189
--header-bg-color: var(--violet800);
8290
--main-bg: white;

app/templates/application.hbs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
{{page-title "crates.io: Rust Package Registry" separator=' - ' prepend=true}}
44
{{set-theme this.design.theme}}
5+
{{set-color-scheme this.colorScheme.scheme}}
56

67
<ProgressBar/>
78
<NotificationContainer @position="top-right"/>

public/assets/color-mode.svg

Lines changed: 1 addition & 0 deletions
Loading

public/assets/moon.svg

Lines changed: 3 additions & 0 deletions
Loading

public/assets/sun.svg

Lines changed: 3 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)