Merge pull request #358 from hashicorp/feature-dark-mode-toggle
Feature dark mode toggle
This commit is contained in:
23 files changed
+334
-85
No files matched your search
@@ -28,6 +28,7 @@
|
||||
button=(component "rose/dropdown/button" style=this.style)
|
||||
item=(component "rose/anonymous" class="rose-dropdown-item")
|
||||
separator=(component "rose/anonymous" tagName="hr" class="rose-dropdown-separator")
|
||||
section=(component "rose/dropdown/section" style=this.style)
|
||||
)}}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -9,13 +9,17 @@ import { boolean } from '@storybook/addon-knobs';
|
||||
A simple dropdown component with support for links and buttons.
|
||||
|
||||
<Preview>
|
||||
<Story name="Basic Dropdown" height="5rem">{{
|
||||
<Story name="Basic Dropdown" height="7rem">{{
|
||||
template: hbs`
|
||||
<Rose::Dropdown @text="Choose One…" @icon="user-organization" @showCaret={{showCaret}} as |dropdown|>
|
||||
<dropdown.link @route="index">Menu item</dropdown.link>
|
||||
<dropdown.link @route="about">Menu item</dropdown.link>
|
||||
<dropdown.separator />
|
||||
<dropdown.button>Button menu item</dropdown.button>
|
||||
<dropdown.separator />
|
||||
<dropdown.section @title="Dropdown Section Title">
|
||||
<dropdown.link @route="index">Menu item</dropdown.link>
|
||||
</dropdown.section>
|
||||
</Rose::Dropdown>
|
||||
`,
|
||||
context: {
|
||||
@@ -65,6 +69,10 @@ A simple dropdown component with support for links and buttons.
|
||||
<dropdown.link @route="index">Menu item</dropdown.link>
|
||||
<dropdown.link @route="about">Menu item</dropdown.link>
|
||||
<dropdown.button>Button menu item</dropdown.button>
|
||||
<dropdown.separator />
|
||||
<dropdown.section @title="Dropdown Section Title">
|
||||
<dropdown.link @route="index">Menu item</dropdown.link>
|
||||
</dropdown.section>
|
||||
</Rose::Dropdown>
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<section class="rose-dropdown-section" aria-labelledby={{concat "dropdown-section-title-" this.id}}>
|
||||
{{#if @title}}
|
||||
<h2
|
||||
id={{concat "dropdown-section-title-" this.id}}
|
||||
class="rose-dropdown-section-title"
|
||||
>
|
||||
{{@title}}
|
||||
</h2>
|
||||
{{/if}}
|
||||
|
||||
{{yield}}
|
||||
</section>
|
||||
@@ -0,0 +1,14 @@
|
||||
import Component from '@glimmer/component';
|
||||
import { generateComponentID } from '../../../../utilities/component-auto-id';
|
||||
import { action } from '@ember/object';
|
||||
|
||||
export default class RoseDialogComponent extends Component {
|
||||
|
||||
// =attributes
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
id = generateComponentID();
|
||||
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
{{yield (hash
|
||||
radio=(component 'rose/form/radio/radio' name=@name selectedValue=@selectedValue disabled=@disabled)
|
||||
radio=(component 'rose/form/radio/radio' name=@name selectedValue=@selectedValue disabled=@disabled changed=@changed)
|
||||
)}}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Meta, Story, Preview } from '@storybook/addon-docs/blocks';
|
||||
import { hbs } from 'ember-cli-htmlbars';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import { text, boolean, select } from '@storybook/addon-knobs';
|
||||
|
||||
<Meta title="Rose|Form/Radio/Group" component="Form/Radio/Group" />
|
||||
@@ -13,6 +14,7 @@ Renders a form radiofield group.
|
||||
@disabled={{false}}
|
||||
@name={{name}}
|
||||
@selectedValue="disagree"
|
||||
@changed={{fn}}
|
||||
as |radioGroup|
|
||||
>
|
||||
<radioGroup.radio
|
||||
@@ -36,6 +38,7 @@ Renders a form radiofield group.
|
||||
@disabled={{disabled}}
|
||||
@name={{name}}
|
||||
@selectedValue={{selectedValue}}
|
||||
@changed={{changed}}
|
||||
as |radioGroup|
|
||||
>
|
||||
<radioGroup.radio
|
||||
@@ -73,6 +76,7 @@ Renders a form radiofield group.
|
||||
secondFieldValue: text('second value', 'maybe'),
|
||||
thirdFieldLabel: text('third label', 'Disagree'),
|
||||
thirdFieldValue: text('third value', 'disagree'),
|
||||
changed: action('changed')
|
||||
}
|
||||
}}</Story>
|
||||
</Preview>
|
||||
@@ -9,7 +9,8 @@
|
||||
@name={{@name}}
|
||||
@value={{@value}}
|
||||
@groupValue={{@selectedValue}}
|
||||
@disabled={{@disabled}}/>
|
||||
@disabled={{@disabled}}
|
||||
@changed={{@changed}} />
|
||||
|
||||
<label class="rose-form-radio-label" for={{this.id}}>
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ Renders a form radiofield.
|
||||
@value="yes-agree"
|
||||
@selectedValue="yes-agree"
|
||||
@disabled={{false}}
|
||||
@changed={{fn}}
|
||||
/>
|
||||
```
|
||||
|
||||
|
||||
@@ -6,6 +6,24 @@
|
||||
$xxxs: sizing.rems(xxxs); // 2
|
||||
|
||||
.rose-card-link {
|
||||
|
||||
--background-color-light: transparent;
|
||||
--background-color-dark: var(--ui-gray-subtler-6);
|
||||
|
||||
--background-color: var(--background-color-light);
|
||||
|
||||
.ember-application.rose-theme-light & {
|
||||
--background-color: var(--background-color-light);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
--background-color: var(--background-color-dark);
|
||||
}
|
||||
|
||||
.ember-application.rose-theme-dark & {
|
||||
--background-color: var(--background-color-dark);
|
||||
}
|
||||
|
||||
@include type.type(s);
|
||||
border: sizing.rems(xxxxs) solid var(--ui-gray-subtler-2);
|
||||
border-radius: sizing.rems(xxxs);
|
||||
@@ -15,10 +33,7 @@ $xxxs: sizing.rems(xxxs); // 2
|
||||
margin: 0 sizing.rems(m) sizing.rems(m) 0;
|
||||
box-shadow: 0 $xxxs $xxxs rgba(var(--stark-components), var(--opacity-4)),
|
||||
0 $xxxs $xxxs rgba(var(--stark-components), var(--opacity-4));
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
background-color: var(--ui-gray-subtler-6);
|
||||
}
|
||||
background-color: var(--background-color);
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
|
||||
@@ -3,10 +3,27 @@
|
||||
|
||||
$xs: sizing.rems(xs); // 8
|
||||
$xxs: sizing.rems(xxs); // 4
|
||||
$chevron: "data:image/svg+xml;utf-8,<svg viewBox='0 0 24 24' fill='%231b1f26' xmlns='http://www.w3.org/2000/svg'><path fill-rule='evenodd' clip-rule='evenodd' d='M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6-1.41-1.41z'></path></svg>";
|
||||
$chevronWhite: "data:image/svg+xml;utf-8,<svg viewBox='0 0 24 24' fill='%23ffffff' xmlns='http://www.w3.org/2000/svg'><path fill-rule='evenodd' clip-rule='evenodd' d='M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6-1.41-1.41z'></path></svg>";
|
||||
$chevron: url("data:image/svg+xml;utf-8,<svg viewBox='0 0 24 24' fill='%231b1f26' xmlns='http://www.w3.org/2000/svg'><path fill-rule='evenodd' clip-rule='evenodd' d='M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6-1.41-1.41z'></path></svg>");
|
||||
$chevronWhite: url("data:image/svg+xml;utf-8,<svg viewBox='0 0 24 24' fill='%23ffffff' xmlns='http://www.w3.org/2000/svg'><path fill-rule='evenodd' clip-rule='evenodd' d='M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6-1.41-1.41z'></path></svg>");
|
||||
|
||||
.rose-dropdown {
|
||||
--background-image-light: #{$chevron};
|
||||
--background-image-dark: #{$chevronWhite};
|
||||
|
||||
--background-image: var(--background-image-light);
|
||||
|
||||
.ember-application.rose-theme-light & {
|
||||
--background-image: var(--background-image-light);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
--background-image: var(--background-image-dark);
|
||||
}
|
||||
|
||||
.ember-application.rose-theme-dark & {
|
||||
--background-image: var(--background-image-dark);
|
||||
}
|
||||
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
|
||||
@@ -59,14 +76,10 @@ $chevronWhite: "data:image/svg+xml;utf-8,<svg viewBox='0 0 24 24' fill='%23fffff
|
||||
|
||||
&.show-caret {
|
||||
padding-right: sizing.rems(xl);
|
||||
background-image: url($chevron);
|
||||
background: var(--background-image);
|
||||
background-repeat: no-repeat;
|
||||
background-position: right sizing.rems(m) center;
|
||||
background-size: sizing.rems(m);
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
background-image: url($chevronWhite);
|
||||
}
|
||||
}
|
||||
|
||||
// Hide default twistie triangle
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
@import 'button';
|
||||
@import 'link';
|
||||
@import 'item';
|
||||
@import 'section';
|
||||
@@ -0,0 +1,13 @@
|
||||
@use '../../variables/sizing';
|
||||
@use '../../utilities/type';
|
||||
|
||||
.rose-dropdown-section {
|
||||
.rose-dropdown-section-title {
|
||||
@include type.type(s, bold);
|
||||
padding: 0 sizing.rems(s);
|
||||
margin: 0;
|
||||
$line-height: 36 / 14;
|
||||
line-height: $line-height;
|
||||
color: var(--ui-gray)
|
||||
}
|
||||
}
|
||||
@@ -9,15 +9,29 @@
|
||||
@import 'dropdown';
|
||||
|
||||
.rose-header {
|
||||
|
||||
--box-shadow-light: none;
|
||||
--box-shadow-dark: inset 0 -#{sizing.rems(xxxxs)} 0 var(--ui-border-subtler-1);
|
||||
|
||||
--box-shadow: var(--box-shadow-light);
|
||||
|
||||
.ember-application.rose-theme-light & {
|
||||
--box-shadow: var(--box-shadow-light);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
--box-shadow: var(--box-shadow-dark);
|
||||
}
|
||||
|
||||
.ember-application.rose-theme-dark & {
|
||||
--box-shadow: var(--box-shadow-dark);
|
||||
}
|
||||
|
||||
display: grid;
|
||||
grid-template-areas: 'brand nav utilities';
|
||||
grid-template-columns: 0.01fr auto 1fr;
|
||||
background: var(--black);
|
||||
box-shadow: inset 0 -#{sizing.rems(xxxxs)} 0 var(--ui-border-subtler-1);
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
box-shadow: none;
|
||||
}
|
||||
box-shadow: var(--box-shadow);
|
||||
}
|
||||
|
||||
@media (max-width: media.width(small)) {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
// Light Mode
|
||||
:root {
|
||||
@mixin light-mode {
|
||||
--opacity-5: 0.025;
|
||||
--opacity-4: 0.05;
|
||||
--opacity-3: 0.1;
|
||||
@@ -15,12 +15,26 @@
|
||||
// Dark Mode
|
||||
// Subtler opacities look better in dark mode, so these are halved compared to
|
||||
// light mode.
|
||||
@mixin dark-mode {
|
||||
--opacity-5: 0.0125;
|
||||
--opacity-4: 0.0125;
|
||||
--opacity-3: 0.025;
|
||||
--opacity-2: 0.025;
|
||||
--opacity-1: 0.125;
|
||||
}
|
||||
|
||||
// Light mode is the default, hence it is applied to `html` by default
|
||||
.ember-application,
|
||||
.ember-application.rose-theme-light {
|
||||
@include light-mode;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--opacity-5: 0.0125;
|
||||
--opacity-4: 0.0125;
|
||||
--opacity-3: 0.025;
|
||||
--opacity-2: 0.025;
|
||||
--opacity-1: 0.125;
|
||||
.ember-application {
|
||||
@include dark-mode;
|
||||
}
|
||||
}
|
||||
|
||||
.ember-application.rose-theme-dark {
|
||||
@include dark-mode;
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
// Light Mode
|
||||
:root {
|
||||
@mixin light-mode {
|
||||
// absolutes
|
||||
--white: #{color(white)};
|
||||
--black: #{color(black)};
|
||||
@@ -80,62 +80,76 @@
|
||||
}
|
||||
|
||||
// Dark Mode
|
||||
@mixin dark-mode {
|
||||
// poles
|
||||
--subtle: var(--black);
|
||||
--stark: #{color(ui-gray, 100)};
|
||||
--stark-components: 255, 255, 255;
|
||||
|
||||
// theme colors
|
||||
--info-subtler-3: #{color(blue, 800)};
|
||||
--info-subtler-2: #{color(blue, 700)};
|
||||
--info-subtler-1: #{color(blue, 600)};
|
||||
--info: #{color(blue)};
|
||||
--info-starker-1: #{color(blue, 300)};
|
||||
--info-starker-2: #{color(blue, 200)};
|
||||
|
||||
--alert-subtler-2: #{color(orange, 900)};
|
||||
--alert-subtler-1: #{color(orange, 800)};
|
||||
--alert: #{color(orange)};
|
||||
--alert-starker-1: #{color(orange, 200)};
|
||||
|
||||
--warning-subtler-2: #{color(yellow, 900)};
|
||||
--warning-subtler-1: #{color(yellow, 800)};
|
||||
--warning: #{color(yellow)};
|
||||
--warning-starker-1: #{color(yellow, 200)};
|
||||
|
||||
--failure-subtler-2: #{color(red, 900)};
|
||||
--failure-subtler-1: #{color(red, 800)};
|
||||
--failure: #{color(red, 300)};
|
||||
--failure-starker-1: #{color(red, 200)};
|
||||
|
||||
--success-subtler-2: #{color(green, 900)};
|
||||
--success-subtler-1: #{color(green, 800)};
|
||||
--success: #{color(green, 700)};
|
||||
--success-starker-1: #{color(green, 400)};
|
||||
|
||||
--action-subtler-2: #{darken(color(blue, 900), 10%)};
|
||||
--action-subtler-1h: #{darken(color(blue, 900), 5%)};
|
||||
--action-subtler-1: #{color(blue, 800)};
|
||||
--action: #{color(blue, 400)};
|
||||
--action-starker-1: #{color(blue, 200)};
|
||||
|
||||
--ui-border-subtler-1: #{color(ui-gray, 800)};
|
||||
--ui-border: #{color(ui-gray, 700)};
|
||||
|
||||
--ui-gray-subtler-6: #{color(ui-gray, 900)};
|
||||
--ui-gray-subtler-5: #{color(ui-gray, 800)};
|
||||
--ui-gray-subtler-4: #{color(ui-gray, 700)};
|
||||
--ui-gray-subtler-3: #{color(ui-gray, 600)};
|
||||
--ui-gray-subtler-2: #{color(ui-gray, 500)};
|
||||
--ui-gray-subtler-1: #{color(ui-gray, 400)};
|
||||
--ui-gray: #{color(ui-gray, 300)};
|
||||
--ui-gray-starker-1: #{color(ui-gray, 200)};
|
||||
--ui-gray-starker-2: #{color(ui-gray, 100)};
|
||||
--ui-gray-starker-3: #{color(ui-gray, 050)};
|
||||
--ui-gray-starker-4: #{color(ui-gray, 010)};
|
||||
|
||||
--ui-header-subtler: #{color(ui-cool-gray, 100)};
|
||||
}
|
||||
|
||||
// Light mode is the default, hence it is applied to `html` by default
|
||||
.ember-application,
|
||||
.ember-application.rose-theme-light {
|
||||
@include light-mode;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
// poles
|
||||
--subtle: var(--black);
|
||||
--stark: #{color(ui-gray, 100)};
|
||||
--stark-components: 255, 255, 255;
|
||||
|
||||
// theme colors
|
||||
--info-subtler-3: #{color(blue, 800)};
|
||||
--info-subtler-2: #{color(blue, 700)};
|
||||
--info-subtler-1: #{color(blue, 600)};
|
||||
--info: #{color(blue)};
|
||||
--info-starker-1: #{color(blue, 300)};
|
||||
--info-starker-2: #{color(blue, 200)};
|
||||
|
||||
--alert-subtler-2: #{color(orange, 900)};
|
||||
--alert-subtler-1: #{color(orange, 800)};
|
||||
--alert: #{color(orange)};
|
||||
--alert-starker-1: #{color(orange, 200)};
|
||||
|
||||
--warning-subtler-2: #{color(yellow, 900)};
|
||||
--warning-subtler-1: #{color(yellow, 800)};
|
||||
--warning: #{color(yellow)};
|
||||
--warning-starker-1: #{color(yellow, 200)};
|
||||
|
||||
--failure-subtler-2: #{color(red, 900)};
|
||||
--failure-subtler-1: #{color(red, 800)};
|
||||
--failure: #{color(red, 300)};
|
||||
--failure-starker-1: #{color(red, 200)};
|
||||
|
||||
--success-subtler-2: #{color(green, 900)};
|
||||
--success-subtler-1: #{color(green, 800)};
|
||||
--success: #{color(green, 700)};
|
||||
--success-starker-1: #{color(green, 400)};
|
||||
|
||||
--action-subtler-2: #{darken(color(blue, 900), 10%)};
|
||||
--action-subtler-1h: #{darken(color(blue, 900), 5%)};
|
||||
--action-subtler-1: #{color(blue, 800)};
|
||||
--action: #{color(blue, 400)};
|
||||
--action-starker-1: #{color(blue, 200)};
|
||||
|
||||
--ui-border-subtler-1: #{color(ui-gray, 800)};
|
||||
--ui-border: #{color(ui-gray, 700)};
|
||||
|
||||
--ui-gray-subtler-6: #{color(ui-gray, 900)};
|
||||
--ui-gray-subtler-5: #{color(ui-gray, 800)};
|
||||
--ui-gray-subtler-4: #{color(ui-gray, 700)};
|
||||
--ui-gray-subtler-3: #{color(ui-gray, 600)};
|
||||
--ui-gray-subtler-2: #{color(ui-gray, 500)};
|
||||
--ui-gray-subtler-1: #{color(ui-gray, 400)};
|
||||
--ui-gray: #{color(ui-gray, 300)};
|
||||
--ui-gray-starker-1: #{color(ui-gray, 200)};
|
||||
--ui-gray-starker-2: #{color(ui-gray, 100)};
|
||||
--ui-gray-starker-3: #{color(ui-gray, 050)};
|
||||
--ui-gray-starker-4: #{color(ui-gray, 010)};
|
||||
|
||||
--ui-header-subtler: #{color(ui-cool-gray, 100)};
|
||||
.ember-application {
|
||||
@include dark-mode;
|
||||
}
|
||||
}
|
||||
|
||||
.ember-application.rose-theme-dark {
|
||||
@include dark-mode;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from 'rose/components/rose/dropdown/section';
|
||||
@@ -35,6 +35,11 @@
|
||||
|
||||
<dropdown.button>Button menu item</dropdown.button>
|
||||
<dropdown.button @style="danger">Button - danger</dropdown.button>
|
||||
<dropdown.separator />
|
||||
|
||||
<dropdown.section @title="Dropdown Section Title">
|
||||
<dropdown.link @route="index">Menu item</dropdown.link>
|
||||
</dropdown.section>
|
||||
</Rose::Dropdown>
|
||||
|
||||
<Rose::Dropdown @showCaret={{false}} @icon="more-horizontal" as |dropdown|>
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'ember-qunit';
|
||||
import { render, find } from '@ember/test-helpers';
|
||||
import { hbs } from 'ember-cli-htmlbars';
|
||||
|
||||
module('Integration | Component | rose/dropdown/section', function(hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test('it renders', async function(assert) {
|
||||
await render(hbs`
|
||||
<Rose::Dropdown::Section>
|
||||
template block text
|
||||
</Rose::Dropdown::Section>
|
||||
`);
|
||||
assert.ok(find('.rose-dropdown-section'));
|
||||
assert.equal(this.element.textContent.trim(), 'template block text');
|
||||
});
|
||||
|
||||
test('it renders with optional @title', async function(assert) {
|
||||
await render(hbs`
|
||||
<Rose::Dropdown::Section @title="Section Title">
|
||||
template block text
|
||||
</Rose::Dropdown::Section>
|
||||
`);
|
||||
assert.equal(find('.rose-dropdown-section-title').textContent.trim(), 'Section Title');
|
||||
});
|
||||
});
|
||||
@@ -52,9 +52,15 @@ module('Integration | Component | rose/form/radio/group', function (hooks) {
|
||||
assert.equal(findAll('[type="radio"]')[1].checked, false);
|
||||
});
|
||||
|
||||
test('it reflects active radiofield value in @selectedValue', async function (assert) {
|
||||
test('it reflects active radiofield value in @selectedValue and triggers a @changed function', async function (assert) {
|
||||
assert.expect(5);
|
||||
this.changed = (value) => assert.ok(value);
|
||||
await render(hbs`
|
||||
<Rose::Form::Radio::Group @name="bird" @selectedValue={{this.selectedValue}} as |radioGroup|>
|
||||
<Rose::Form::Radio::Group
|
||||
@name="bird"
|
||||
@selectedValue={{this.selectedValue}}
|
||||
@changed={{this.changed}}
|
||||
as |radioGroup|>
|
||||
<radioGroup.radio
|
||||
@name="bird"
|
||||
@label="Pegion"
|
||||
|
||||
@@ -26,6 +26,11 @@ export default class ApplicationRoute extends Route.extend(
|
||||
|
||||
// =methods
|
||||
|
||||
beforeModel() {
|
||||
const theme = this.session.get('data.theme');
|
||||
this.toggleTheme(theme);
|
||||
}
|
||||
|
||||
/**
|
||||
* After becoming authenticated, does nothing. This overrides the default
|
||||
* behavior of the ApplicationRouteMixin, which is to redirect after auth.
|
||||
@@ -115,4 +120,29 @@ export default class ApplicationRoute extends Route.extend(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the specified color theme to the root ember element.
|
||||
* @param {string} theme - "light", "dark", or nullish (system default)
|
||||
*/
|
||||
@action
|
||||
toggleTheme(theme) {
|
||||
const rootElementSelector = getOwner(this).rootElement;
|
||||
const rootEl = getOwner(this).lookup('service:-document')
|
||||
.querySelector(rootElementSelector);
|
||||
this.session.set('data.theme', theme);
|
||||
switch (theme) {
|
||||
case 'light':
|
||||
rootEl.classList.add('rose-theme-light');
|
||||
rootEl.classList.remove('rose-theme-dark');
|
||||
break;
|
||||
case 'dark':
|
||||
rootEl.classList.add('rose-theme-dark');
|
||||
rootEl.classList.remove('rose-theme-light');
|
||||
break;
|
||||
default:
|
||||
rootEl.classList.remove('rose-theme-dark');
|
||||
rootEl.classList.remove('rose-theme-light');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,11 +23,35 @@
|
||||
{{t 'actions.change-password'}}
|
||||
</dropdown.link>
|
||||
<dropdown.separator />
|
||||
|
||||
<dropdown.button
|
||||
{{on "click" (route-action "invalidateSession")}}
|
||||
>
|
||||
{{t 'actions.deauthenticate'}}
|
||||
</dropdown.button>
|
||||
|
||||
<dropdown.separator />
|
||||
|
||||
<dropdown.section @title={{t "titles.toggle-color-theme"}}>
|
||||
<Rose::Form as |form|>
|
||||
<form.radioGroup
|
||||
@name="theme"
|
||||
@selectedValue={{this.session.data.theme}}
|
||||
@changed={{route-action "toggleTheme"}}
|
||||
as |radioGroup|>
|
||||
<dropdown.item>
|
||||
<radioGroup.radio @label={{t "themes.system"}} />
|
||||
</dropdown.item>
|
||||
<dropdown.item>
|
||||
<radioGroup.radio @label={{t "themes.light"}} @value="light" />
|
||||
</dropdown.item>
|
||||
<dropdown.item>
|
||||
<radioGroup.radio @label={{t "themes.dark"}} @value="dark" />
|
||||
</dropdown.item>
|
||||
</form.radioGroup>
|
||||
</Rose::Form>
|
||||
</dropdown.section>
|
||||
|
||||
</utilities.dropdown>
|
||||
</header.utilities>
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
click,
|
||||
find,
|
||||
findAll,
|
||||
getRootElement
|
||||
//setupOnerror,
|
||||
} from '@ember/test-helpers';
|
||||
import { setupApplicationTest } from 'ember-qunit';
|
||||
@@ -315,4 +316,29 @@ module('Acceptance | authentication', function (hooks) {
|
||||
'Session is unauthenticated, after encountering 401'
|
||||
);
|
||||
});
|
||||
|
||||
test('color theme is applied from session data', async function (assert) {
|
||||
assert.expect(12);
|
||||
authenticateSession({ scope: { id: globalScope.id, type: globalScope.type } });
|
||||
// system default
|
||||
await visit(orgsURL);
|
||||
assert.notOk(currentSession().get('data.theme'));
|
||||
assert.notOk(getRootElement().classList.contains('rose-theme-light'));
|
||||
assert.notOk(getRootElement().classList.contains('rose-theme-dark'));
|
||||
// toggle light mode
|
||||
await click('[name="theme"][value="light"]');
|
||||
assert.equal(currentSession().get('data.theme'), 'light');
|
||||
assert.ok(getRootElement().classList.contains('rose-theme-light'));
|
||||
assert.notOk(getRootElement().classList.contains('rose-theme-dark'));
|
||||
// toggle dark mode
|
||||
await click('[name="theme"][value="dark"]');
|
||||
assert.equal(currentSession().get('data.theme'), 'dark');
|
||||
assert.notOk(getRootElement().classList.contains('rose-theme-light'));
|
||||
assert.ok(getRootElement().classList.contains('rose-theme-dark'));
|
||||
// toggle system default
|
||||
await click('[name="theme"][value=""]');
|
||||
assert.notOk(currentSession().get('data.theme'));
|
||||
assert.notOk(getRootElement().classList.contains('rose-theme-light'));
|
||||
assert.notOk(getRootElement().classList.contains('rose-theme-dark'));
|
||||
});
|
||||
});
|
||||
@@ -19,9 +19,14 @@ titles:
|
||||
actions: Actions
|
||||
documentation: Documentation
|
||||
abandon-confirm: Discard unsaved changes?
|
||||
toggle-color-theme: Toggle Color Theme
|
||||
descriptions:
|
||||
empty-set: There are no items to display yet. You may be able to add items or try back later.
|
||||
questions:
|
||||
delete-confirm: Are you sure you want to delete this resource?
|
||||
remove-confirm: Are you sure you want to remove this association?
|
||||
abandon-confirm: Are you sure you want to navigate away? Your unsaved changes will be lost.
|
||||
themes:
|
||||
system: System Default
|
||||
light: Light
|
||||
dark: Dark
|
||||
Reference in new issue
Block a user