案例

Sealed:放得下才封口的信封

給 X、Bluesky 和單則簡訊用的字數檢查器:真的放得下,信封才封蠟;還會點名那個把簡訊從 160 字砍到 70 字的彎引號。

  • 6 張圖片
開啟頁面查看將在新分頁開啟 boloop-works.pages.dev,該頁面為獨立站點,不屬於本站。

圖片署名:Tink

一個能直接用的字數檢查器,用三隻信封來做:「X post」「Bluesky post」和「One text message」(一則簡訊)。只有文字真的放得下,信封才會封上紅色火漆。

打開頁面時已經放好一封示範信(“Running 10 minutes late — the train’s stuck outside Hongqiao…”)。第一秒內紙條滑進信封:X(125 / 280)和 Bluesky(125 / 300)闔上並封蠟;簡訊信封闔不上,紙條頂出信封蓋,紅色虛線以上露出的就是真正放不下的那段原文,下方寫著 “Open · 55 over · sends as 2 texts”。為什麼只有 70?一條虛線框直接點名:一個破折號和一個彎引號。簡訊裡只要出現一個 GSM 字母表以外的字元,上限就從 160 變成 70。按 “Make it SMS-safe (swap 3)”,第三隻信封當場以 125 / 160 封上。

每打一個字信封都會跟著變化。“Trim to fit” 會把超出的部分剪到放得下為止,不會把一個字元剪成兩半;Undo 可以復原。你打的字永遠不會被悄悄改寫,只有這些按鈕會改動文字。emoji 換不掉,會標成 “can’t swap”,不會被偷偷刪掉。可以複製文字;剪貼簿被攔截等錯誤會直接顯示並朗讀。減少動態效果時直接顯示最終狀態。360 px 手機可用。不儲存、不上傳任何內容。

計數依據:X 直接用 X 開源的 twitter-text 3.1.0(未改動,打包進頁面),連結算 23,大部分中日韓文字和 emoji 算 2。Bluesky 依貼文 schema 的兩條線:300 個字素、3,000 位元組(UTF-8)。簡訊依 GSM 03.38:160 個 7 位元字元(分則時每則 153,€ ^ { } [ ] ~ | \ 各佔 2);一旦出現 Unicode 字元就是 70(分則 67)。限制:比 twitter-text 3.1.0 更新的 emoji 依該函式庫的方式計數,可能與 X 線上不同;Bluesky App 可能會縮短長連結;沒有處理各國簡訊的擴充字元表。

線上試用:https://boloop-works.pages.dev/works/sealed/

下載原型檔案(zip,152 KB):https://boloop-works.pages.dev/works/sealed/sealed.zip

實際設計說明

Design a small, genuinely useful character counter made of three envelopes — "X post" (280, counted with X's open-source twitter-text 3.1.0, bundled unmodified), "Bluesky post" (300 graphemes and 3,000 UTF-8 bytes, from the app.bsky.feed.post schema) and "One text message" (GSM 03.38: 160 7-bit characters, or 70 once a single Unicode character appears) — as a runnable single-page web app (plain HTML/CSS/JS, no backend, no build, English UI, local fonts, inline SVG favicon).

First second, desktop and 390 px phone: a sample letter is already in place. Paper slips slide into the envelopes; X and Bluesky close and get a red wax seal pressed on; the SMS envelope cannot close — its slip sticks out above the flap and the part above a red dashed fold line is the actual text that does not fit. Under it: "Open · 55 over · sends as 2 texts". A dashed panel names the culprits ("These 2 marks shrink one SMS from 160 to 70 characters: — ’") with one button: "Make it SMS-safe (swap 3)".

Operable: every keystroke moves the slips, opens/closes flaps and presses or lifts seals. Explicit buttons only ever change the text: "Make it SMS-safe" (swaps ’ ‘ “ ” — – … and no-break space for plain ones; emoji are listed as "can't swap"), "Trim to fit" per open envelope (cuts to fit, never inside a grapheme), and one-level Undo. Typing is never rewritten, there is no maxlength. Errors are visible and announced (role=alert): empty copy, blocked clipboard, browser without Intl.Segmenter. Status line (aria-live polite) settles 0.7 s after typing. Reduced motion: final state at once. Nothing is stored or sent.

Inspired by @binniebunnnies and @marcgmbh.