feat(icon): Phosphor glyph card — hero + real-UI-size strip (T-313)

The icon card renders each glyph at a hero size plus a continuous sample
strip (10–48px) so legibility is judged at the sizes the app uses, with the
entry's optional label + description and a per-entry or card-level color.
Wired end to end: icon.show publishes on the `icon` bus, the Claude
extension injects an IconMessage, and conversation_view paints the card
(display-only, D-78). en+nl catalogs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-29 13:10:53 +02:00
co-authored by Claude Opus 4.8
parent 9a2b4e9eca
commit 281fb2a869
10 changed files with 205 additions and 1 deletions
@@ -38,6 +38,8 @@ ToolResultMessage _result(String content, {bool isError = false}) =>
ImageMessage _image(String path, {String? caption, String? label, String? description}) =>
ImageMessage(uuid: 'i', timestamp: _t, isSidechain: false, path: path, caption: caption, label: label, description: description);
IconMessage _iconMsg(List<IconEntry> entries, {String? color}) => IconMessage(uuid: 'ic', timestamp: _t, isSidechain: false, entries: entries, color: color);
class _MockClipboard {
Map<String, dynamic> _data = {'text': null};
Future<Object?> handleMethodCall(MethodCall call) async {
@@ -480,6 +482,17 @@ void main() {
expect(find.text('before'), findsOneWidget);
});
testWidgets('an icon card renders the glyph label, description, and size strip (T-313)', (tester) async {
await pumpWith(tester, [
_iconMsg([const IconEntry(codepoint: 0xe2a4, name: 'gear', label: 'Settings', description: 'global scope')]),
]);
expect(find.text('icons'), findsOneWidget); // card label
expect(find.text('Settings'), findsOneWidget); // entry label
expect(find.text('global scope'), findsOneWidget);
expect(find.text('10'), findsOneWidget); // smallest strip sample
expect(find.text('48'), findsOneWidget); // largest strip sample
});
testWidgets('inject() drives a new image card into a live view (T-249)', (tester) async {
final c = await pumpWith(tester, [_user('hi')]);
expect(find.text('image'), findsNothing);