Skip to content

Commit 8b36ba1

Browse files
committed
feat: add Token Beam integration for real-time color syncing in design tools
1 parent c72bec2 commit 8b36ba1

File tree

1 file changed

+138
-2
lines changed

1 file changed

+138
-2
lines changed

dist/index.html

Lines changed: 138 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,6 +1088,40 @@
10881088
height: 0;
10891089
}
10901090

1091+
.token-beam {
1092+
margin-top: 10vmin;
1093+
font-size: 1.4em;
1094+
}
1095+
.token-beam p {
1096+
font-size: .8em;
1097+
}
1098+
.token-beam__title + .l-sec__controls{
1099+
margin-top: 0;
1100+
}
1101+
.token-beam__token {
1102+
cursor: pointer;
1103+
user-select: all;
1104+
text-decoration: underline;
1105+
padding-top: 0.25em;
1106+
font-size: .9rem;
1107+
display: block;
1108+
}
1109+
.token-beam__token:hover {
1110+
border-color: var(--c0);
1111+
text-decoration: none;
1112+
}
1113+
.token-beam__status {
1114+
font-style: normal;
1115+
}
1116+
.token-beam__status[data-state="paired"] {
1117+
opacity: 1;
1118+
color: var(--c0);
1119+
}
1120+
.token-beam__status[data-state="error"] {
1121+
opacity: 1;
1122+
color: red;
1123+
}
1124+
10911125
.support {
10921126
font-size: 1.4em;
10931127
margin-top: 10vmin;
@@ -1870,6 +1904,28 @@ <h2 id="export" class="hidden">Export</h2>
18701904

18711905
</div>
18721906

1907+
<div class="token-beam">
1908+
<h2 class="subtitle token-beam__title">Export</h2>
1909+
1910+
<div class="l-sec__controls">
1911+
<label>
1912+
<span>
1913+
<span class="t">Token Beam</span>
1914+
<em class="token-beam__status" data-tb-status></em>
1915+
</span>
1916+
<i>
1917+
<span class="token-beam__token" data-tb-token title="Click to copy">connecting…</span>
1918+
</i>
1919+
</label>
1920+
</div>
1921+
<p>
1922+
Beam your "<strong class="t">poline</strong>" palette directly into <a
1923+
href="https://github.com/meodai/token-beam/releases/" target="_blank" rel="noopener">Figma, Aseprite, Blender or
1924+
Adobe&nbsp;XD</a>. Copy the session token below, paste it in your design tool's Token Beam plugin and every color
1925+
update syncs instantly.
1926+
</p>
1927+
</div>
1928+
18731929
<div class="support">
18741930
<h2 class="subtitle support__title">Support</h2>
18751931
<p>
@@ -2531,6 +2587,10 @@ <h2 class="export__title">${paletteTitle}</h2>
25312587
}, 100);
25322588

25332589
updateUI();
2590+
2591+
document.dispatchEvent(
2592+
new CustomEvent('poline:colors', { detail: { colors } })
2593+
);
25342594
}
25352595

25362596
updateSVG();
@@ -3302,6 +3362,82 @@ <h2 class="export__title">${paletteTitle}</h2>
33023362
}, 1500);
33033363
}, 2000);
33043364
</script>
3305-
</body>
33063365

3307-
</html>
3366+
<script type="module">
3367+
import { SourceSession, createCollection } from 'https://esm.sh/token-beam@1.9.0';
3368+
3369+
const $token = document.querySelector('[data-tb-token]');
3370+
const $status = document.querySelector('[data-tb-status]');
3371+
let session = null;
3372+
let lastColors = [];
3373+
3374+
function setStatus(text, state = '') {
3375+
$status.textContent = text;
3376+
$status.dataset.state = state;
3377+
}
3378+
3379+
function syncColors(colors) {
3380+
if (!session || !colors.length) return;
3381+
const tokens = {};
3382+
colors.forEach((hex, i) => {
3383+
tokens[`${String(i + 1).padStart(2, '0')}`] = hex;
3384+
});
3385+
session.sync(createCollection(`Poline`, tokens));
3386+
}
3387+
3388+
async function initTokenBeam() {
3389+
session = new SourceSession({
3390+
clientType: 'web',
3391+
origin: 'Poline Color Palette',
3392+
});
3393+
3394+
session.on('paired', ({ sessionToken }) => {
3395+
$token.textContent = sessionToken;
3396+
$token.title = 'Click to copy';
3397+
setStatus('waiting for plugin…', '');
3398+
});
3399+
3400+
session.on('peer-connected', ({ clientType }) => {
3401+
setStatus(`connected to ${clientType}`, 'paired');
3402+
syncColors(lastColors);
3403+
});
3404+
3405+
session.on('peer-disconnected', () => {
3406+
setStatus('plugin disconnected', '');
3407+
});
3408+
3409+
session.on('error', ({ message }) => {
3410+
setStatus(message, 'error');
3411+
});
3412+
3413+
session.on('disconnected', () => {
3414+
setStatus('reconnecting…', '');
3415+
});
3416+
3417+
await session.connect();
3418+
}
3419+
3420+
$token.addEventListener('click', () => {
3421+
const text = $token.textContent;
3422+
if (text && text.startsWith('beam://')) {
3423+
navigator.clipboard.writeText(text);
3424+
const prev = $status.textContent;
3425+
const prevState = $status.dataset.state;
3426+
setStatus('copied!', '');
3427+
setTimeout(() => setStatus(prev, prevState), 1500);
3428+
}
3429+
});
3430+
3431+
document.addEventListener('poline:colors', (e) => {
3432+
lastColors = e.detail.colors;
3433+
if (!session || session.getState() !== 'paired') return;
3434+
syncColors(lastColors);
3435+
});
3436+
3437+
initTokenBeam().catch(err => {
3438+
console.error('[token-beam]', err);
3439+
setStatus('connection failed', 'error');
3440+
});
3441+
</script>
3442+
</body>
3443+
</html>

0 commit comments

Comments
 (0)