Fix styling issues

This commit is contained in:
William Brawner 2022-08-17 02:01:18 +00:00
parent b31c306b0a
commit f01457dfba
10 changed files with 141 additions and 107 deletions

View file

@ -7,6 +7,7 @@ import './script/pages/app-home';
import './script/components/active-timer';
import './script/components/counter';
import './script/components/header';
import './script/components/icons/icon-add';
import './script/components/icons/icon-back';
import './script/components/icons/icon-forward';
import './script/components/icons/icon-navigation';

View file

@ -12,9 +12,6 @@ export class AppHeader extends LitElement {
static get styles() {
return css`
* {
--neutral-fill-stealth-rest: rgba(255, 255, 255, 0);
--neutral-fill-stealth-hover: rgba(255, 255, 255, 0.2);
--neutral-fill-stealth-active: rgba(255, 255, 255, 0.4);
user-select: none;
}

View file

@ -0,0 +1,20 @@
import { css, html, LitElement } from 'lit';
import { customElement } from 'lit/decorators.js';
// manually in-lining the svg until vite supports it
@customElement('icon-add')
export class AddIcon extends LitElement {
static get styles() {
return css`
svg {
display: block;
color: var(--foreground-color);
}
`;
}
render() {
return html`
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M10 2.5a.5.5 0 00-1 0V9H2.5a.5.5 0 000 1H9v6.5a.5.5 0 001 0V10h6.5a.5.5 0 000-1H10V2.5z"/></svg>
`;
}
}

View file

@ -1,5 +1,3 @@
// @ts-ignore
import Navigation from '@fluentui/svg-icons/icons/navigation_20_regular.svg';
import { css, html, LitElement } from 'lit';
import { customElement } from 'lit/decorators.js';

View file

@ -1,7 +1,5 @@
import { LitElement, css, html } from 'lit';
import { property, customElement, query } from 'lit/decorators.js';
// @ts-ignore
import Add from '@fluentui/svg-icons/icons/add_20_regular.svg';
import { IntervalTimer } from '../timer';
import { SelectTimerEvent } from '../select-timer-event';
@ -70,54 +68,16 @@ export class AppSidebar extends LitElement {
display: block;
}
pwa-install {
position: relative;
box-sizing: border-box;
outline: none;
font-family: var(--body-font);
font-size: var(--type-ramp-base-font-size);
line-height: var(--type-ramp-base-line-height);
font-weight: initial;
font-variation-settings: var(--type-ramp-base-font-variations);
height: calc((var(--base-height-multiplier) + var(--density)) * var(--design-unit) * 1px);
min-width: calc((var(--base-height-multiplier) + var(--density)) * var(--design-unit) * 1px);
color: var(--neutral-foreground-rest);
border-radius: calc(var(--control-corner-radius) * 1px);
fill: currentcolor;
cursor: pointer;
fluent-option {
--design-unit: 6;
}
pwa-install::part(openButton) {
background: var(--neutral-fill-stealth-rest);
border: calc(var(--stroke-width) * 1px) solid transparent;
flex-grow: 1;
box-sizing: border-box;
display: inline-flex;
justify-content: start;
align-items: center;
padding: 0 calc((10 + (var(--design-unit) * 2 * var(--density))) * 1px);
white-space: nowrap;
outline: none;
text-decoration: none;
color: inherit;
border-radius: inherit;
fill: inherit;
cursor: inherit;
font-family: inherit;
height: 100%;
}
pwa-install::part(openButton):hover {
background: var(--neutral-fill-stealth-hover);
}
fluent-button, pwa-install {
box-sizing: border-box;
height: 42px;
fluent-button {
--design-unit: 6;
padding: 5px;
}
fluent-button, button, pwa-install::part(openButton) {
fluent-button::part(control) {
justify-content: start;
width: 100%;
}
@ -129,18 +89,6 @@ export class AppSidebar extends LitElement {
constructor() {
super();
window.addEventListener('beforeinstallprompt', (event) => {
event.preventDefault();
});
}
updated() {
// Stupid hack to get the button to be left-aligned
const button: HTMLButtonElement | null | undefined = this.fButton?.shadowRoot?.querySelector('button');
if (button) {
button.setAttribute('style', 'justify-content: start;');
}
}
private toggleVisibility() {
@ -175,13 +123,15 @@ export class AppSidebar extends LitElement {
<fluent-option
@click=${() => this.selectTimer(timer.id!)}
selected=${timer.id === this.selectedTimer}
value=${timer.name}>${timer.name}</fluent-option>
value=${timer.name}>
${timer.name}<br />${timer.description || ''}
</fluent-option>
`;
})}
</fluent-listbox>
<fluent-divider></fluent-divider>
<fluent-button appearance="stealth" @click="${this.newTimer}">
<img slot="start" src="${Add}" aria-hidden="true" />
<icon-add slot="start"></icon-add>
New Timer
</fluent-button>
</div>

View file

@ -17,8 +17,10 @@ export class TimerFormDialog extends LitElement {
display: flex;
box-sizing: border-box;
flex-direction: column;
max-height: var(--dialog-height);
max-width: var(--dialog-width);
height: var(--dialog-height);
width: var(--dialog-width);
max-height: 100%;
max-width: 100%;
padding: 1em;
}
@ -32,9 +34,16 @@ export class TimerFormDialog extends LitElement {
flex-direction: column;
overflow-y: auto;
margin: 1em 0;
}
fluent-button {
margin: 1em 0;
::part(control) {
--dialog-height: 764px;
box-sizing: border-box;
max-height: 100vh;
max-width: 100vw;
display: flex;
flex-direction: column;
justify-content: center;
}
`;
}
@ -88,10 +97,7 @@ export class TimerFormDialog extends LitElement {
}
private async save() {
let id: string | undefined = this.timerId?.value;
if (!id) {
id = undefined;
}
const id: string = this.timerId?.value || '';
const name = this.timerName?.value;
if (!name) {
// TODO: Show errors in form
@ -99,7 +105,7 @@ export class TimerFormDialog extends LitElement {
return;
}
const timer = new IntervalTimer(name);
timer.id = this.timer?.id;
timer.id = Number.parseInt(id);
timer.description = this.timerDescription?.value;
timer.warmUp = parseDuration(this.timerWarmUp?.value);
timer.lowIntensity = parseDuration(this.timerLowIntensity?.value);
@ -115,14 +121,44 @@ export class TimerFormDialog extends LitElement {
this.toggleVisibility();
}
private async delete() {
const id = Number.parseInt(this.timerId?.value || '');
await this.timerService?.delete(id);
this.toggleVisibility();
}
private deleteButton() {
if (this.timer?.id) {
return html`
<fluent-button
appearance="outline"
tabindex="0"
@click=${this.delete}
style="margin-top: 1em;">Delete</fluent-button>
`;
}
}
private durationString(duration: number | undefined) {
if (!duration) {
return '';
} else {
return durationString(duration);
}
}
render() {
let body;
if (this.saving) {
return html`
<div class="dialog">
<p>Saving...</p>
</div>
`;
} else {
const title = this.timer?.id ? 'Edit Timer' : 'New Timer';
body = html`
<div class="dialog">
<div class="dialog ${this.timer?.id ? 'tall' : ''}">
<h2>${title}</h2>
<form @submit=${this.save}>
<input
@ -145,31 +181,31 @@ export class TimerFormDialog extends LitElement {
appearance="outline"
placeholder="05:00"
pattern="${this.durationPattern}"
.value=${durationString(this.timer?.warmUp)}>Warm Up</fluent-text-field>
.value=${this.durationString(this.timer?.warmUp)}>Warm Up</fluent-text-field>
<fluent-text-field
id="timer-low"
appearance="outline"
placeholder="00:30"
pattern="${this.durationPattern}"
.value=${durationString(this.timer?.lowIntensity)}>Low Intensity</fluent-text-field>
.value=${this.durationString(this.timer?.lowIntensity)}>Low Intensity</fluent-text-field>
<fluent-text-field
id="timer-hi"
appearance="outline"
placeholder="01:00"
pattern="${this.durationPattern}"
.value=${durationString(this.timer?.highIntensity)}>High Intensity</fluent-text-field>
.value=${this.durationString(this.timer?.highIntensity)}>High Intensity</fluent-text-field>
<fluent-text-field
id="timer-rest"
appearance="outline"
placeholder="01:00"
pattern="${this.durationPattern}"
.value=${durationString(this.timer?.rest)}>Rest</fluent-text-field>
.value=${this.durationString(this.timer?.rest)}>Rest</fluent-text-field>
<fluent-text-field
id="timer-cool"
appearance="outline"
placeholder="05:00"
pattern="${this.durationPattern}"
.value=${durationString(this.timer?.coolDown)}>Cooldown</fluent-text-field>
.value=${this.durationString(this.timer?.coolDown)}>Cooldown</fluent-text-field>
<fluent-text-field
id="timer-sets"
appearance="outline"
@ -180,14 +216,19 @@ export class TimerFormDialog extends LitElement {
appearance="outline"
placeholder="2"
.value=${this.timer?.rounds}>Rounds</fluent-text-field>
<fluent-button
appearance="accent"
tabindex="0"
@click=${this.save}
style="margin: 1em 0;">Save</fluent-button>
<fluent-button appearance="outline" tabindex="0" @click=${this.toggleVisibility}>Cancel</fluent-button>
${this.deleteButton()}
</form>
<fluent-button appearance="accent" tabindex="0" @click=${this.save}>Save</fluent-button>
<fluent-button appearance="outline" tabindex="0" @click=${this.toggleVisibility}>Cancel</fluent-button>
</div>
`;
}
return html`
<fluent-dialog ?hidden=${!this.visible} trap-focus modal>
<fluent-dialog ?hidden=${!this.visible} trap-focus modal class=${this.timer?.id ? 'tall' : ''}>
${body}
</fluent-dialog>
`;

View file

@ -23,6 +23,11 @@ export class AppHome extends LitElement {
active-timer {
flex-grow: 1;
}
p {
margin: 0;
text-align: center;
}
`;
}
@ -38,16 +43,6 @@ export class AppHome extends LitElement {
});
}
share() {
if ((navigator as any).share) {
(navigator as any).share({
title: 'PWABuilder pwa-starter',
text: 'Check out the PWABuilder pwa-starter!',
url: 'https://github.com/pwa-builder/pwa-starter',
});
}
}
private async closeEditor() {
this.editTimer = undefined;
this.timers = await this.timerService?.getAll() || [];
@ -56,6 +51,14 @@ export class AppHome extends LitElement {
}
}
private editButton() {
if (this.selectedTimer) {
return html`
<fluent-button appearance="stealth" slot="actions" @click=${() => this.editTimer = this.selectedTimer}>Edit</fluent-button>
`;
}
}
render() {
let body;
const timer = this.timers.filter(t => t.id === this.selectedTimer)[0] || this.timers[0];
@ -65,7 +68,14 @@ export class AppHome extends LitElement {
`;
} else {
body = html`
<p>Create a timer to begin</p>
<p>
Create a timer to begin<br />
<fluent-button
appearance="stealth"
@click=${() => this.editTimer = -1}>
New Timer
</fluent-button>
</p>
`;
}
@ -77,7 +87,7 @@ export class AppHome extends LitElement {
.selectedTimer=${this.selectedTimer}
@newtimer=${() => this.editTimer = -1}
@selecttimer=${(e: SelectTimerEvent) => this.selectedTimer = e.timerId}>
<fluent-button appearance="stealth" slot="actions" @click=${() => this.editTimer = timer.id}>Edit</fluent-button>
${this.editButton()}
</app-header>
${body}
<timer-form-dialog

View file

@ -5,7 +5,7 @@ import { IDBPDatabase } from 'idb';
export interface TimerService {
getAll(): Promise<IntervalTimer[]>;
save(timer: IntervalTimer): Promise<IntervalTimer>;
delete(timer: IntervalTimer): Promise<void>;
delete(timer: IntervalTimer | number): Promise<void>;
}
const dbName = 'interval-timer';
@ -24,6 +24,9 @@ class IDBTimerService implements TimerService {
}
async save(timer: IntervalTimer): Promise<IntervalTimer> {
if (!timer.id) {
delete timer.id;
}
const key = await this.db.put(storeName, timer);
return {
...timer,

View file

@ -29,7 +29,7 @@ export function className(phase: Phase) {
}
export function durationString(n: number | undefined): string {
if (!n) return '00:00';
if (typeof n !== 'number') return '';
let remainder = n;
let s = '';
if (remainder > 60) {

View file

@ -1,4 +1,3 @@
/*
This file is used for all of your global styles and CSS variables.
Check here https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties for more info on using CSS variables.
@ -9,7 +8,8 @@
--foreground-color: rgba(255, 255, 255, 1);
}
html, body {
html,
body {
font-family: var(--font-family);
padding: 0;
margin: 0;
@ -20,12 +20,14 @@ html, body {
transition: all 0.25s ease;
}
fluent-design-system-provider, app-index {
fluent-design-system-provider,
app-index {
height: 100%;
color: var(--foreground-color);
}
@media (prefers-color-scheme: dark) {
html,
body {
background: #181818;
@ -74,6 +76,7 @@ fluent-design-system-provider, app-index {
}
@media (prefers-color-scheme: light) {
html,
body {
background: white;
@ -82,7 +85,7 @@ fluent-design-system-provider, app-index {
fluent-design-system-provider {
--foreground-color: black;
--fill-color: #edebe9;
--fill-color: #f1f1f1;
--background-color: white;
--accent-base-color: #F2C812;
@ -92,14 +95,25 @@ fluent-design-system-provider, app-index {
--accent-fill-active: #F4D033;
--accent-fill-selected: #C7A50F;
--neutral-foreground-rest: #e5e5e5;
--accent-foreground-rest: var(--foreground-color);
--accent-stroke-control-rest: linear-gradient(#F5D447 90%, #D2AD0F 100%);
--accent-stroke-control-hover: linear-gradient(#F5D447 90%, #D2AD0F 100%);
--accent-stroke-control-active: #F5D447;
--accent-stroke-control-focus: linear-gradient(#F5D447 90%, #D2AD0F 100%);
--foreground-on-accent-rest: #000000;
--foreground-on-accent-hover: #000000;
--foreground-on-accent-active: #000000;
--neutral-foreground-rest: #2B2B2B;
--neutral-fill-input-rest: #e5e5e5;
--neutral-fill-input-hover: white;
--neutral-fill-stealth-rest: #e5e5e5;
--neutral-fill-stealth-rest: rgba(0, 0, 0, 0);
--neutral-fill-stealth-hover: rgba(0, 0, 0, 0.2);
--neutral-fill-stealth-active: rgba(0, 0, 0, 0.4);
--neutral-fill-rest: #5d5d5d;
--neutral-fill-input-active: #e5e5e5;
--timer-background-red: #FF0909;
--timer-background-green: #1cb91c;
--timer-background-yellow: #F2C812;
--timer-background-blue: #0091ff;
}
}
}