Add theme toggler
This commit is contained in:
parent
0880d75397
commit
3532555313
11 changed files with 140 additions and 20 deletions
|
|
@ -8,12 +8,17 @@
|
|||
--color-gray-dark: 66 66 66;
|
||||
--color-gray: 97 97 97;
|
||||
--color-gray-light: 199 199 199;
|
||||
--color-gray-lightest: 209 209 209;
|
||||
--color-gray-lighter: 209 209 209;
|
||||
--color-gray-lightest: 245 245 245;
|
||||
}
|
||||
|
||||
body {
|
||||
@apply text-gray-dark;
|
||||
}
|
||||
|
||||
p {
|
||||
@apply mb-4;
|
||||
}
|
||||
}
|
||||
|
||||
.royal-table {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<div class="flex items-center -space-x-px" role="group" ...attributes>
|
||||
{{yield
|
||||
(hash
|
||||
button=(component "button" group=this onClick=this.buttonPressed)
|
||||
Button=(component "button" group=this)
|
||||
)
|
||||
}}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,27 @@
|
|||
import Component from '@glimmer/component';
|
||||
import { action } from '@ember/object';
|
||||
import { action, get } from '@ember/object';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
import { hbs } from 'ember-template-imports';
|
||||
import { Loading } from 'ember-mdi';
|
||||
import { on } from '@ember/modifier';
|
||||
import eq from '../helpers/eq';
|
||||
|
||||
export const commonClasses =
|
||||
'inline-flex items-center px-3 py-2 leading-4 text-sm cursor-pointer border hover:opacity-80 active:opacity-60 focus:outline-none text-black border-gray-dark';
|
||||
export const primaryStyleClasses = 'text-primary border-primary';
|
||||
export const sizes = {
|
||||
sm: 'text-sm py-0.5',
|
||||
md: 'px-3 py-2',
|
||||
lg: 'px-4 py-3',
|
||||
};
|
||||
|
||||
export const iconSizes = {
|
||||
sm: 18,
|
||||
md: 22,
|
||||
lg: 24,
|
||||
};
|
||||
|
||||
export const styles = {
|
||||
default: 'border rounded',
|
||||
primary: 'border rounded text-primary border-primary',
|
||||
};
|
||||
|
||||
export default class ButtonComponent extends Component {
|
||||
static template = hbs`
|
||||
|
|
@ -16,22 +29,20 @@ export default class ButtonComponent extends Component {
|
|||
disabled={{this.disabled}}
|
||||
type={{this.type}}
|
||||
class="
|
||||
{{commonClasses}}
|
||||
{{if (eq this.style 'primary') primaryStyleClasses}}
|
||||
{{if @group 'first:rounded-l-md last:rounded-r-md' 'rounded-md'}}
|
||||
inline-flex items-center justify-center
|
||||
{{get sizes this.size}}
|
||||
{{get styles this.style}}
|
||||
"
|
||||
...attributes
|
||||
{{on 'click' this.handleClick}}
|
||||
>
|
||||
{{#if this.isPending}}
|
||||
<Loading @spin={{true}} class="mx-1" />
|
||||
<Loading @spin={{true}} @size={{get iconSizes this.size}} />
|
||||
{{else if @icon}}
|
||||
<@icon class="mx-1" />
|
||||
<@icon @size={{get iconSizes this.size}} />
|
||||
{{/if}}
|
||||
{{#if this.text}}
|
||||
<span class="mx-1">
|
||||
{{this.text}}
|
||||
</span>
|
||||
{{this.text}}
|
||||
{{/if}}
|
||||
</button>
|
||||
`;
|
||||
|
|
@ -43,7 +54,7 @@ export default class ButtonComponent extends Component {
|
|||
}
|
||||
|
||||
get size() {
|
||||
return this.args.size ?? 'default';
|
||||
return this.args.size ?? 'md';
|
||||
}
|
||||
|
||||
get isActive() {
|
||||
|
|
|
|||
1
app/components/divider.hbs
Normal file
1
app/components/divider.hbs
Normal file
|
|
@ -0,0 +1 @@
|
|||
<div class="border-b my-4"/>
|
||||
13
app/components/theme-toggler.hbs
Normal file
13
app/components/theme-toggler.hbs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<div class='grid grid-cols-3 gap-1 p-1 rounded bg-gray-lightest'>
|
||||
{{#each this.themes as |item|}}
|
||||
{{#let (eq item.id this.theme) as |selected|}}
|
||||
<Button
|
||||
@text={{item.name}}
|
||||
@icon={{item.icon}}
|
||||
@onClick={{fn this.changeTheme item.id}}
|
||||
@size='sm'
|
||||
class='border-none {{if selected "bg-white shadow-sm"}}'
|
||||
/>
|
||||
{{/let}}
|
||||
{{/each}}
|
||||
</div>
|
||||
32
app/components/theme-toggler.js
Normal file
32
app/components/theme-toggler.js
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
import { action } from '@ember/object';
|
||||
import Component from '@glimmer/component';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { WhiteBalanceSunny, ThemeLightDark, WeatherNight } from 'ember-mdi';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
|
||||
export default class ThemeTogglerComponent extends Component {
|
||||
@service session;
|
||||
|
||||
@tracked theme;
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
|
||||
this.theme = document.documentElement.dataset.theme;
|
||||
}
|
||||
|
||||
get themes() {
|
||||
return [
|
||||
{ id: 'light', name: 'Light', icon: WhiteBalanceSunny },
|
||||
{ id: 'system', name: 'System', icon: ThemeLightDark },
|
||||
{ id: 'dark', name: 'Dark', icon: WeatherNight },
|
||||
];
|
||||
}
|
||||
|
||||
@action
|
||||
changeTheme(theme) {
|
||||
localStorage.setItem('theme', theme);
|
||||
this.theme = theme;
|
||||
document.documentElement.dataset.theme = theme;
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
{{content-for "head"}}
|
||||
|
||||
<link integrity="" rel="stylesheet" href="{{rootURL}}assets/vendor.css">
|
||||
<link integrity="" rel="stylesheet" href="{{rootURL}}assets/vendor.css" onload="localStorage&&localStorage.theme&&(document.documentElement.dataset.theme=localStorage.theme)">
|
||||
<link integrity="" rel="stylesheet" href="{{rootURL}}assets/meiliadmin.css">
|
||||
|
||||
{{content-for "head-footer"}}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
'flex items-center px-4 py-2 font-semibold text-lg text-gray-dark'
|
||||
as |classLink|
|
||||
}}
|
||||
<nav class='flex flex-col flex-1'>
|
||||
<nav class='flex flex-col flex-1 mb-4'>
|
||||
{{!-- <div class='px-4 py-2 text-sm text-gray'>Indexes</div>
|
||||
{{#each @model.results as |item|}}
|
||||
<LinkTo
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
Keys
|
||||
</LinkTo>
|
||||
|
||||
<div class="border-b my-4"></div>
|
||||
<Divider />
|
||||
|
||||
<a
|
||||
href='https://docs.meilisearch.com/'
|
||||
|
|
@ -56,15 +56,20 @@
|
|||
<Icons::Github class='fill-gray mr-2' />
|
||||
MeiliAdmin
|
||||
</a>
|
||||
|
||||
<Divider />
|
||||
|
||||
<button
|
||||
type='button'
|
||||
{{on 'click' this.invalidateSession}}
|
||||
class='{{classLink}} mt-auto'
|
||||
class={{classLink}}
|
||||
>
|
||||
<Icons::Logout class='fill-gray mr-2' />
|
||||
Logout
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
<ThemeToggler />
|
||||
{{/let}}
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,14 @@ module.exports = {
|
|||
darkMode: 'media',
|
||||
theme: {
|
||||
extend: {
|
||||
borderColor: (theme) => theme('colors.gray.lightest'),
|
||||
borderColor: (theme) => theme('colors.gray.lighter'),
|
||||
colors: {
|
||||
gray: {
|
||||
darkest: 'rgb(var(--color-gray-darkest) / <alpha-value>)',
|
||||
dark: 'rgb(var(--color-gray-dark) / <alpha-value>)',
|
||||
DEFAULT: 'rgb(var(--color-gray) / <alpha-value>)',
|
||||
light: 'rgb(var(--color-gray-light) / <alpha-value>)',
|
||||
lighter: 'rgb(var(--color-gray-lighter) / <alpha-value>)',
|
||||
lightest: 'rgb(var(--color-gray-lightest) / <alpha-value>)',
|
||||
},
|
||||
primary: {
|
||||
|
|
|
|||
26
tests/integration/components/divider-test.js
Normal file
26
tests/integration/components/divider-test.js
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'meiliadmin/tests/helpers';
|
||||
import { render } from '@ember/test-helpers';
|
||||
import { hbs } from 'ember-cli-htmlbars';
|
||||
|
||||
module('Integration | Component | divider', function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test('it renders', async function (assert) {
|
||||
// Set any properties with this.set('myProperty', 'value');
|
||||
// Handle any actions with this.set('myAction', function(val) { ... });
|
||||
|
||||
await render(hbs`<Divider />`);
|
||||
|
||||
assert.dom(this.element).hasText('');
|
||||
|
||||
// Template block usage:
|
||||
await render(hbs`
|
||||
<Divider>
|
||||
template block text
|
||||
</Divider>
|
||||
`);
|
||||
|
||||
assert.dom(this.element).hasText('template block text');
|
||||
});
|
||||
});
|
||||
26
tests/integration/components/theme-toggler-test.js
Normal file
26
tests/integration/components/theme-toggler-test.js
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'meiliadmin/tests/helpers';
|
||||
import { render } from '@ember/test-helpers';
|
||||
import { hbs } from 'ember-cli-htmlbars';
|
||||
|
||||
module('Integration | Component | theme-toggler', function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test('it renders', async function (assert) {
|
||||
// Set any properties with this.set('myProperty', 'value');
|
||||
// Handle any actions with this.set('myAction', function(val) { ... });
|
||||
|
||||
await render(hbs`<ThemeToggler />`);
|
||||
|
||||
assert.dom(this.element).hasText('');
|
||||
|
||||
// Template block usage:
|
||||
await render(hbs`
|
||||
<ThemeToggler>
|
||||
template block text
|
||||
</ThemeToggler>
|
||||
`);
|
||||
|
||||
assert.dom(this.element).hasText('template block text');
|
||||
});
|
||||
});
|
||||
Loading…
Reference in a new issue