Further UI improvements

This commit is contained in:
0x1eef 2023-10-20 17:39:09 -03:00
parent 05e519c737
commit 7542e762fc
15 changed files with 189 additions and 182 deletions

View file

@ -1,5 +1,5 @@
$black: #454545;
$max-width: 475px;
$max-width: 728px;
[lang="en"] {
font-family: "Kanit Regular";
@ -26,7 +26,8 @@ body .root {
body .root .content {
margin: 0 auto;
width: $max-width;
width: 80%;
max-width: $max-width;
height: 100%;
@media screen and (max-width: $max-width) {
@ -59,7 +60,7 @@ body .root .content .row.dropdown-row {
body .root .content ul.body {
clear: both;
list-style-type: none;
height: 400px;
height: 90%;
padding: 0;
/* Height of 625px, or less */

View file

@ -0,0 +1,96 @@
.play.icon, .pause.icon {
width: 32px;
height: 22px;
g {
transform: translate(2px, 0);
}
}
.pause.icon g {
rect {
width: 15px;
height: 40px;
fill: #FFF;
}
rect:first-child {
transform: translate(-3px, 0);
}
}
.refresh.icon {
width: 16px;
height: 16px;
}
.stalled.icon {
display: inline-block;
position: relative;
left: 7px;
height: 4px;
div {
display: inline-block;
position: absolute;
left: 8px;
width: 6px;
animation: stalled 0.8s cubic-bezier(0, 0.5, 0.5, 1) infinite;
}
div:nth-child(1) {
left: 12px;
animation-delay: -0.24s;
}
div:nth-child(2) {
left: 20px;
animation-delay: -0.12s;
}
div:nth-child(3) {
left: 28px;
animation-delay: 0;
}
}
@keyframes stalled {
0% {
top: 4px;
height: 8px;
}
50%, 100% {
top: 8px;
height: 4px;
}
}
.content.theme ul.stream span.title {
.sound-on.icon, .sound-off.icon {
width: 24px;
height: 24px;
transform: translate(0, 4px);
}
}
.content.theme {
.footer .sound-on.icon, .footer .sound-off.icon {
width: 32px;
height: 30px;
g { transform: translate(32px,30px); }
}
}
.content.theme.ar {
ul.stream span.title {
.sound-on.icon, .sound-off.icon {
transform: rotate(180deg);
g {
transform: translate(0px, 10px);
}
}
}
.footer .sound-on.icon, .footer .sound-off.icon {
transform: rotate(180deg);
g {transform: translate(32px,3px); }
}
}

View file

@ -1,80 +0,0 @@
.shape {
display: flex;
align-items: center;
justify-content: center;
flex-direction: row;
width: 24px;
height: 24px;
border-radius: 5px;
background: #606850;
cursor: pointer;
}
.shape .play-shape {
position: relative;
left: 1px;
width: 12px;
height: 12px;
background: #FFF;
clip-path: polygon(0 0, 100% 50%, 0 100%);
}
.shape .pause-shape {
width: 3px;
height: 12px;
background: #FFF;
clip-path: stroke-box;
&:first-child {
position: relative;
right: 2px;
}
&:last-child {
position: relative;
left: 1.5px;
}
}
.loading {
display: inline-block;
position: relative;
width: 4px;
height: 4px;
right: 38px;
div {
display: inline-block;
position: absolute;
left: 8px;
width: 6px;
animation: loading 0.8s cubic-bezier(0, 0.5, 0.5, 1) infinite;
}
div:nth-child(1) {
left: 12px;
animation-delay: -0.24s;
}
div:nth-child(2) {
left: 20px;
animation-delay: -0.12s;
}
div:nth-child(3) {
left: 28px;
animation-delay: 0;
}
}
@keyframes loading {
0% {
top: 4px;
height: 8px;
}
50%, 100% {
top: 8px;
height: 4px;
}
}

View file

@ -1,6 +1,6 @@
@import "layout";
@import "components/Select";
@import "components/Shape";
@import "components/Icon";
.content .row.details {
direction: rtl;
@ -41,34 +41,18 @@
}
.content .row.footer {
height: 32px;
align-items: flex-end;
.timer {
display: flex;
justify-content: center;
flex-direction: column;
font-size: 65%;
justify-content: flex-end;
width: 40px;
font-size: 80%;
font-family: "Kanit Regular";
text-align: center;
width: 40px;
height: 32px;
font-weight: bold;
border-radius: 5px;
}
.shape {
width: 40px;
height: 32px;
}
.svg.sound-on, .svg.sound-off {
width: 32px;
height: 32px;
cursor: pointer;
g { transform: translate(16px, 16px); }
}
.shape.refresh {
height: 16px;
width: 16px;
}
}
@ -97,10 +81,6 @@
position: relative;
top: 2px;
}
.svg.sound-on, .svg.sound-off {
transform: rotate(180deg);
}
}
@import "themes/moon";

View file

@ -1,2 +1,2 @@
$green: #606850;
$white: #FFF;
$white-primary: #FFF;

View file

@ -8,7 +8,7 @@
.surah.id {
background: $green;
color: $white;
color: $white-primary;
border-radius: 5px;
padding: 3px;
}

View file

@ -13,7 +13,7 @@
.timer {
background-color: $green;
color: $white;
color: $white-primary;
}
.row .shape.refresh {

View file

@ -1,4 +1,4 @@
$gold: #ECB200;
$gold-light: lighten($gold, 10%);
$blue :darken(#e4eff8, 35%);
$white: #FFF;
$gold-primary: #ECB200;
$gold-secondary: lighten($gold-primary, 5%);
$blue-primary: darken(#e4eff8, 35%);
$white-primary: #FFF;

View file

@ -1,16 +1,11 @@
.root .content.theme.moon {
@import "colors";
.header .image {
background-image: url("/images/moon.svg");
background-size: cover;
}
.row.title {
color: $gold;
color: $gold-primary;
}
.row.dropdown-row .react-select {
color: $gold;
color: $gold-primary;
}
}

View file

@ -0,0 +1,31 @@
.play.icon {
fill: $blue-primary;
stroke: darken($blue-primary, 40%);
stroke-width: 2px;
}
.pause.icon {
background: unset;
rect {
fill: $blue-primary;
stroke: darken($blue-primary, 40%);
stroke-width: 1px;
}
}
.refresh.icon {
background: unset;
fill: $blue-primary;
}
.stalled.icon {
div { background: $gold-secondary; }
}
.sound-on.icon, .sound-off.icon {
polygon {
fill: $blue-primary;
stroke-width: 2;
}
}

View file

@ -7,21 +7,21 @@
ul.body.index a {
&:active, &:link, &:visited {
color: $blue;
color: $blue-primary;
}
.surah.id {
background: $gold-light;
color: $white;
background: $gold-secondary;
color: $white-primary;
border-radius: 5px;
padding: 3px;
border: 1px solid $blue;
border: 1px solid $blue-primary;
}
}
.row.surah.choose-random {
&:active, &:link, &:visited {
color: $blue;
color: $blue-primary;
text-decoration: none;
}
&:hover {

View file

@ -1,41 +1,21 @@
.root .content.theme.moon {
@import "themes/moon/colors";
@import "themes/moon/components/Icon";
.row.details {
color: $gold;
color: $gold-primary;
}
.row.footer .timer {
color: $blue-primary;
}
ul.body.stream {
li.ayah {
span.title {
color: $gold;
color: $gold-primary;
}
p { }
}
}
.row .timer {
color: $white;
background: $gold;
}
.row .shape {
background: $gold;
}
.row .shape.refresh {
background: unset;
fill: $gold;
}
.row .loading div {
background: $gold;
}
.svg.sound-on, .svg.sound-off {
polygon {
fill: $blue;
stroke-width: 2;
}
}
}

View file

@ -1,7 +1,7 @@
import url from "url";
import * as Quran from "lib/Quran";
import React, { useEffect, useMemo, useState } from "react";
import { SoundOnShape, SoundOffShape } from "components/Shape";
import { SoundOnIcon, SoundOffIcon } from "components/Icon";
type Props = {
recitation: Quran.Recitation;
@ -54,8 +54,8 @@ export function AudioControl({
return (
<>
{soundOn && <SoundOnShape onClick={turnOffSound} />}
{!soundOn && <SoundOffShape onClick={turnOnSound} />}
{soundOn && <SoundOnIcon onClick={turnOffSound} />}
{!soundOn && <SoundOffIcon onClick={turnOnSound} />}
</>
);
}

View file

@ -4,29 +4,33 @@ interface Props {
onClick: () => void;
}
export function PlayShape({ onClick }: Props) {
export function PlayIcon({ onClick }: Props) {
return (
<div className="shape" onClick={onClick}>
<div className="play-shape" />
</div>
<svg className="play icon" onClick={onClick} viewBox="0 0 48 48">
<g>
<path d="M10,6 L38,24 L10,42 Z" />
</g>
</svg>
);
}
export function PauseShape({ onClick }: Props) {
export function PauseIcon({ onClick }: Props) {
return (
<div className="shape" onClick={onClick}>
<div className="pause-shape" />
<div className="pause-shape" />
</div>
<svg className="icon pause" onClick={onClick} viewBox="0 0 48 48">
<g>
<rect x="7" y="6" />
<rect x="28" y="6" />
</g>
</svg>
);
}
export function SoundOnShape({ onClick }: Props) {
export function SoundOnIcon({ onClick }: Props) {
return (
<svg
viewBox="0 0 100 100"
preserveAspectRatio="xMidYMid meet"
className="svg sound-off"
className="sound-on icon"
onClick={onClick}
>
<g>
@ -57,12 +61,12 @@ export function SoundOnShape({ onClick }: Props) {
);
}
export function SoundOffShape({ onClick }: Props) {
export function SoundOffIcon({ onClick }: Props) {
return (
<svg
viewBox="0 0 100 100"
preserveAspectRatio="xMidYMid meet"
className="svg sound-off"
className="sound-off icon"
onClick={onClick}
>
<g>
@ -99,11 +103,11 @@ export function SoundOffShape({ onClick }: Props) {
);
}
export function RefreshShape({ onClick }: Props) {
export function RefreshIcon({ onClick }: Props) {
return (
<svg
onClick={onClick}
className="shape refresh"
className="refresh icon"
x="0px"
y="0px"
width="438.542px"
@ -145,9 +149,9 @@ export function RefreshShape({ onClick }: Props) {
);
}
export function LoadingShape() {
export function StalledIcon() {
return (
<div className="loading">
<div className="stalled icon">
<div />
<div />
<div />

View file

@ -8,7 +8,7 @@ import { SelectOption } from "components/Select";
import { ThemeSelect } from "components/ThemeSelect";
import { LanguageSelect } from "components/LanguageSelect";
import { AudioControl } from "components/AudioControl";
import { PlayShape, PauseShape, RefreshShape, LoadingShape } from "components/Shape";
import { PlayIcon, PauseIcon, RefreshIcon, StalledIcon } from "components/Icon";
import * as Quran from "lib/Quran";
import { i18n, TFunction } from "lib/i18n";
@ -86,10 +86,10 @@ function SurahStream({ node, recitations, locale, paused, t }: Props) {
)}
<div className={classNames({ "justify-end": endOfStream }, "row", "footer")}>
{readyToRender && isPaused && !endOfStream && (
<PlayShape onClick={() => setIsPaused(false)} />
<PlayIcon onClick={() => setIsPaused(false)} />
)}
{readyToRender && !isPaused && !endOfStream && (
<PauseShape onClick={() => setIsPaused(true)} />
<PauseIcon onClick={() => setIsPaused(true)} />
)}
{readyToRender && !endOfStream && (
<AudioControl
@ -114,11 +114,11 @@ function SurahStream({ node, recitations, locale, paused, t }: Props) {
isStalled={isStalled}
/>
)}
{readyToRender && endOfStream && <RefreshShape onClick={() => setStream([])} />}
{readyToRender && endOfStream && <RefreshIcon onClick={() => setStream([])} />}
</div>
{readyToRender && soundOn && isStalled && (
<div className="row spinner justify-end">
<LoadingShape />
<StalledIcon />
</div>
)}
</div>