168 lines
7.1 KiB
JavaScript
168 lines
7.1 KiB
JavaScript
// Chrome spoof — static-but-believable browser UI.
|
|
|
|
const TABS = [
|
|
{ title: 'New Tab', active: true },
|
|
{ title: 'Meridian Docs', active: false },
|
|
{ title: 'Search', active: false },
|
|
];
|
|
|
|
const SHORTCUTS = [
|
|
{ label: 'GitHub', url: 'https://github.com' },
|
|
{ label: 'Gmail', url: 'https://mail.google.com' },
|
|
{ label: 'YouTube', url: 'https://youtube.com' },
|
|
{ label: 'Maps', url: 'https://maps.google.com' },
|
|
{ label: 'Drive', url: 'https://drive.google.com' },
|
|
{ label: 'Calendar', url: 'https://calendar.google.com' },
|
|
{ label: 'Docs', url: 'https://docs.google.com' },
|
|
{ label: 'Translate', url: 'https://translate.google.com' },
|
|
];
|
|
|
|
export default {
|
|
id: 'chrome',
|
|
title: 'Chrome',
|
|
render(container, api) {
|
|
let activeTab = 0;
|
|
let navUrl = '';
|
|
|
|
const root = document.createElement('div');
|
|
root.style.cssText = 'height:100%;display:flex;flex-direction:column;background:var(--bg-1);';
|
|
|
|
// Tab strip
|
|
const tabStrip = document.createElement('div');
|
|
tabStrip.style.cssText = 'display:flex;background:var(--bg-2);border-bottom:1px solid var(--border);flex-shrink:0;overflow-x:auto;';
|
|
|
|
// New tab button
|
|
const newTabBtn = document.createElement('button');
|
|
newTabBtn.style.cssText = 'padding:8px 12px;font-size:16px;border:none;background:transparent;color:var(--text-dim);cursor:pointer;flex-shrink:0;';
|
|
newTabBtn.textContent = '+';
|
|
newTabBtn.addEventListener('click', () => {
|
|
const newIdx = TABS.length;
|
|
TABS.push({ title: 'New Tab', active: true });
|
|
TABS.forEach((t) => { t.active = false; });
|
|
TABS[newIdx].active = true;
|
|
activeTab = newIdx;
|
|
navUrl = '';
|
|
updateTabBar();
|
|
updateBody();
|
|
});
|
|
|
|
function updateTabBar() {
|
|
tabStrip.innerHTML = '';
|
|
TABS.forEach((tab, i) => {
|
|
const btn = document.createElement('button');
|
|
btn.style.cssText = 'padding:8px 16px;font-size:12px;border:none;background:transparent;color:' + (tab.active ? 'var(--text)' : 'var(--text-dim)') + ';border-right:1px solid var(--border);cursor:pointer;transition:color 150ms;max-width:180px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;';
|
|
btn.textContent = tab.title;
|
|
btn.addEventListener('click', () => {
|
|
activeTab = i;
|
|
navUrl = SHORTCUTS[i] ? SHORTCUTS[i].url : '';
|
|
updateTabBar();
|
|
updateBody();
|
|
});
|
|
tabStrip.appendChild(btn);
|
|
});
|
|
tabStrip.appendChild(newTabBtn);
|
|
}
|
|
|
|
updateTabBar();
|
|
root.appendChild(tabStrip);
|
|
|
|
// Address bar
|
|
const addrBar = document.createElement('div');
|
|
addrBar.style.cssText = 'display:flex;align-items:center;padding:6px 12px;gap:8px;background:var(--bg-2);border-bottom:1px solid var(--border);flex-shrink:0;';
|
|
|
|
const urlInput = document.createElement('input');
|
|
urlInput.type = 'text';
|
|
urlInput.value = navUrl || (SHORTCUTS[activeTab] ? SHORTCUTS[activeTab].url : '');
|
|
urlInput.style.cssText = 'flex:1;padding:6px 12px;background:var(--bg-3);border:1px solid var(--border);border-radius:20px;color:var(--text);font-size:13px;outline:none;';
|
|
urlInput.placeholder = 'Search or enter web address';
|
|
urlInput.addEventListener('keydown', (e) => {
|
|
if (e.key === 'Enter') {
|
|
const val = urlInput.value.trim();
|
|
if (val) {
|
|
navUrl = val;
|
|
updateBody();
|
|
}
|
|
}
|
|
});
|
|
|
|
const reloadBtn = document.createElement('button');
|
|
reloadBtn.style.cssText = 'padding:4px 8px;background:transparent;border:none;color:var(--text-dim);cursor:pointer;font-size:14px;';
|
|
reloadBtn.textContent = '\u{21BB}';
|
|
reloadBtn.addEventListener('click', () => { updateBody(); });
|
|
|
|
addrBar.appendChild(urlInput);
|
|
addrBar.appendChild(reloadBtn);
|
|
root.appendChild(addrBar);
|
|
|
|
// Body
|
|
const body = document.createElement('div');
|
|
body.style.cssText = 'flex:1;overflow-y:auto;padding:40px 20px;background:var(--bg-1);';
|
|
|
|
function updateBody() {
|
|
body.innerHTML = '';
|
|
urlInput.value = navUrl || (TABS[activeTab].title === 'New Tab' ? '' : TABS[activeTab].title.toLowerCase().replace(/\s+/g, '-') + '.meridian.dev');
|
|
|
|
if (activeTab === 0 && !navUrl) {
|
|
// New tab page
|
|
const titleEl = document.createElement('h2');
|
|
titleEl.style.cssText = 'font-size:22px;font-weight:500;color:var(--text);margin-bottom:28px;text-align:center;';
|
|
titleEl.textContent = 'Meridian Browser';
|
|
body.appendChild(titleEl);
|
|
|
|
const grid = document.createElement('div');
|
|
grid.style.cssText = 'display:grid;grid-template-columns:repeat(4,1fr);gap:12px;max-width:600px;margin:0 auto;';
|
|
|
|
SHORTCUTS.forEach((sc) => {
|
|
const tile = document.createElement('div');
|
|
tile.style.cssText = 'padding:16px 12px;background:var(--bg-2);border:1px solid var(--border);border-radius:8px;text-align:center;cursor:pointer;transition:background 150ms;';
|
|
tile.addEventListener('mouseenter', () => { tile.style.background = 'var(--bg-3)'; });
|
|
tile.addEventListener('mouseleave', () => { tile.style.background = 'var(--bg-2)'; });
|
|
tile.addEventListener('click', () => {
|
|
navUrl = sc.url;
|
|
TABS[0].title = sc.label;
|
|
updateTabBar();
|
|
updateBody();
|
|
});
|
|
const tileIcon = document.createElement('div');
|
|
tileIcon.style.cssText = 'font-size:18px;font-weight:600;color:var(--accent);margin-bottom:4px;';
|
|
tileIcon.textContent = sc.label.charAt(0);
|
|
const tileLabel = document.createElement('div');
|
|
tileLabel.style.cssText = 'font-size:11px;color:var(--text-dim);';
|
|
tileLabel.textContent = sc.label;
|
|
tile.appendChild(tileIcon);
|
|
tile.appendChild(tileLabel);
|
|
grid.appendChild(tile);
|
|
});
|
|
|
|
body.appendChild(grid);
|
|
} else {
|
|
// Simulated page
|
|
const page = document.createElement('div');
|
|
page.style.cssText = 'max-width:600px;margin:0 auto;';
|
|
|
|
const heading = document.createElement('h2');
|
|
heading.style.cssText = 'font-size:22px;font-weight:500;color:var(--text);margin-bottom:12px;';
|
|
heading.textContent = 'Simulated page for ' + (navUrl || TABS[activeTab].title);
|
|
page.appendChild(heading);
|
|
|
|
const urlDisplay = document.createElement('div');
|
|
urlDisplay.style.cssText = 'font-size:12px;color:var(--text-dim);margin-bottom:24px;font-family:monospace;padding:8px 12px;background:var(--bg-2);border:1px solid var(--border);border-radius:4px;';
|
|
urlDisplay.textContent = navUrl || TABS[activeTab].title;
|
|
page.appendChild(urlDisplay);
|
|
|
|
const para = document.createElement('p');
|
|
para.style.cssText = 'font-size:14px;color:var(--text-dim);line-height:1.7;';
|
|
const displayUrl = navUrl || TABS[activeTab].title;
|
|
para.textContent = 'This is a simulated page for ' + displayUrl + '. Meridian Browser does not make actual network requests — it is a spoof. Nothing to see here unless you count the aesthetic choices.';
|
|
page.appendChild(para);
|
|
|
|
body.appendChild(page);
|
|
}
|
|
}
|
|
|
|
root.appendChild(body);
|
|
container.appendChild(root);
|
|
updateBody();
|
|
},
|
|
};
|