T9.3 - S6: one icon system - monochrome text glyphs, one meaning each
The set mixed colour emoji with dingbats, and the same glyph read as two things partly BECAUSE emoji render as per-platform artwork. The system chosen: monochrome text-presentation glyphs - the suite is classic-script vanilla HTML with no bundler, so an SVG sprite or icon font is a new asset pipeline, while text glyphs render through the same font stack as the words beside them. The enforceable form of "renders identically on Windows, macOS and a tablet": no emoji-range codepoint and no U+FE0F selector anywhere in UI source, swept by the probe on every run. Converted: green-check/red-cross emoji in the admin and users consoles to checkmark/cross, no-entry to circled-slash (blocked/on hold), the lock to the pencil already meaning "edit with a logged reason" on sign-offs, the star to the diamond, the folder to the reference marker, the side nav's lightning to the gear, and the WATCH glyph (U+231A - emoji-presentation BY DEFAULT per Unicode) to a text-presentation clock face. Dropped where the label already carried the meaning: lightning on Save & view, the camera on Add photo, the page/frame pictograms on file rows (the filename is the label). Stale help copy fixed while its emoji left: it still described the pre-T9.4 "Load sample" and the pre-T7.10 "Usage Logs" locations. The meaning-to-icon mapping is in docs/reference/tokens.md - one meaning per glyph, one glyph per meaning, both directions asserted from the document itself; the probe also sweeps every page for glyphs not in the approved set, so an unmapped icon cannot creep in. Verification (each probe run alone): NEW tests/icon_check.py 5/5. Regressions: frame_check 38/38, files_check 36/36, a11y_check 22/22, cards_check 44/44. Items: S6 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -34,7 +34,7 @@ async function boot(){
|
||||
_scope = (status === 200 && json) ? json : { can_manage_users:false, scope:'projects',
|
||||
grantable_roles:[], grantable_project_roles:[], managed_projects:[], project_roles:PROJECT_ROLES };
|
||||
if(status !== 200){
|
||||
banner('scope-banner','bad','❌ '+apiError(status, json, 'Could not work out what you may do here')+
|
||||
banner('scope-banner','bad','✕ '+apiError(status, json, 'Could not work out what you may do here')+
|
||||
' Showing the directory read-only.');
|
||||
} else {
|
||||
renderScope();
|
||||
@@ -85,7 +85,7 @@ async function loadUsers(){
|
||||
const wrap = document.getElementById('users-table');
|
||||
const { status, json } = await api('GET','/api/auth/users');
|
||||
if(status !== 200 || !Array.isArray(json)){
|
||||
banner('users-banner','bad','❌ '+apiError(status, json, 'Could not load the directory'));
|
||||
banner('users-banner','bad','✕ '+apiError(status, json, 'Could not load the directory'));
|
||||
wrap.innerHTML = ''; return;
|
||||
}
|
||||
banner('users-banner','', '');
|
||||
@@ -354,11 +354,11 @@ async function createUser(){
|
||||
role: val('nu-role'), project_role: val('nu-project-role'),
|
||||
});
|
||||
if(status === 200){
|
||||
say('var(--green)','✅ Created '+username+'.');
|
||||
say('var(--green)','✓ Created '+username+'.');
|
||||
['nu-username','nu-fullname','nu-email','nu-password'].forEach(id => document.getElementById(id).value = '');
|
||||
loadUsers();
|
||||
} else {
|
||||
say('var(--red)','❌ '+apiError(status, json, 'Could not create the account'));
|
||||
say('var(--red)','✕ '+apiError(status, json, 'Could not create the account'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user