Design tab menu and hover menu button

This commit is contained in:
AlphaX-Projects 2023-06-12 18:13:56 +02:00
parent b46ad24c90
commit bf55cb5faf
4 changed files with 217 additions and 141 deletions

View File

@ -60,6 +60,9 @@ html {
--gif-button-row-bg: #eaeaef; --gif-button-row-bg: #eaeaef;
--gif-button-row-color: #464040; --gif-button-row-color: #464040;
--gif-collection-hover-bg: #eaeaefa3; --gif-collection-hover-bg: #eaeaefa3;
--app-background-1: #045de9;
--app-background-2: #09c6f9;
--app-icon: #ffffff;
} }
html[theme="dark"] { html[theme="dark"] {
@ -124,4 +127,7 @@ html[theme="dark"] {
--gif-button-row-bg: #82899c; --gif-button-row-bg: #82899c;
--gif-button-row-color: #151212; --gif-button-row-color: #151212;
--gif-collection-hover-bg: #ffffff26; --gif-collection-hover-bg: #ffffff26;
--app-background-1: #7f5a83;
--app-background-2: #0d324d;
--app-icon: #03a9f4;
} }

View File

@ -119,9 +119,9 @@ class AppView extends connect(store)(LitElement) {
return [ return [
css` css`
* { * {
--mdc-theme-primary: rgb(3, 169, 244); --mdc-theme-primary: rgb(3, 169, 244);
--mdc-theme-secondary: var(--mdc-theme-primary); --mdc-theme-secondary: var(--mdc-theme-primary);
--mdc-theme-error: rgb(255, 89, 89); --mdc-theme-error: rgb(255, 89, 89);
--lumo-primary-text-color: rgb(0, 167, 245); --lumo-primary-text-color: rgb(0, 167, 245);
--lumo-primary-color-50pct: rgba(0, 167, 245, 0.5); --lumo-primary-color-50pct: rgba(0, 167, 245, 0.5);
--lumo-primary-color-10pct: rgba(0, 167, 245, 0.1); --lumo-primary-color-10pct: rgba(0, 167, 245, 0.1);
@ -468,7 +468,6 @@ class AppView extends connect(store)(LitElement) {
<app-header id='appHeader' slot="header" fixed> <app-header id='appHeader' slot="header" fixed>
<app-toolbar> <app-toolbar>
<paper-icon-button id="mb" class="menu-toggle-button" drawer-toggle icon="menu"></paper-icon-button> <paper-icon-button id="mb" class="menu-toggle-button" drawer-toggle icon="menu"></paper-icon-button>
<vaadin-tooltip text="${translate("general.update")}" for="mb" position="bottom"></vaadin-tooltip>
<div main-title> <div main-title>
<span class="qora-title"> <span class="qora-title">
<img src="${this.config.coin.logo}" style="height:32px; padding-left:12px;"> <img src="${this.config.coin.logo}" style="height:32px; padding-left:12px;">
@ -513,6 +512,12 @@ class AppView extends connect(store)(LitElement) {
addTradeBotRoutes(parentEpml) addTradeBotRoutes(parentEpml)
parentEpml.imReady() parentEpml.imReady()
var drawerTog = this.shadowRoot.getElementById("mb")
drawerTog.addEventListener('mouseover', function() {
drawerTog.click()
})
this.getNodeType() this.getNodeType()
const myAppNode = store.getState().app.nodeConfig.knownNodes[store.getState().app.nodeConfig.node] const myAppNode = store.getState().app.nodeConfig.knownNodes[store.getState().app.nodeConfig.node]

View File

@ -6,13 +6,7 @@ import { addPluginRoutes } from '../plugins/addPluginRoutes.js'
import { repeat } from 'lit/directives/repeat.js'; import { repeat } from 'lit/directives/repeat.js';
import ShortUniqueId from 'short-unique-id'; import ShortUniqueId from 'short-unique-id';
import { setNewTab } from '../redux/app/app-actions.js' import { setNewTab } from '../redux/app/app-actions.js'
import '@vaadin/icon'
import '@vaadin/icons'
import '@vaadin/icon'
import '@vaadin/icons'
import '@material/mwc-icon' import '@material/mwc-icon'
class ShowPlugin extends connect(store)(LitElement) { class ShowPlugin extends connect(store)(LitElement) {
@ -99,7 +93,7 @@ class ShowPlugin extends connect(store)(LitElement) {
} }
.tab:hover { .tab:hover {
background: #F3F4F6; background: var(--nav-color-hover);
color: #03a9f4; color: #03a9f4;
font-weight: bold; font-weight: bold;
} }
@ -154,6 +148,7 @@ class ShowPlugin extends connect(store)(LitElement) {
color: #03a9f4; color: #03a9f4;
--mdc-icon-size: 20px; --mdc-icon-size: 20px;
} }
.iconInactive { .iconInactive {
position: absolute; position: absolute;
top: 7px; top: 7px;
@ -218,13 +213,13 @@ class ShowPlugin extends connect(store)(LitElement) {
class="add-tab-button" class="add-tab-button"
title="Add Tab" title="Add Tab"
@click=${() => { @click=${() => {
const lengthOfTabs = this.tabs.length const lengthOfTabs = this.tabs.length
this.addTab({ this.addTab({
url: "", url: "",
id: this.uid() id: this.uid()
}) })
this.currentTab = lengthOfTabs this.currentTab = lengthOfTabs
}} }}
> >
+ +
</button> </button>
@ -232,8 +227,7 @@ class ShowPlugin extends connect(store)(LitElement) {
${repeat(this.tabs, (tab) => tab.id, (tab, index) => html` ${repeat(this.tabs, (tab) => tab.id, (tab, index) => html`
<div class=${this.currentTab === index ? "showIframe" : "hideIframe"}> <div class=${this.currentTab === index ? "showIframe" : "hideIframe"}>
<iframe src="${plugSrc(tab.myPlugObj)}" id="showPluginFrame${index}" style="width:100%;
<iframe src="${plugSrc(tab.myPlugObj)}" id="showPluginFrame${index}" style="width:100%;
height:calc(var(--window-height) - 102px); height:calc(var(--window-height) - 102px);
border:0; border:0;
padding:0; padding:0;
@ -241,10 +235,8 @@ class ShowPlugin extends connect(store)(LitElement) {
class=${!tab.myPlugObj ? "hideIframe" : ""} class=${!tab.myPlugObj ? "hideIframe" : ""}
> >
</iframe> </iframe>
<nav-bar class=${!tab.myPlugObj ? "showIframe" : "hideIframe"} .registeredUrls=${this.registeredUrls} .changePage=${(val) => this.changePage(val)}>
<nav-bar class=${!tab.myPlugObj ? "showIframe" : "hideIframe"} .registeredUrls=${this.registeredUrls} .changePage=${(val) => this.changePage(val)}></nav-bar> </nav-bar>
</div> </div>
`)} `)}
` `
@ -320,7 +312,6 @@ class ShowPlugin extends connect(store)(LitElement) {
} }
changePage(page) { changePage(page) {
const copiedTabs = [...this.tabs] const copiedTabs = [...this.tabs]
copiedTabs[this.currentTab] = { copiedTabs[this.currentTab] = {
...copiedTabs[this.currentTab], ...copiedTabs[this.currentTab],
@ -328,8 +319,6 @@ class ShowPlugin extends connect(store)(LitElement) {
url: page.url url: page.url
} }
this.tabs = copiedTabs this.tabs = copiedTabs
} }
stateChanged(state) { stateChanged(state) {
@ -390,127 +379,166 @@ class ShowPlugin extends connect(store)(LitElement) {
window.customElements.define('show-plugin', ShowPlugin) window.customElements.define('show-plugin', ShowPlugin)
class NavBar extends LitElement { class NavBar extends connect(store)(LitElement) {
static get properties() { static get properties() {
return { return {
registeredUrls: { type: Array }, menuList: { type: Array },
changePage: { attribute: false }, newMenuList: { type: Array },
myMenuList: { type: Array },
addressInfo: { type: Object },
changePage: { attribute: false }
} }
} }
constructor() { constructor() {
super() super()
this.registeredUrls = [] this.menuList = []
this.newMenuList = []
this.myMenuList = []
this.addressInfo = {}
}
}
static styles = css` static styles = css`
.parent { .parent {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
padding: 20px; padding: 20px;
} overflow-y: auto;
.navbar { }
display: flex;
justify-content: space-between; .navbar {
align-items: center; display: flex;
background-color: #f8f8f8; justify-content: space-between;
padding: 10px 20px; align-items: center;
max-width: 750px; background-color: color: var(--white);
width: 80%; padding: 10px 20px;
} max-width: 750px;
.navbar input { width: 80%;
font-size: 16px; }
padding: 5px;
flex-grow: 1; .navbar input {
margin-right: 10px; font-size: 16px;
border: 1px solid #ddd; color: #000;
} padding: 5px;
.navbar button { flex-grow: 1;
padding: 5px 10px; margin-right: 10px;
background-color: #4CAF50; border: 1px solid var(--black);
color: white; }
border: none;
cursor: pointer; .navbar button {
} padding: 5px 10px;
.navbar button:hover { font-size: 18px;
background-color: #45a049; background-color: var(--app-background-1);
} background-image: linear-gradient(315deg, var(--app-background-1) 0%, var(--app-background-2) 74%);
.app-list { color: var(--app-icon);
display: flex; border: 1px solid transparent;
justify-content: space-around; border-radius: 3px;
padding: 20px 0; cursor: pointer;
gap: 20px; }
flex-wrap: wrap;
} .navbar button:hover {
.app-list .app-icon { background-color: #45a049;
text-align: center; }
font-size: 24px;
width: 150px; .app-list {
height: 150px; display: flex;
background: white; justify-content: space-between;
border-radius: 5px; padding: 20px 0;
padding: 5px; gap: 20px;
display: flex; flex-wrap: wrap;
flex-direction: column; }
align-items: center;
justify-content: center; .app-list .app-icon {
gap: 10px; text-align: center;
cursor: pointer; font-size: 16px;
} font-weight: bold;
.app-list .app-icon span { color: var(--black);
display: block; width: 150px;
} height: 110px;
`; background: transparent;
padding: 5px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 10px;
cursor: pointer;
}
.app-list .app-icon span {
display: block;
}
.app-icon-box {
display: flex;
align-items: center;
padding-left: 14px;
width: 80px;
height: 80px;
background-color: var(--app-background-1);
background-image: linear-gradient(315deg, var(--app-background-1) 0%, var(--app-background-2) 74%);
border-top-left-radius: 10px;
border-top-right-radius: 20px;
border-bottom-left-radius: 20px;
border-bottom-right-radius: 10px;
}
.menuIcon {
color: var(--app-icon);
--mdc-icon-size: 64px;
}
`
async extractComponents(url) { async extractComponents(url) {
if (!url.startsWith("qortal://")) { if (!url.startsWith("qortal://")) {
return null; return null
} }
url = url.replace(/^(qortal\:\/\/)/, ""); url = url.replace(/^(qortal\:\/\/)/, "")
if (url.includes("/")) { if (url.includes("/")) {
let parts = url.split("/"); let parts = url.split("/")
const service = parts[0].toUpperCase(); const service = parts[0].toUpperCase()
parts.shift(); parts.shift()
const name = parts[0]; const name = parts[0]
parts.shift(); parts.shift()
let identifier; let identifier
if (parts.length > 0) { if (parts.length > 0) {
identifier = parts[0]; // Do not shift yet identifier = parts[0] // Do not shift yet
// Check if a resource exists with this service, name and identifier combination // Check if a resource exists with this service, name and identifier combination
const myNode = store.getState().app.nodeConfig.knownNodes[store.getState().app.nodeConfig.node]; const myNode = store.getState().app.nodeConfig.knownNodes[store.getState().app.nodeConfig.node]
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port; const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
let responseObj = await parentEpml.request('apiCall', { let responseObj = await parentEpml.request('apiCall', {
url: `${nodeUrl}/arbitrary/resource/status/${service}/${name}/${identifier}?apiKey=${myNode.apiKey}}` url: `${nodeUrl}/arbitrary/resource/status/${service}/${name}/${identifier}?apiKey=${myNode.apiKey}}`
}) })
if (responseObj.totalChunkCount > 0) { if (responseObj.totalChunkCount > 0) {
// Identifier exists, so don't include it in the path // Identifier exists, so don't include it in the path
parts.shift(); parts.shift()
} }
else { else {
identifier = null; identifier = null
} }
} }
const path = parts.join("/"); const path = parts.join("/")
const components = {}; const components = {}
components["service"] = service; components["service"] = service
components["name"] = name; components["name"] = name
components["identifier"] = identifier; components["identifier"] = identifier
components["path"] = path; components["path"] = path
return components; return components
} }
return null; return null
} }
async getQuery(value) { async getQuery(value) {
let newQuery = value; let newQuery = value
if (newQuery.endsWith('/')) { if (newQuery.endsWith('/')) {
newQuery = newQuery.slice(0, -1); newQuery = newQuery.slice(0, -1)
} }
const res = await this.extractComponents(newQuery) const res = await this.extractComponents(newQuery)
if (!res) return if (!res) return
@ -527,15 +555,14 @@ class NavBar extends LitElement {
} }
this.changePage({ this.changePage({
"url": "qapp", "url": "qapp",
"domain": "core", "domain": "core",
"page": `qdn/browser/index.html${query}`, "page": `qdn/browser/index.html${query}`,
"title": "Q-App", "title": "Q-App",
"icon": "vaadin:desktop", "icon": "vaadin:external-browser",
"mwcicon": "open_in_browser",
"menus": [], "menus": [],
"parent": false "parent": false
}) })
} }
@ -548,36 +575,62 @@ class NavBar extends LitElement {
if (e.key === 'Enter') { if (e.key === 'Enter') {
const value = this.shadowRoot.getElementById('linkInput').value const value = this.shadowRoot.getElementById('linkInput').value
this.getQuery(value) this.getQuery(value)
} }
} }
render() { render() {
return html` return html`
<div class="parent"> <div class="parent">
<div class="navbar"> <div class="navbar">
<input @keydown=${this._handleKeyDown} id="linkInput" type="text" placeholder="qortal://" /> <input @keydown=${this._handleKeyDown} id="linkInput" type="text" placeholder="qortal://" />
<button @click="${this.handlePasteLink}">Go</button> <button @click="${this.handlePasteLink}">Go</button>
</div> </div>
<div> <div>
<div class="app-list"> <div class="app-list">
${repeat(this.myMenuList, (plugin) => plugin.url, (plugin, index) => html`
${repeat(this.registeredUrls, (plugin) => plugin.url, (plugin, index) => html` <div class="app-icon" @click=${() => {
<div class="app-icon" @click=${() => { this.changePage(plugin)
this.changePage(plugin) }}>
}}> <div class="app-icon-box">
<vaadin-icon icon=${plugin.icon} slot="icon"></vaadin-icon> <mwc-icon class="menuIcon">${plugin.mwcicon}</mwc-icon>
<span>${plugin.title}</span> </div>
</div> <span>${plugin.title}</span>
</div>
`)} `)}
</div>
</div>
</div> </div>
</div> `
</div> }
`;
firstUpdated() {
const addressInfo = this.addressInfo
const isMinter = addressInfo?.error !== 124 && +addressInfo?.level > 0
const isSponsor = +addressInfo?.level >= 5
if (!isMinter) {
this.newMenuList = this.menuList.filter((minter) => {
return minter.url !== 'minting'
})
} else {
this.newMenuList = this.menuList.filter((minter) => {
return minter.url !== 'become-minter'
})
}
if (!isSponsor) {
this.myMenuList = this.newMenuList.filter((sponsor) => {
return sponsor.url !== 'sponsorship-list'
})
} else {
this.myMenuList = this.newMenuList
}
}
stateChanged(state) {
this.menuList = state.app.registeredUrls
this.addressInfo = state.app.accountInfo.addressInfo
} }
} }
customElements.define('nav-bar', NavBar); customElements.define('nav-bar', NavBar)

View File

@ -29,6 +29,7 @@ html {
--relaynodetxt: #646464; --relaynodetxt: #646464;
--menuhover: #eeeeee; --menuhover: #eeeeee;
--menuactive: #ebebeb; --menuactive: #ebebeb;
--menuactivergb: 235, 235, 235;
--mainmenutext: #080808; --mainmenutext: #080808;
--mainmenutexthover: #080808; --mainmenutexthover: #080808;
--switchbackground: #666666; --switchbackground: #666666;
@ -42,11 +43,13 @@ html {
--nav-icon-color: #080808; --nav-icon-color: #080808;
--nav-border-color: #eeeeee; --nav-border-color: #eeeeee;
--nav-border-selected-color: #03a9f4; --nav-border-selected-color: #03a9f4;
--error: #d50000;
--background: url("/img/qortal_background_light_.jpg"); --background: url("/img/qortal_background_light_.jpg");
--chatHeadBg: #ebebeb; --chatHeadBg: #ebebeb;
--chatHeadBgActive: #ebebeb; --chatHeadBgActive: #ebebeb;
--chatHeadText: #080808; --chatHeadText: #080808;
--chatHeadTextActive: #080808; --chatHeadTextActive: #080808;
--lightChatHeadHover: #1e1f201a;
--group-header: #929292; --group-header: #929292;
--group-drop-shadow: rgb(17 17 26 / 10%) 0px 1px 0px; --group-drop-shadow: rgb(17 17 26 / 10%) 0px 1px 0px;
--reactions-tooltip-bg: #ffffff; --reactions-tooltip-bg: #ffffff;
@ -57,6 +60,9 @@ html {
--gif-button-row-bg: #eaeaef; --gif-button-row-bg: #eaeaef;
--gif-button-row-color: #464040; --gif-button-row-color: #464040;
--gif-collection-hover-bg: #eaeaefa3; --gif-collection-hover-bg: #eaeaefa3;
--app-background-1: #045de9;
--app-background-2: #09c6f9;
--app-icon: #ffffff;
} }
html[theme="dark"] { html[theme="dark"] {
@ -90,6 +96,7 @@ html[theme="dark"] {
--relaynodetxt: #d4d4d4; --relaynodetxt: #d4d4d4;
--menuhover: #008fd5; --menuhover: #008fd5;
--menuactive: #008fd5; --menuactive: #008fd5;
--menuactivergb: 0, 143, 213;
--mainmenutext: #008fd5; --mainmenutext: #008fd5;
--mainmenutexthover: #0f1a2e; --mainmenutexthover: #0f1a2e;
--switchbackground: #eeeeee; --switchbackground: #eeeeee;
@ -103,11 +110,13 @@ html[theme="dark"] {
--nav-icon-color: #008fd5; --nav-icon-color: #008fd5;
--nav-border-color: #0b305e; --nav-border-color: #0b305e;
--nav-border-selected-color: #76c8f5; --nav-border-selected-color: #76c8f5;
--error: #d50000;
--background: url("/img/qortal_background_dark_.jpg"); --background: url("/img/qortal_background_dark_.jpg");
--chatHeadBg: #008fd5; --chatHeadBg: #008fd5;
--chatHeadBgActive: #0f1a2e; --chatHeadBgActive: #0f1a2e;
--chatHeadText: #ffffff; --chatHeadText: #ffffff;
--chatHeadTextActive: #ffffff; --chatHeadTextActive: #ffffff;
--lightChatHeadHover: #e0e1e31a;
--group-header: #c8c8c8; --group-header: #c8c8c8;
--group-drop-shadow: rgb(191 191 191 / 32%) 0px 1px 0px; --group-drop-shadow: rgb(191 191 191 / 32%) 0px 1px 0px;
--reactions-tooltip-bg: #161515; --reactions-tooltip-bg: #161515;
@ -118,4 +127,7 @@ html[theme="dark"] {
--gif-button-row-bg: #82899c; --gif-button-row-bg: #82899c;
--gif-button-row-color: #151212; --gif-button-row-color: #151212;
--gif-collection-hover-bg: #ffffff26; --gif-collection-hover-bg: #ffffff26;
--app-background-1: #7f5a83;
--app-background-2: #0d324d;
--app-icon: #03a9f4;
} }