mirror of
https://github.com/He4eT/tabswitcher.git
synced 2026-05-04 17:07: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
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 {
|
||||
background-color: red;
|
||||
header {
|
||||
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'>
|
||||
<head>
|
||||
<meta charset='UTF-8'>
|
||||
<title>Tabswhither</title>
|
||||
<title>Tabswitcher</title>
|
||||
<link rel='stylesheet' href='../css/common.css' />
|
||||
<link rel='stylesheet' href='./search.css' />
|
||||
</head>
|
||||
|
||||
<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>
|
||||
</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