feat: add colorful / accent color mode toggle

- CAT_COLORS: カテゴリ別カラーマップ(ダーク/ライト両対応)
- 統一色モード: すべて var(--accent) Teal
- カラフルモード: sns=Blue / media=Pink / news=Orange / tools=Slate / nav=Green / shop=Amber / posimai=Teal
- カラフル時: アイコン stroke + カード背景・ボーダーに極薄カラーを適用
- セクションラベルもカテゴリ色に追従
- 設定パネルに色ドット付きトグルボタンを追加
- localStorage に設定を保存
This commit is contained in:
posimai 2026-03-21 11:06:48 +09:00
parent 9d3cd8510e
commit d85b825bba
1 changed files with 133 additions and 8 deletions

View File

@ -208,6 +208,44 @@
.empty-title { font-size: 14px; font-weight: 500; margin-bottom: 4px; }
.empty-sub { font-size: 13px; }
/* ── Color mode selector ── */
.color-mode-selector {
display: flex;
gap: 6px;
margin-top: 8px;
}
.color-mode-btn {
flex: 1;
padding: 7px 8px;
border-radius: 8px;
border: 1px solid var(--border);
background: transparent;
color: var(--text2);
font-size: 12px;
font-family: inherit;
cursor: pointer;
transition: all 0.12s;
display: flex;
align-items: center;
justify-content: center;
gap: 5px;
}
.color-mode-btn.active {
background: var(--surface2);
border-color: var(--accent);
color: var(--accent);
font-weight: 600;
}
.color-dots {
display: flex;
gap: 2px;
}
.color-dot {
width: 6px;
height: 6px;
border-radius: 50%;
}
/* ── Settings extras ── */
.settings-field-label {
font-size: 12px;
@ -293,6 +331,28 @@
</div>
</div>
<div style="margin-top:20px">
<div class="settings-group-label">アイコンカラー</div>
<div class="color-mode-selector">
<button class="color-mode-btn" data-color-mode="accent" id="colorModeAccent">
<span class="color-dots">
<span class="color-dot" style="background:#6EE7B7"></span>
<span class="color-dot" style="background:#6EE7B7"></span>
<span class="color-dot" style="background:#6EE7B7"></span>
</span>
統一色
</button>
<button class="color-mode-btn" data-color-mode="colorful" id="colorModeColorful">
<span class="color-dots">
<span class="color-dot" style="background:#60A5FA"></span>
<span class="color-dot" style="background:#F472B6"></span>
<span class="color-dot" style="background:#4ADE80"></span>
</span>
カラフル
</button>
</div>
</div>
<div style="margin-top:20px">
<div class="settings-group-label">同期(オプション)</div>
<p class="settings-field-label">
@ -353,9 +413,32 @@
// Posimai Veil — アプリランチャー
// ============================================================
const ENABLED_KEY = 'posimai-veil-enabled';
const API_KEY_KEY = 'posimai_api_key';
const API_BASE = 'https://posimai-lab.tail72e846.ts.net/brain/api';
const ENABLED_KEY = 'posimai-veil-enabled';
const API_KEY_KEY = 'posimai_api_key';
const COLOR_MODE_KEY = 'posimai-veil-color-mode';
const API_BASE = 'https://posimai-lab.tail72e846.ts.net/brain/api';
// ── カテゴリカラー(ダーク / ライト) ──────────────────────
const CAT_COLORS = {
dark: {
posimai: '#6EE7B7', // Tealブランドカラー
sns: '#60A5FA', // Blue
media: '#F472B6', // Pink
news: '#FB923C', // Orange
tools: '#94A3B8', // Slate
nav: '#4ADE80', // Green
shop: '#FBBF24', // Amber
},
light: {
posimai: '#059669', // Emerald-600
sns: '#2563EB', // Blue-600
media: '#DB2777', // Pink-600
news: '#EA580C', // Orange-600
tools: '#475569', // Slate-600
nav: '#16A34A', // Green-600
shop: '#D97706', // Amber-600
},
};
// ── アプリDB ────────────────────────────────────────────────
// android : Androidパッケージ名_camera/_phone/_settings は特殊intent
@ -501,8 +584,18 @@ let enabledIds = loadEnabled();
let activeCat = 'all';
let searchQ = '';
let editMode = false;
let colorMode = localStorage.getItem(COLOR_MODE_KEY) || 'accent'; // 'accent' | 'colorful'
let apiKey = localStorage.getItem(API_KEY_KEY) || '';
function getTheme() {
return document.documentElement.getAttribute('data-theme') === 'light' ? 'light' : 'dark';
}
function getCatColor(cat) {
if (colorMode !== 'colorful') return 'var(--accent)';
return CAT_COLORS[getTheme()][cat] || 'var(--accent)';
}
function loadEnabled() {
try {
const raw = localStorage.getItem(ENABLED_KEY);
@ -607,22 +700,37 @@ function renderApps() {
const orderedCats = CAT_ORDER.filter(c => groups[c]);
container.innerHTML = orderedCats.map(cat => {
const apps = groups[cat];
const apps = groups[cat];
const color = getCatColor(cat);
const isColorful = colorMode === 'colorful';
// カラフルモード時: カードに極薄の色背景+ボーダー
const cardColorStyle = isColorful
? `--item-color:${color};`
: '';
return `
<div class="app-section">
<div class="section-label">${CAT_LABELS[cat] || cat}</div>
<div class="section-label"
style="${isColorful ? `color:${color};opacity:.9` : ''}">${CAT_LABELS[cat] || cat}</div>
<div class="app-grid">
${apps.map(app => {
const on = enabledIds.has(app.id);
const hidden = !editMode && !on ? ' hidden' : '';
const editCls = editMode ? ` edit-mode ${on ? 'on' : 'off'}` : '';
const bgStyle = isColorful
? `background:${color}14;border-color:${color}38;`
: '';
return `
<div class="app-item${editCls}${hidden}"
data-id="${app.id}" role="button" tabindex="0"
aria-label="${app.label}">
<i data-lucide="${app.icon}" class="app-icon"></i>
aria-label="${app.label}"
style="${bgStyle}${cardColorStyle}">
<i data-lucide="${app.icon}" class="app-icon"
style="stroke:${color}"></i>
<span class="app-label">${app.label}</span>
<span class="check-badge" aria-hidden="true">
<span class="check-badge" aria-hidden="true"
style="background:${color}">
<i data-lucide="check"
style="width:9px;height:9px;stroke-width:3;stroke:#0D0D0D"></i>
</span>
@ -666,6 +774,23 @@ document.getElementById('searchInput').addEventListener('input', e => {
renderApps();
});
// ── カラーモード切替 ────────────────────────────────────────
function syncColorModeUI() {
document.getElementById('colorModeAccent').classList.toggle('active', colorMode === 'accent');
document.getElementById('colorModeColorful').classList.toggle('active', colorMode === 'colorful');
}
['colorModeAccent', 'colorModeColorful'].forEach(id => {
document.getElementById(id).addEventListener('click', () => {
colorMode = id === 'colorModeAccent' ? 'accent' : 'colorful';
localStorage.setItem(COLOR_MODE_KEY, colorMode);
syncColorModeUI();
renderApps();
});
});
syncColorModeUI();
// ── API キー保存 ────────────────────────────────────────────
document.getElementById('apiKeyInput').value = apiKey;
document.getElementById('apiKeySave').addEventListener('click', () => {