mirror of
https://github.com/schlagmichdoch/PairDrop.git
synced 2025-04-20 15:06:15 -04:00
Make overflowing icons expandable via caret button and fix header btn opacity
This commit is contained in:
parent
e7031cea90
commit
b5535c7ace
5 changed files with 173 additions and 98 deletions
|
@ -40,8 +40,7 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body translate="no">
|
<body translate="no">
|
||||||
<header class="row-reverse opacity-0">
|
<header class="row-reverse wrap opacity-0">
|
||||||
<div class="row-reverse">
|
|
||||||
<a href="#about" class="icon-button" data-i18n-key="header.about" data-i18n-attrs="title aria-label">
|
<a href="#about" class="icon-button" data-i18n-key="header.about" data-i18n-attrs="title aria-label">
|
||||||
<svg class="icon">
|
<svg class="icon">
|
||||||
<use xlink:href="#info-outline"></use>
|
<use xlink:href="#info-outline"></use>
|
||||||
|
@ -96,18 +95,21 @@
|
||||||
<use xlink:href="#public-room-icon"></use>
|
<use xlink:href="#public-room-icon"></use>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="expand" class="icon-button" data-i18n-key="header.expand" data-i18n-attrs="title" hidden>
|
||||||
|
<svg class="icon">
|
||||||
|
<use xlink:href="#caret"></use>
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<!-- Center -->
|
<!-- Center -->
|
||||||
<div id="center" class="opacity-0">
|
<div id="center" class="opacity-0">
|
||||||
<!-- Peers -->
|
<!-- Peers -->
|
||||||
<div class="x-peers-filler"></div>
|
<x-peers class="center grow"></x-peers>
|
||||||
<x-peers class="center"></x-peers>
|
<x-no-peers class="center grow fade-in no-animation-on-load" data-i18n-key="instructions.no-peers" data-i18n-attrs="data-drop-bg">
|
||||||
<x-no-peers class="no-animation-on-load" data-i18n-key="instructions.no-peers" data-i18n-attrs="data-drop-bg">
|
|
||||||
<h2 data-i18n-key="instructions.no-peers-title" data-i18n-attrs="text"></h2>
|
<h2 data-i18n-key="instructions.no-peers-title" data-i18n-attrs="text"></h2>
|
||||||
<div data-i18n-key="instructions.no-peers-subtitle" data-i18n-attrs="text"></div>
|
<div data-i18n-key="instructions.no-peers-subtitle" data-i18n-attrs="text"></div>
|
||||||
</x-no-peers>
|
</x-no-peers>
|
||||||
<x-instructions data-i18n-key="instructions.x-instructions" data-i18n-attrs="desktop mobile data-drop-peer data-drop-bg"></x-instructions>
|
<x-instructions class="fade-in" data-i18n-key="instructions.x-instructions" data-i18n-attrs="desktop mobile data-drop-peer data-drop-bg"></x-instructions>
|
||||||
<div class="share-panel panel column" hidden>
|
<div class="share-panel panel column" hidden>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="thumb center">
|
<div class="thumb center">
|
||||||
|
@ -675,6 +677,9 @@
|
||||||
<!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.-->
|
<!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.-->
|
||||||
<path d="M320 464c8.8 0 16-7.2 16-16V160H256c-17.7 0-32-14.3-32-32V48H64c-8.8 0-16 7.2-16 16V448c0 8.8 7.2 16 16 16H320zM0 64C0 28.7 28.7 0 64 0H229.5c17 0 33.3 6.7 45.3 18.7l90.5 90.5c12 12 18.7 28.3 18.7 45.3V448c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V64z"/>
|
<path d="M320 464c8.8 0 16-7.2 16-16V160H256c-17.7 0-32-14.3-32-32V48H64c-8.8 0-16 7.2-16 16V448c0 8.8 7.2 16 16 16H320zM0 64C0 28.7 28.7 0 64 0H229.5c17 0 33.3 6.7 45.3 18.7l90.5 90.5c12 12 18.7 28.3 18.7 45.3V448c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V64z"/>
|
||||||
</symbol>
|
</symbol>
|
||||||
|
<symbol id="caret" viewBox="0 0 320 512">
|
||||||
|
<!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.--><path d="M137.4 374.6c12.5 12.5 32.8 12.5 45.3 0l128-128c9.2-9.2 11.9-22.9 6.9-34.9s-16.6-19.8-29.6-19.8L32 192c-12.9 0-24.6 7.8-29.6 19.8s-2.2 25.7 6.9 34.9l128 128z"/>
|
||||||
|
</symbol>
|
||||||
|
|
||||||
</svg>
|
</svg>
|
||||||
<!-- Scripts -->
|
<!-- Scripts -->
|
||||||
|
|
|
@ -2,7 +2,7 @@ class Localization {
|
||||||
constructor() {
|
constructor() {
|
||||||
Localization.defaultLocale = "en";
|
Localization.defaultLocale = "en";
|
||||||
Localization.supportedLocales = ["ar", "de", "en", "es", "fr", "id", "it", "ja", "nb", "nl", "ro", "ru", "tr", "zh-CN"];
|
Localization.supportedLocales = ["ar", "de", "en", "es", "fr", "id", "it", "ja", "nb", "nl", "ro", "ru", "tr", "zh-CN"];
|
||||||
Localization.supportedLocalesRTL = ["ar"];
|
Localization.supportedLocalesRtl = ["ar"];
|
||||||
|
|
||||||
Localization.translations = {};
|
Localization.translations = {};
|
||||||
Localization.defaultTranslations = {};
|
Localization.defaultTranslations = {};
|
||||||
|
@ -20,8 +20,12 @@ class Localization {
|
||||||
return Localization.supportedLocales.indexOf(locale) > -1;
|
return Localization.supportedLocales.indexOf(locale) > -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static isRTLLanguage(locale) {
|
static isRtlLanguage(locale) {
|
||||||
return Localization.supportedLocalesRTL.indexOf(locale) > -1;
|
return Localization.supportedLocalesRtl.indexOf(locale) > -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static isCurrentLocaleRtl() {
|
||||||
|
return Localization.isRtlLanguage(Localization.locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getSupportedOrDefault(locales) {
|
static getSupportedOrDefault(locales) {
|
||||||
|
@ -46,7 +50,7 @@ class Localization {
|
||||||
|
|
||||||
const htmlRootNode = document.querySelector('html');
|
const htmlRootNode = document.querySelector('html');
|
||||||
|
|
||||||
if (Localization.isRTLLanguage(locale)) {
|
if (Localization.isRtlLanguage(locale)) {
|
||||||
htmlRootNode.setAttribute('dir', 'rtl');
|
htmlRootNode.setAttribute('dir', 'rtl');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
class PairDrop {
|
class PairDrop {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.$headerNotificationButton = $('notification');
|
this.$headerNotificationBtn = $('notification');
|
||||||
this.$headerEditPairedDevicesBtn = $('edit-paired-devices');
|
this.$headerEditPairedDevicesBtn = $('edit-paired-devices');
|
||||||
this.$footerPairedDevicesBadge = $$('.discovery-wrapper .badge-room-secret');
|
this.$footerPairedDevicesBadge = $$('.discovery-wrapper .badge-room-secret');
|
||||||
this.$headerInstallBtn = $('install');
|
this.$headerInstallBtn = $('install');
|
||||||
|
@ -46,7 +46,8 @@ class PairDrop {
|
||||||
await this.footerUI.showLoading();
|
await this.footerUI.showLoading();
|
||||||
|
|
||||||
// Evaluate css shifting UI elements and fade in UI elements
|
// Evaluate css shifting UI elements and fade in UI elements
|
||||||
await this.evaluateUI();
|
await this.evaluatePermissionsAndRoomSecrets();
|
||||||
|
await this.headerUI.evaluateOverflowing();
|
||||||
await this.headerUI.fadeIn();
|
await this.headerUI.fadeIn();
|
||||||
await this.footerUI._evaluateFooterBadges();
|
await this.footerUI._evaluateFooterBadges();
|
||||||
await this.footerUI.fadeIn();
|
await this.footerUI.fadeIn();
|
||||||
|
@ -87,10 +88,10 @@ class PairDrop {
|
||||||
return e.preventDefault();
|
return e.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
async evaluateUI() {
|
async evaluatePermissionsAndRoomSecrets() {
|
||||||
// Check whether notification permissions have already been granted
|
// Check whether notification permissions have already been granted
|
||||||
if ('Notification' in window && Notification.permission !== 'granted') {
|
if ('Notification' in window && Notification.permission !== 'granted') {
|
||||||
this.$headerNotificationButton.removeAttribute('hidden');
|
this.$headerNotificationBtn.removeAttribute('hidden');
|
||||||
}
|
}
|
||||||
|
|
||||||
let roomSecrets = await PersistentStorage.getAllRoomSecrets();
|
let roomSecrets = await PersistentStorage.getAllRoomSecrets();
|
||||||
|
|
|
@ -114,12 +114,62 @@ class ThemeUI {
|
||||||
class HeaderUI {
|
class HeaderUI {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.$header = $$('header.opacity-0');
|
this.$header = $$('header');
|
||||||
|
this.$expandBtn = $('expand');
|
||||||
|
Events.on("resize", _ => this.evaluateOverflowing());
|
||||||
|
this.$expandBtn.addEventListener('click', _ => this.onExpandBtnClick());
|
||||||
}
|
}
|
||||||
|
|
||||||
async fadeIn() {
|
async fadeIn() {
|
||||||
this.$header.classList.remove('opacity-0');
|
this.$header.classList.remove('opacity-0');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async evaluateOverflowing() {
|
||||||
|
// remove and reset bracket icon before evaluating
|
||||||
|
this.$expandBtn.setAttribute('hidden', true);
|
||||||
|
this.$expandBtn.classList.add('flipped');
|
||||||
|
|
||||||
|
const rtlLocale = Localization.isCurrentLocaleRtl();
|
||||||
|
let icon;
|
||||||
|
const $headerIconsShown = document.querySelectorAll('body > header:first-of-type > *:not([hidden])');
|
||||||
|
|
||||||
|
for (let i= 1; i < $headerIconsShown.length; i++) {
|
||||||
|
let isFurtherLeftThanLastIcon = $headerIconsShown[i].offsetLeft >= $headerIconsShown[i-1].offsetLeft;
|
||||||
|
let isFurtherRightThanLastIcon = $headerIconsShown[i].offsetLeft <= $headerIconsShown[i-1].offsetLeft;
|
||||||
|
if ((!rtlLocale && isFurtherLeftThanLastIcon) || (rtlLocale && isFurtherRightThanLastIcon)) {
|
||||||
|
// we have found the first icon on second row. Use previous icon.
|
||||||
|
icon = $headerIconsShown[i-1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (icon) {
|
||||||
|
// overflowing
|
||||||
|
// add overflowing-hidden class
|
||||||
|
this.$header.classList.add('overflow-hidden');
|
||||||
|
// add expand btn 2 before icon
|
||||||
|
this.$expandBtn.removeAttribute('hidden');
|
||||||
|
icon.before(this.$expandBtn);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// no overflowing
|
||||||
|
// add overflowing-hidden class
|
||||||
|
this.$header.classList.remove('overflow-hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onExpandBtnClick() {
|
||||||
|
// toggle overflowing-hidden class and flip expand btn icon
|
||||||
|
if (this.$header.classList.contains('overflow-hidden')) {
|
||||||
|
this.$header.classList.remove('overflow-hidden');
|
||||||
|
this.$header.classList.add('overflow-expanded');
|
||||||
|
this.$expandBtn.classList.remove('flipped');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.$header.classList.add('overflow-hidden');
|
||||||
|
this.$header.classList.remove('overflow-expanded');
|
||||||
|
this.$expandBtn.classList.add('flipped');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CenterUI {
|
class CenterUI {
|
||||||
|
|
|
@ -130,7 +130,7 @@ html {
|
||||||
}
|
}
|
||||||
|
|
||||||
header {
|
header {
|
||||||
position: absolute;
|
position: relative;
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
@ -140,67 +140,95 @@ header {
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
header > .row-reverse > * {
|
header.overflow-hidden {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
header:not(.overflow-expanded) {
|
||||||
|
height: 56px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header > * {
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
header > .row-reverse > div {
|
header > * {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-self: flex-start;
|
align-self: flex-start;
|
||||||
touch-action: manipulation;
|
touch-action: manipulation;
|
||||||
}
|
}
|
||||||
|
|
||||||
header > .row-reverse > div .icon-button {
|
header > .icon-button {
|
||||||
height: 40px;
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header * {
|
||||||
transition: all 300ms;
|
transition: all 300ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
header > .row-reverse > div > div {
|
#theme-wrapper > div {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
header > .row-reverse > div:not(:hover) .icon-button:not(.selected) {
|
/* expand theme buttons */
|
||||||
|
#theme-wrapper:not(:hover) .icon-button:not(.selected) {
|
||||||
height: 0;
|
height: 0;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#theme-wrapper:hover::before {
|
#theme-wrapper:hover::before {
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
background: currentColor;
|
background: var(--primary-color);
|
||||||
opacity: 0.1;
|
opacity: 0.2;
|
||||||
transition: opacity 300ms;
|
transition: opacity 300ms;
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
|
height: 120px;
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: 0;
|
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
header > .row-reverse > div:hover .icon-button.selected::before {
|
#theme-wrapper:hover .icon-button:not(.selected):hover:before {
|
||||||
opacity: 0.1;
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
#theme-wrapper:hover .icon-button.selected::before {
|
||||||
|
opacity: 0.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (pointer: coarse) {
|
@media (pointer: coarse) {
|
||||||
header > .row-reverse > div:hover .icon-button.selected:hover::before {
|
#theme-wrapper:hover .icon-button.selected:hover::before {
|
||||||
opacity: 0.2;
|
opacity: 0.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
header > .row-reverse > div .icon-button:not(.selected) {
|
#theme-wrapper .icon-button:not(.selected) {
|
||||||
height: 0;
|
height: 0;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
header > .row-reverse > div > div {
|
#theme-wrapper > div {
|
||||||
flex-direction: column-reverse;
|
flex-direction: column-reverse;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#expand > .icon {
|
||||||
|
transition: transform 150ms ease-out
|
||||||
|
}
|
||||||
|
|
||||||
|
html:not([dir="rtl"]) #expand.flipped > .icon {
|
||||||
|
transform: rotate(-90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
html[dir="rtl"] #expand.flipped > .icon {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
[hidden] {
|
[hidden] {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
@ -334,19 +362,16 @@ x-noscript {
|
||||||
|
|
||||||
/* Animations */
|
/* Animations */
|
||||||
|
|
||||||
|
/* Opacity for elements at keyframe 100% is set on element (default 1) */
|
||||||
@keyframes fade-in {
|
@keyframes fade-in {
|
||||||
0% {
|
0% {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#center {
|
#center {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-top: 56px;
|
|
||||||
flex-direction: column-reverse;
|
flex-direction: column-reverse;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
|
@ -359,18 +384,10 @@ x-noscript {
|
||||||
|
|
||||||
/* Peers */
|
/* Peers */
|
||||||
|
|
||||||
#x-peers-filler {
|
|
||||||
display: flex;
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
x-peers {
|
x-peers {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: row wrap;
|
flex-flow: row wrap;
|
||||||
flex-grow: 1;
|
|
||||||
align-items: start !important;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
transition: background-color 0.5s ease;
|
transition: background-color 0.5s ease;
|
||||||
|
@ -382,8 +399,6 @@ x-peers {
|
||||||
--peers-per-row: 6; /* default if browser does not support :has selector */
|
--peers-per-row: 6; /* default if browser does not support :has selector */
|
||||||
--x-peers-width: min(100vw, calc(var(--peers-per-row) * (var(--peer-width) + 25px) - 16px));
|
--x-peers-width: min(100vw, calc(var(--peers-per-row) * (var(--peer-width) + 25px) - 16px));
|
||||||
width: var(--x-peers-width);
|
width: var(--x-peers-width);
|
||||||
margin-right: 20px;
|
|
||||||
margin-left: 20px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Empty Peers List */
|
/* Empty Peers List */
|
||||||
|
@ -597,6 +612,7 @@ x-dialog:not([show]) x-background {
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
|
z-index: -1;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
background-color: var(--accent-color);
|
background-color: var(--accent-color);
|
||||||
transition: opacity 300ms;
|
transition: opacity 300ms;
|
||||||
|
@ -604,17 +620,17 @@ x-dialog:not([show]) x-background {
|
||||||
|
|
||||||
.btn:not([disabled]):hover:before,
|
.btn:not([disabled]):hover:before,
|
||||||
.icon-button:hover:before {
|
.icon-button:hover:before {
|
||||||
opacity: 0.1;
|
opacity: 0.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn[selected],
|
.btn[selected],
|
||||||
.icon-button[selected] {
|
.icon-button[selected] {
|
||||||
opacity: 0.1;
|
opacity: 0.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn:focus:before,
|
.btn:focus:before,
|
||||||
.icon-button:focus:before {
|
.icon-button:focus:before {
|
||||||
opacity: 0.2;
|
opacity: 0.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-round {
|
.btn-round {
|
||||||
|
@ -810,14 +826,12 @@ x-dialog[show] ~ div x-toast {
|
||||||
/* Instructions */
|
/* Instructions */
|
||||||
|
|
||||||
x-instructions {
|
x-instructions {
|
||||||
|
display: flex;
|
||||||
position: relative;
|
position: relative;
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-left: 10px;
|
margin: 50px 10px 0px;
|
||||||
margin-right: 10px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex-grow: 1;
|
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -834,8 +848,9 @@ x-instructions[drop-bg]:not([drop-peer]):before {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
x-peers:empty,
|
||||||
x-peers:empty~x-instructions {
|
x-peers:empty~x-instructions {
|
||||||
opacity: 0 !important;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (hover: none) and (pointer: coarse) {
|
@media (hover: none) and (pointer: coarse) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue