feat: 🎸 add initial color theme toggle UX
This commit is contained in:
9 files changed
+98
-4
No files matched your search
@@ -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 } 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
|
||||
@@ -62,6 +65,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}}>
|
||||
{{@label}}
|
||||
|
||||
@@ -15,6 +15,7 @@ Renders a form radiofield.
|
||||
@value="yes-agree"
|
||||
@selectedValue="yes-agree"
|
||||
@disabled={{false}}
|
||||
@changed={{fn}}
|
||||
/>
|
||||
```
|
||||
|
||||
|
||||
@@ -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,33 @@
|
||||
{{t 'actions.change-password'}}
|
||||
</dropdown.link>
|
||||
<dropdown.separator />
|
||||
|
||||
<dropdown.button
|
||||
{{on "click" (route-action "invalidateSession")}}
|
||||
>
|
||||
{{t 'actions.deauthenticate'}}
|
||||
</dropdown.button>
|
||||
|
||||
<dropdown.separator />
|
||||
|
||||
<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>
|
||||
|
||||
</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'));
|
||||
});
|
||||
});
|
||||
@@ -25,3 +25,7 @@ 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