mirror of
https://github.com/He4eT/tabswitcher.git
synced 2026-05-05 01:17:23 +00:00
pages/search: shaped tabs
This commit is contained in:
parent
8d91c80b8b
commit
5df95ea62c
6 changed files with 221 additions and 20 deletions
|
|
@ -2,29 +2,43 @@ html, body {
|
||||||
font-family: sans;
|
font-family: sans;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
|
||||||
|
|
||||||
.popup {
|
|
||||||
--step: 8px;
|
--step: 8px;
|
||||||
|
|
||||||
--color-bg: #ffffff;
|
/* @see https://acorn.firefox.com/latest/styles/color-MZHBVuZc#section-gray-c2 */
|
||||||
--color-text: #333333;
|
--gray-light-05: #fbfbfe;
|
||||||
--color-accent: #888888;
|
--gray-light-10: #f9f9fb;
|
||||||
|
--gray-light-20: #f0f0f4;
|
||||||
|
--gray-light-30: #e0e0e6;
|
||||||
|
--gray-light-40: #cfcfd8;
|
||||||
|
--gray-light-50: #bfbfc9;
|
||||||
|
|
||||||
|
--gray-dark-05: #5b5b66;
|
||||||
|
--gray-dark-10: #52525e;
|
||||||
|
--gray-dark-30: #42414d;
|
||||||
|
--gray-dark-40: #3a3944;
|
||||||
|
--gray-dark-60: #2b2a33;
|
||||||
|
--gray-dark-80: #1c1b22;
|
||||||
|
--gray-dark-90: #15141a;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
--color-bg: var(--gray-light-10);
|
||||||
|
--color-text: var(--gray-dark-80);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
.popup {
|
body {
|
||||||
--color-bg: #1c1c1c;
|
--color-bg: var(--gray-dark-60);
|
||||||
--color-text: #eeeeee;
|
--color-text: var(--gray-light-40);
|
||||||
--color-accent: #cccccc;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Controls */
|
/* Common */
|
||||||
|
|
||||||
*:focus-visible {
|
body {
|
||||||
outline-color: var(--color-accent);
|
font-size: calc(2 * var(--step));
|
||||||
outline-offset: 4px;
|
|
||||||
outline-style: solid;
|
background-color: var(--color-bg);
|
||||||
outline-width: 1px;
|
color: var(--color-text);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
36
pages/search/modules/labels.js
Normal file
36
pages/search/modules/labels.js
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
const labels = {
|
||||||
|
/* tabId: label, */
|
||||||
|
}
|
||||||
|
|
||||||
|
const lettersOrder = 'lkjhyuionm'
|
||||||
|
|
||||||
|
const digits2label = (digits) => [...digits]
|
||||||
|
.map((digit) => lettersOrder[digit])
|
||||||
|
.join('')
|
||||||
|
|
||||||
|
const label2digits = (label) => [...label]
|
||||||
|
.map((letter) => [...lettersOrder].findIndex((x) => x === letter))
|
||||||
|
.join('')
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
export const id2label = (id, tabs) => {
|
||||||
|
if (!labels[id]) {
|
||||||
|
const label = Object.keys(labels).length
|
||||||
|
labels[id] = String(label)
|
||||||
|
}
|
||||||
|
|
||||||
|
const keyLength = String(tabs?.length).length
|
||||||
|
const digits = String(labels[id]).padStart(keyLength, 0)
|
||||||
|
return digits2label(digits)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const label2id = (label) => {
|
||||||
|
const paddedDigits = label2digits(label)
|
||||||
|
const digits = String(parseInt(paddedDigits))
|
||||||
|
|
||||||
|
const [key] = Object.entries(labels)
|
||||||
|
.find(([_, value]) => value === digits)
|
||||||
|
|
||||||
|
return parseInt(key)
|
||||||
|
}
|
||||||
58
pages/search/modules/store.js
Normal file
58
pages/search/modules/store.js
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
import * as labels from './labels.js'
|
||||||
|
|
||||||
|
export const init = ({
|
||||||
|
tabs: browserTabs,
|
||||||
|
onStateUpdate,
|
||||||
|
}) => {
|
||||||
|
/* Initial state */
|
||||||
|
const state = {
|
||||||
|
tabs: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
const shapeTabs = (tabs) => tabs
|
||||||
|
.map((tab) => ({
|
||||||
|
label: labels.id2label(tab.id, tabs),
|
||||||
|
...tab,
|
||||||
|
}))
|
||||||
|
.map((tab) => [
|
||||||
|
'favIconUrl',
|
||||||
|
'id',
|
||||||
|
'label',
|
||||||
|
'title',
|
||||||
|
'url',
|
||||||
|
].reduce((acc, x) => (acc[x] = tab[x], acc), {}))
|
||||||
|
|
||||||
|
const fetchTabs = () =>
|
||||||
|
browserTabs.query({ currentWindow: true, active: false })
|
||||||
|
.then(shapeTabs)
|
||||||
|
.then((tabs) => tabs.reverse())
|
||||||
|
.then((tabs) => void (state.tabs = tabs))
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
const updateState = () =>
|
||||||
|
fetchTabs()
|
||||||
|
.then(() => onStateUpdate(state))
|
||||||
|
|
||||||
|
updateState()
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
return {
|
||||||
|
getCurrentState() {
|
||||||
|
return state
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
goToTab(id) {
|
||||||
|
browserTabs.update(id, { active: true })
|
||||||
|
.then(updateState)
|
||||||
|
},
|
||||||
|
closeTab(id) {
|
||||||
|
browserTabs.remove(id)
|
||||||
|
.then(updateState)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,63 @@
|
||||||
body {
|
header {
|
||||||
background-color: red;
|
display: flex;
|
||||||
|
padding: calc(2 * var(--step));
|
||||||
|
gap: calc(2 * var(--step));
|
||||||
|
}
|
||||||
|
|
||||||
|
header > input {
|
||||||
|
border: 0;
|
||||||
|
border-bottom: 2px solid var(--gray-light-30);
|
||||||
|
padding: var(--step);
|
||||||
|
flex: 1 1 auto;
|
||||||
|
font: inherit;
|
||||||
|
background: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
header > input#searchbox {
|
||||||
|
flex-grow: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
header > input:focus-visible {
|
||||||
|
outline: none;
|
||||||
|
border-bottom: 2px solid var(--color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
padding: calc(2 * var(--step));
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab {
|
||||||
|
appearance: none;
|
||||||
|
text-align: unset;
|
||||||
|
|
||||||
|
background: inherit;
|
||||||
|
font: inherit;
|
||||||
|
border: inherit;
|
||||||
|
|
||||||
|
width: auto;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
padding: calc(1 * var(--step));
|
||||||
|
gap: calc(2 * var(--step));
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab .label {
|
||||||
|
font-family: monospace;
|
||||||
|
color: var(--gray-dark-05);
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab > .title,
|
||||||
|
.tab > .url {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab .url {
|
||||||
|
color: var(--gray-dark-05);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,36 @@
|
||||||
<html lang='en'>
|
<html lang='en'>
|
||||||
<head>
|
<head>
|
||||||
<meta charset='UTF-8'>
|
<meta charset='UTF-8'>
|
||||||
<title>Tabswhither</title>
|
<title>Tabswitcher</title>
|
||||||
<link rel='stylesheet' href='../css/common.css' />
|
<link rel='stylesheet' href='../css/common.css' />
|
||||||
<link rel='stylesheet' href='./search.css' />
|
<link rel='stylesheet' href='./search.css' />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
lorem
|
<header>
|
||||||
|
<input type='search' id='searchbox' placeholder='Filter' autofocus>
|
||||||
|
<input type='search' id='actionbox' placeholder='Action (? for help)'>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<button class='tab'>
|
||||||
|
<div class='label'>jk</div>
|
||||||
|
<div class='title'>
|
||||||
|
Color - Firefox Design Systems
|
||||||
|
</div>
|
||||||
|
<div class='url'>
|
||||||
|
https://acorn.firefox.com/latest/styles/color-MZHBVuZc#section-background-c2
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<button class='tab'>
|
||||||
|
<div class='label'>kjqww</div>
|
||||||
|
<div class='title'>
|
||||||
|
Color - Firefox Design Systems
|
||||||
|
</div>
|
||||||
|
<div class='url'>
|
||||||
|
https://acorn.firefox.com/latest/styles/color-MZHBVuZc#section-background-c2
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</main>
|
||||||
|
<script type='module' src='./search.js'></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|
|
||||||
10
pages/search/search.js
Normal file
10
pages/search/search.js
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import * as Store from './modules/store.js'
|
||||||
|
|
||||||
|
console.log('1234')
|
||||||
|
|
||||||
|
const store = Store.init({
|
||||||
|
tabs: browser.tabs,
|
||||||
|
onStateUpdate: console.log,
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log(store.getCurrentState())
|
||||||
Loading…
Add table
Add a link
Reference in a new issue