Replace platform checkboxes with pill toggles in social scheduler

Target selection is now a row of compact pills (per platform+target)
instead of grouped checkbox lists. Clicking a pill toggles it active;
the image icon inside only activates when the pill is selected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Bashy 2026-06-04 20:09:57 +03:00
parent 24c9deef94
commit 5b801514b2
2 changed files with 51 additions and 39 deletions

View file

@ -458,6 +458,21 @@ pre { color: #e6edf3; }
.social-platform-mastodon { background: rgba(99,100,255,.25); color: #a29cf4; border-color: rgba(99,100,255,.4); }
.social-platform-linkedin { background: rgba(10,102,194,.25); color: #5ba3d9; border-color: rgba(10,102,194,.4); }
.social-pill {
display: inline-flex; align-items: center; gap: 5px;
padding: 3px 10px; border-radius: 999px;
border: 1px solid var(--hm-border); cursor: pointer;
font-size: .8rem; color: var(--hm-muted);
background: transparent; user-select: none; transition: all .15s;
}
.social-pill:hover { border-color: #8b949e; color: #c9d1d9; }
.social-pill.active[data-platform="discord"] { background: rgba(88,101,242,.2); border-color: rgba(88,101,242,.7); color: #9aa0f5; }
.social-pill.active[data-platform="mastodon"] { background: rgba(99,100,255,.2); border-color: rgba(99,100,255,.7); color: #a29cf4; }
.social-pill.active[data-platform="linkedin"] { background: rgba(10,102,194,.2); border-color: rgba(10,102,194,.7); color: #5ba3d9; }
.social-pill-img { opacity: .35; font-size: .75em; transition: opacity .15s; }
.social-pill:hover .social-pill-img { opacity: .6; }
.social-pill.img-on .social-pill-img { opacity: 1; }
.social-post-card .card-body { border-left: 3px solid transparent; border-radius: inherit; }
.social-post-card.status-pending .card-body { border-left-color: #e3b341; }
.social-post-card.status-done .card-body { border-left-color: #3fb950; }

View file

@ -3896,55 +3896,52 @@ window.addEventListener('DOMContentLoaded', () => {
el.innerHTML = '<div class="text-muted small">No eligible projects configured. <a href="/settings">Go to Settings</a> to enable projects.</div>';
return;
}
const platformIcon = { discord: 'bi-discord', mastodon: 'bi-mastodon', linkedin: 'bi-linkedin' };
const platformLabel = { discord: 'Discord', mastodon: 'Mastodon', linkedin: 'LinkedIn' };
el.innerHTML = _targets.map(group => {
const platforms = ['discord', 'mastodon', 'linkedin'].filter(p => group.targets[p]?.length);
if (!platforms.length) return '';
return `<div class="mb-3">
<div class="small fw-semibold text-muted mb-1">${esc(group.project_name)}</div>
${platforms.map(platform => `
<div class="mb-2">
<div class="small text-muted mb-1"><i class="bi ${platformIcon[platform]}"></i> ${platformLabel[platform]}</div>
${group.targets[platform].map(t => {
const cbId = `st_${group.project_id}_${platform}_${t.key}`;
const imgId = `si_${group.project_id}_${platform}_${t.key}`;
const checked = prefill?.some(x => x.project_id == group.project_id && x.platform === platform && x.target_key === t.key) ? 'checked' : '';
const imgChecked = prefill?.some(x => x.project_id == group.project_id && x.platform === platform && x.target_key === t.key && x.include_image) ? 'checked' : '';
return `<div class="d-flex align-items-center gap-2 mb-1">
<input class="form-check-input social-target-cb" type="checkbox" id="${cbId}"
data-pid="${group.project_id}" data-platform="${platform}" data-key="${esc(t.key)}" ${checked}>
<label class="form-check-label small flex-grow-1" for="${cbId}">${esc(t.label)}</label>
<input class="form-check-input social-img-cb ${_hasImage ? '' : 'd-none'}" type="checkbox" id="${imgId}"
data-for="${cbId}" title="Include image" ${imgChecked}>
<label class="form-check-label small text-muted ${_hasImage ? '' : 'd-none'}" for="${imgId}">
<i class="bi bi-image"></i>
</label>
const pills = _targets.flatMap(group =>
['discord', 'mastodon', 'linkedin'].flatMap(platform =>
(group.targets[platform] || []).map(t => {
const active = prefill?.some(x => x.project_id == group.project_id && x.platform === platform && x.target_key === t.key);
const imgOn = prefill?.some(x => x.project_id == group.project_id && x.platform === platform && x.target_key === t.key && x.include_image);
return `<div class="social-pill${active ? ' active' : ''}${imgOn ? ' img-on' : ''}"
data-pid="${group.project_id}" data-platform="${platform}" data-key="${esc(t.key)}"
title="${esc(group.project_name)}">
<i class="bi bi-${platform}"></i>${esc(t.label)}
<span class="social-pill-img${_hasImage ? '' : ' d-none'}" title="Include image"><i class="bi bi-image-fill"></i></span>
</div>`;
}).join('')}
</div>`).join('')}
</div>`;
}).join('');
})
)
);
el.innerHTML = `<div class="d-flex flex-wrap gap-2">${pills.join('')}</div>`;
el.querySelectorAll('.social-pill').forEach(pill => {
pill.addEventListener('click', e => {
if (e.target.closest('.social-pill-img')) {
if (pill.classList.contains('active')) pill.classList.toggle('img-on');
return;
}
pill.classList.toggle('active');
if (pill.classList.contains('active') && _hasImage) pill.classList.add('img-on');
else if (!pill.classList.contains('active')) pill.classList.remove('img-on');
});
});
}
function toggleImageCols(show) {
_hasImage = show;
page.querySelectorAll('.social-img-cb, .social-img-cb + label').forEach(el => {
el.classList.toggle('d-none', !show);
});
if (show) page.querySelectorAll('.social-img-cb').forEach(cb => { cb.checked = true; });
page.querySelectorAll('.social-pill-img').forEach(el => el.classList.toggle('d-none', !show));
if (show) page.querySelectorAll('.social-pill.active').forEach(p => p.classList.add('img-on'));
if (!show) page.querySelectorAll('.social-pill').forEach(p => p.classList.remove('img-on'));
}
function collectTargets() {
const targets = [];
page.querySelectorAll('.social-target-cb:checked').forEach(cb => {
const imgCb = page.querySelector(`.social-img-cb[data-for="${cb.id}"]`);
page.querySelectorAll('.social-pill.active').forEach(pill => {
targets.push({
project_id: +cb.dataset.pid,
platform: cb.dataset.platform,
target_key: cb.dataset.key,
include_image: imgCb?.checked ? 1 : 0,
project_id: +pill.dataset.pid,
platform: pill.dataset.platform,
target_key: pill.dataset.key,
include_image: pill.classList.contains('img-on') ? 1 : 0,
});
});
return targets;