@nadicodeai/ui 9.2.1 → 10.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -0
- package/README.md +4 -29
- package/dist/agent-orb.d.ts +3 -0
- package/dist/agent-orb.d.ts.map +1 -0
- package/dist/agent-orb.js +2 -0
- package/dist/assets/brand/aionlabs.svg +2 -0
- package/dist/assets/brand/airtable.svg +2 -0
- package/dist/assets/brand/apple.svg +2 -0
- package/dist/assets/brand/arcee.svg +2 -0
- package/dist/assets/brand/asana.svg +2 -0
- package/dist/assets/brand/atlassian.svg +2 -0
- package/dist/assets/brand/baidu.svg +2 -0
- package/dist/assets/brand/bytedance.svg +2 -0
- package/dist/assets/brand/claude.svg +2 -0
- package/dist/assets/brand/cohere.svg +2 -0
- package/dist/assets/brand/datadog.svg +2 -0
- package/dist/assets/brand/deepseek.svg +2 -0
- package/dist/assets/brand/discord.svg +2 -0
- package/dist/assets/brand/dolphin.svg +2 -0
- package/dist/assets/brand/dotsstudio.svg +2 -0
- package/dist/assets/brand/figma.svg +2 -0
- package/dist/assets/brand/gemini.svg +2 -0
- package/dist/assets/brand/github.svg +2 -0
- package/dist/assets/brand/gitlab.svg +2 -0
- package/dist/assets/brand/gmail.svg +2 -0
- package/dist/assets/brand/google-calendar.svg +2 -0
- package/dist/assets/brand/google-drive.svg +2 -0
- package/dist/assets/brand/grok.svg +2 -0
- package/dist/assets/brand/huggingface.svg +2 -0
- package/dist/assets/brand/ibm.svg +2 -0
- package/dist/assets/brand/inception.svg +2 -0
- package/dist/assets/brand/inclusionai.svg +2 -0
- package/dist/assets/brand/index.json +778 -0
- package/dist/assets/brand/inference.svg +2 -0
- package/dist/assets/brand/intercom.svg +2 -0
- package/dist/assets/brand/jira.svg +2 -0
- package/dist/assets/brand/kwaipilot.svg +2 -0
- package/dist/assets/brand/linear.svg +2 -0
- package/dist/assets/brand/linux.svg +2 -0
- package/dist/assets/brand/liquid.svg +2 -0
- package/dist/assets/brand/longcat.svg +2 -0
- package/dist/assets/brand/mattermost.svg +2 -0
- package/dist/assets/brand/meta.svg +2 -0
- package/dist/assets/brand/microsoft.svg +2 -0
- package/dist/assets/brand/minimax.svg +2 -0
- package/dist/assets/brand/mistral.svg +2 -0
- package/dist/assets/brand/moonshot.svg +2 -0
- package/dist/assets/brand/morph.svg +2 -0
- package/dist/assets/brand/n8n.svg +2 -0
- package/dist/assets/brand/netlify.svg +2 -0
- package/dist/assets/brand/nexagi.svg +2 -0
- package/dist/assets/brand/notion.svg +2 -0
- package/dist/assets/brand/nousresearch.svg +2 -0
- package/dist/assets/brand/nova.svg +2 -0
- package/dist/assets/brand/nvidia.svg +2 -0
- package/dist/assets/brand/openai.svg +2 -0
- package/dist/assets/brand/openrouter.svg +2 -0
- package/dist/assets/brand/paypal.svg +2 -0
- package/dist/assets/brand/perceptron.svg +2 -0
- package/dist/assets/brand/perplexity.svg +2 -0
- package/dist/assets/brand/poolside.svg +2 -0
- package/dist/assets/brand/postgresql.svg +2 -0
- package/dist/assets/brand/qwen.svg +2 -0
- package/dist/assets/brand/reka.svg +2 -0
- package/dist/assets/brand/relace.svg +2 -0
- package/dist/assets/brand/sakana.svg +2 -0
- package/dist/assets/brand/sentry.svg +2 -0
- package/dist/assets/brand/signal.svg +2 -0
- package/dist/assets/brand/slack.svg +2 -0
- package/dist/assets/brand/spotify.svg +2 -0
- package/dist/assets/brand/square.svg +2 -0
- package/dist/assets/brand/stepfun.svg +2 -0
- package/dist/assets/brand/stripe.svg +2 -0
- package/dist/assets/brand/supabase.svg +2 -0
- package/dist/assets/brand/telegram.svg +2 -0
- package/dist/assets/brand/tencent.svg +2 -0
- package/dist/assets/brand/the-drummer.svg +2 -0
- package/dist/assets/brand/thinkingmachines.svg +2 -0
- package/dist/assets/brand/todoist.svg +2 -0
- package/dist/assets/brand/unbiased.svg +2 -0
- package/dist/assets/brand/unreal-engine.svg +2 -0
- package/dist/assets/brand/upstage.svg +2 -0
- package/dist/assets/brand/vercel.svg +2 -0
- package/dist/assets/brand/webflow.svg +2 -0
- package/dist/assets/brand/whatsapp.svg +2 -0
- package/dist/assets/brand/windows.svg +2 -0
- package/dist/assets/brand/writer.svg +2 -0
- package/dist/assets/brand/xiaomimimo.svg +2 -0
- package/dist/assets/brand/youtube.svg +2 -0
- package/dist/assets/brand/yuanbao.svg +2 -0
- package/dist/assets/brand/zai.svg +2 -0
- package/dist/assets/brand/zapier.svg +2 -0
- package/dist/components/action-status.d.ts +5 -0
- package/dist/components/action-status.d.ts.map +1 -1
- package/dist/components/action-status.js +6 -2
- package/dist/components/agent-orb-appearance.d.ts +16 -2
- package/dist/components/agent-orb-appearance.d.ts.map +1 -1
- package/dist/components/agent-orb-appearance.js +28 -5
- package/dist/components/agent-orb.d.ts +6 -3
- package/dist/components/agent-orb.d.ts.map +1 -1
- package/dist/components/agent-orb.js +20 -7
- package/dist/components/app-mark-aliases.d.ts +16 -0
- package/dist/components/app-mark-aliases.d.ts.map +1 -0
- package/dist/components/app-mark-aliases.js +84 -0
- package/dist/components/app-mark.d.ts +4 -0
- package/dist/components/app-mark.d.ts.map +1 -1
- package/dist/components/app-mark.js +14 -31
- package/dist/components/automation-section.d.ts.map +1 -1
- package/dist/components/automation-section.js +2 -2
- package/dist/components/badge.js +1 -1
- package/dist/components/brand.d.ts +3 -2
- package/dist/components/brand.d.ts.map +1 -1
- package/dist/components/brand.js +18 -28
- package/dist/components/button.js +1 -1
- package/dist/components/collection-filters.js +2 -2
- package/dist/components/confirm-dialog.d.ts +3 -1
- package/dist/components/confirm-dialog.d.ts.map +1 -1
- package/dist/components/confirm-dialog.js +3 -3
- package/dist/components/drawer.js +5 -5
- package/dist/components/feedback-state.d.ts.map +1 -1
- package/dist/components/feedback-state.js +6 -9
- package/dist/components/footer.js +2 -2
- package/dist/components/house-icons.d.ts.map +1 -1
- package/dist/components/house-icons.js +9 -1
- package/dist/components/input-otp.js +1 -1
- package/dist/components/installer-shell.d.ts.map +1 -1
- package/dist/components/installer-shell.js +5 -6
- package/dist/components/navigation-menu.js +2 -2
- package/dist/components/pending-label.d.ts +15 -0
- package/dist/components/pending-label.d.ts.map +1 -0
- package/dist/components/pending-label.js +14 -0
- package/dist/components/sheet.js +1 -1
- package/dist/components/skeleton.d.ts +4 -0
- package/dist/components/skeleton.d.ts.map +1 -1
- package/dist/components/skeleton.js +5 -1
- package/dist/components/sonner.d.ts.map +1 -1
- package/dist/components/sonner.js +5 -2
- package/dist/components/table.js +1 -1
- package/dist/components/tabs.js +1 -1
- package/dist/components/toggle.js +1 -1
- package/dist/components/waiting-line.d.ts +30 -0
- package/dist/components/waiting-line.d.ts.map +1 -0
- package/dist/components/waiting-line.js +33 -0
- package/dist/eslint/rules/no-invalid-token-utility.js +1 -1
- package/dist/index.d.ts +3 -38
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -38
- package/dist/internal/agent-orb-motion.d.ts +9 -1
- package/dist/internal/agent-orb-motion.d.ts.map +1 -1
- package/dist/internal/agent-orb-motion.js +23 -11
- package/dist/internal/agent-orb.d.ts +14 -1
- package/dist/internal/agent-orb.d.ts.map +1 -1
- package/dist/internal/agent-orb.js +78 -22
- package/dist/internal/assistant-ui/attachment.d.ts.map +1 -1
- package/dist/internal/assistant-ui/attachment.js +3 -2
- package/dist/internal/assistant-ui/reasoning.d.ts.map +1 -1
- package/dist/internal/assistant-ui/reasoning.js +4 -4
- package/dist/internal/assistant-ui/tool-fallback.d.ts.map +1 -1
- package/dist/internal/assistant-ui/tool-fallback.js +5 -4
- package/dist/internal/assistant-ui/tool-group.d.ts.map +1 -1
- package/dist/internal/assistant-ui/tool-group.js +4 -3
- package/dist/lib/motion.d.ts +18 -4
- package/dist/lib/motion.d.ts.map +1 -1
- package/dist/lib/motion.js +18 -4
- package/dist/styles/globals.css +0 -1
- package/docs/activity.md +99 -119
- package/docs/agent-orb.md +71 -20
- package/docs/component-classification.md +4 -4
- package/docs/consuming-cross-repo.md +8 -10
- package/docs/contract.md +10 -9
- package/docs/icon-assets.md +106 -0
- package/docs/migration/10.0.0.md +144 -0
- package/package.json +8 -7
- package/dist/activity.d.ts +0 -2
- package/dist/activity.d.ts.map +0 -1
- package/dist/activity.js +0 -2
- package/dist/components/action-band.d.ts +0 -12
- package/dist/components/action-band.d.ts.map +0 -1
- package/dist/components/action-band.js +0 -48
- package/dist/components/activity-orb.d.ts +0 -21
- package/dist/components/activity-orb.d.ts.map +0 -1
- package/dist/components/activity-orb.js +0 -26
- package/dist/components/benefits-bento.d.ts +0 -15
- package/dist/components/benefits-bento.d.ts.map +0 -1
- package/dist/components/benefits-bento.js +0 -6
- package/dist/components/bento.d.ts +0 -39
- package/dist/components/bento.d.ts.map +0 -1
- package/dist/components/bento.js +0 -70
- package/dist/components/card-marketing.d.ts +0 -30
- package/dist/components/card-marketing.d.ts.map +0 -1
- package/dist/components/card-marketing.js +0 -48
- package/dist/components/code-editor-mockup.d.ts +0 -25
- package/dist/components/code-editor-mockup.d.ts.map +0 -1
- package/dist/components/code-editor-mockup.js +0 -47
- package/dist/components/contact.d.ts +0 -32
- package/dist/components/contact.d.ts.map +0 -1
- package/dist/components/contact.js +0 -46
- package/dist/components/faq-item.d.ts +0 -25
- package/dist/components/faq-item.d.ts.map +0 -1
- package/dist/components/faq-item.js +0 -25
- package/dist/components/faq.d.ts +0 -20
- package/dist/components/faq.d.ts.map +0 -1
- package/dist/components/faq.js +0 -23
- package/dist/components/feature-grid.d.ts +0 -23
- package/dist/components/feature-grid.d.ts.map +0 -1
- package/dist/components/feature-grid.js +0 -33
- package/dist/components/feature-rows.d.ts +0 -23
- package/dist/components/feature-rows.d.ts.map +0 -1
- package/dist/components/feature-rows.js +0 -27
- package/dist/components/glyph-spinner.d.ts +0 -10
- package/dist/components/glyph-spinner.d.ts.map +0 -1
- package/dist/components/glyph-spinner.js +0 -101
- package/dist/components/hero-split.d.ts +0 -23
- package/dist/components/hero-split.d.ts.map +0 -1
- package/dist/components/hero-split.js +0 -35
- package/dist/components/hero.d.ts +0 -28
- package/dist/components/hero.d.ts.map +0 -1
- package/dist/components/hero.js +0 -45
- package/dist/components/integration-flow.d.ts +0 -36
- package/dist/components/integration-flow.d.ts.map +0 -1
- package/dist/components/integration-flow.js +0 -36
- package/dist/components/live-demo.d.ts +0 -31
- package/dist/components/live-demo.d.ts.map +0 -1
- package/dist/components/live-demo.js +0 -30
- package/dist/components/logo-band.d.ts +0 -33
- package/dist/components/logo-band.d.ts.map +0 -1
- package/dist/components/logo-band.js +0 -49
- package/dist/components/logo-tile.d.ts +0 -21
- package/dist/components/logo-tile.d.ts.map +0 -1
- package/dist/components/logo-tile.js +0 -28
- package/dist/components/media-mount.d.ts +0 -13
- package/dist/components/media-mount.d.ts.map +0 -1
- package/dist/components/media-mount.js +0 -15
- package/dist/components/nav-bar.d.ts +0 -24
- package/dist/components/nav-bar.d.ts.map +0 -1
- package/dist/components/nav-bar.js +0 -35
- package/dist/components/newsletter.d.ts +0 -24
- package/dist/components/newsletter.d.ts.map +0 -1
- package/dist/components/newsletter.js +0 -31
- package/dist/components/page-frame.d.ts +0 -30
- package/dist/components/page-frame.d.ts.map +0 -1
- package/dist/components/page-frame.js +0 -30
- package/dist/components/pricing-card.d.ts +0 -30
- package/dist/components/pricing-card.d.ts.map +0 -1
- package/dist/components/pricing-card.js +0 -44
- package/dist/components/pricing.d.ts +0 -25
- package/dist/components/pricing.d.ts.map +0 -1
- package/dist/components/pricing.js +0 -11
- package/dist/components/proof-slot.d.ts +0 -8
- package/dist/components/proof-slot.d.ts.map +0 -1
- package/dist/components/proof-slot.js +0 -8
- package/dist/components/quote-card.d.ts +0 -31
- package/dist/components/quote-card.d.ts.map +0 -1
- package/dist/components/quote-card.js +0 -48
- package/dist/components/seam-grid.d.ts +0 -30
- package/dist/components/seam-grid.d.ts.map +0 -1
- package/dist/components/seam-grid.js +0 -30
- package/dist/components/section-intro.d.ts +0 -18
- package/dist/components/section-intro.d.ts.map +0 -1
- package/dist/components/section-intro.js +0 -22
- package/dist/components/security-grid.d.ts +0 -25
- package/dist/components/security-grid.d.ts.map +0 -1
- package/dist/components/security-grid.js +0 -28
- package/dist/components/shift-band.d.ts +0 -14
- package/dist/components/shift-band.d.ts.map +0 -1
- package/dist/components/shift-band.js +0 -11
- package/dist/components/spinner.d.ts +0 -3
- package/dist/components/spinner.d.ts.map +0 -1
- package/dist/components/spinner.js +0 -7
- package/dist/components/statement.d.ts +0 -32
- package/dist/components/statement.d.ts.map +0 -1
- package/dist/components/statement.js +0 -40
- package/dist/components/steps.d.ts +0 -34
- package/dist/components/steps.d.ts.map +0 -1
- package/dist/components/steps.js +0 -40
- package/dist/components/team-grid.d.ts +0 -27
- package/dist/components/team-grid.d.ts.map +0 -1
- package/dist/components/team-grid.js +0 -30
- package/dist/components/testimonials.d.ts +0 -48
- package/dist/components/testimonials.d.ts.map +0 -1
- package/dist/components/testimonials.js +0 -58
- package/dist/components/texture-strip.d.ts +0 -22
- package/dist/components/texture-strip.d.ts.map +0 -1
- package/dist/components/texture-strip.js +0 -32
- package/dist/components/use-case-bento.d.ts +0 -13
- package/dist/components/use-case-bento.d.ts.map +0 -1
- package/dist/components/use-case-bento.js +0 -8
- package/dist/internal/activity-orb.d.ts +0 -27
- package/dist/internal/activity-orb.d.ts.map +0 -1
- package/dist/internal/activity-orb.js +0 -150
- package/dist/lib/seam.d.ts +0 -29
- package/dist/lib/seam.d.ts.map +0 -1
- package/dist/lib/seam.js +0 -30
package/docs/activity.md
CHANGED
|
@@ -1,133 +1,113 @@
|
|
|
1
1
|
# System activity
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
The system activity family has three motions. They describe ongoing system
|
|
6
|
-
operations across the website, Portal and Nadia. They do not represent an
|
|
7
|
-
Agent's identity, attention or personality. The separate [AgentOrb](agent-orb.md)
|
|
8
|
-
uses seven of the same upstream geometries for persistent identity, with one
|
|
9
|
-
chosen pigment instead of the system activity palette.
|
|
10
|
-
|
|
11
|
-
| Activity | Use when | Library motion |
|
|
12
|
-
| --- | --- | --- |
|
|
13
|
-
| `loading` | Retrieving or revealing content: opening a workspace, fetching records, refreshing a view, retrieving search results. | `composing`: flowing dotted bands wrap around a globe, shown as “Thinking…” in the library's large demo. |
|
|
14
|
-
| `connecting` | Actively establishing or restoring communication with an account, service or device. | `connecting`: links form between nodes and carry signals. |
|
|
15
|
-
| `processing` | Carrying out an operation: saving, submitting, applying changes, validating, importing, preparing an export, reconciling a sync, or other unmeasured work. | `working`: particles travel on tilted orbits. |
|
|
16
|
-
|
|
17
|
-
These are three NadicodeAI activity treatments, not a claim that every design
|
|
18
|
-
system defines these categories. The label names the specific operation;
|
|
19
|
-
people are never expected to decode particle movement alone.
|
|
20
|
-
|
|
21
|
-
## Choose the feedback
|
|
22
|
-
|
|
23
|
-
An operation's purpose selects the orb; the endpoint, worker or request type
|
|
24
|
-
does not. Retrieving search results is `loading`. Establishing the connection
|
|
25
|
-
before that request is `connecting`. A working connection remains a settled
|
|
26
|
-
status while data loads. Synchronizing records after connection is
|
|
27
|
-
`processing`; reconnecting during sync temporarily uses `connecting`.
|
|
28
|
-
|
|
29
|
-
Saving is `processing`, not a fourth activity. Uploading, downloading,
|
|
30
|
-
installing and converting use the existing `Progress` component when the
|
|
31
|
-
completed amount can be measured. For an unmeasured preparation phase, use
|
|
32
|
-
`processing`. When progress will become measurable, reserve a progress
|
|
33
|
-
treatment from the start so the transition does not move the layout. Never
|
|
34
|
-
invent a percentage or surround an indeterminate orb with a simulated fill.
|
|
35
|
-
|
|
36
|
-
Queued, paused, offline, blocked, successful and failed conditions use the
|
|
37
|
-
existing status or action-feedback treatment. A request waiting for a person
|
|
38
|
-
does not keep an orb moving. A retry uses `connecting` only while an actual
|
|
39
|
-
connection attempt is in progress; its failure or recovery replaces activity
|
|
40
|
-
with the appropriate feedback. An account being active is not an activity.
|
|
41
|
-
|
|
42
|
-
Use the indicator beside the operation it describes. Keep the rest of the
|
|
43
|
-
interface available. One operation gets one indicator; separately progressing
|
|
44
|
-
operations can each have one. For content with a predictable layout, prefer
|
|
45
|
-
`Skeleton` or retained content over replacing the region with an orb. Do not
|
|
46
|
-
show both a skeleton and a central orb for the same wait.
|
|
47
|
-
|
|
48
|
-
## Brand treatment
|
|
49
|
-
|
|
50
|
-
All three reuse `thinking-orbs` 0.3.1 (MIT). Their geometry, depth ordering and
|
|
51
|
-
size-specific density remain the library's. NadicodeAI adapts the palette and
|
|
52
|
-
clock, not the rendering engine.
|
|
53
|
-
|
|
54
|
-
The structure inherits the surrounding text's neutral ink. Foreground and
|
|
55
|
-
signal particles carry the existing cobalto `--nc-info` role, mixed with that
|
|
56
|
-
ink to preserve contrast in either appearance. Depth fades into the actual
|
|
57
|
-
surface through transparency. There are no activity-specific colours: cobalto
|
|
58
|
-
means work underway throughout the family. Green, amber and red retain their
|
|
59
|
-
settled feedback meanings. Controls and panel backgrounds remain neutral.
|
|
60
|
-
|
|
61
|
-
The selected clock multipliers are 0.92 for loading, 0.86 for connecting and
|
|
62
|
-
0.92 for processing, applied to each original size-specific preset. The
|
|
63
|
-
connection animation is slightly quieter because its forming links add
|
|
64
|
-
movement as well as its travelling particles. The implementation owns these
|
|
65
|
-
values together; consumers cannot tune speed, density or particle colours.
|
|
66
|
-
|
|
67
|
-
Use 20 CSS pixels inline, including buttons and rows with room for that size;
|
|
68
|
-
64 for a contained region; 88 on an application's entry screen. The 20 preset is
|
|
69
|
-
separately tuned, and must not be obtained by shrinking the 64 preset. The 88
|
|
70
|
-
extent uses the 64 preset. A 12–16 pixel badge slot keeps its existing compact
|
|
71
|
-
spinner until its surrounding component explicitly accommodates this family.
|
|
72
|
-
Nadia's desktop accommodates it once, in the spinner itself: the spinner's box
|
|
73
|
-
stays one text line tall and at least 20 pixels wide, and the 20 pixel orb sits
|
|
74
|
-
centred in it and overhangs it above and below, so a row keeps its height and
|
|
75
|
-
the orb never meets the text beside it.
|
|
76
|
-
|
|
77
|
-
## React
|
|
3
|
+
Who does the work decides how it looks.
|
|
78
4
|
|
|
79
|
-
|
|
80
|
-
|
|
5
|
+
An Agent's work shows that Agent's orb in its state and a sentence saying what
|
|
6
|
+
it is doing; [AgentOrb](agent-orb.md) owns it, and Nadia connecting is her
|
|
7
|
+
ribbon, working. Everything on this page is the *system's* own work: a save, a
|
|
8
|
+
sign-in, a refresh, a page load. An orb means an Agent, so system work never
|
|
9
|
+
takes one.
|
|
81
10
|
|
|
82
|
-
|
|
11
|
+
| The wait | What it shows |
|
|
12
|
+
| --- | --- |
|
|
13
|
+
| Under about a second | The control's own label changes to its pending word. Nothing else. |
|
|
14
|
+
| Past a second | One `WaitingLine` beside the work, and nothing else moves. |
|
|
15
|
+
| Measurable | `Progress` with a written count ("120 di 240 fatture"). |
|
|
16
|
+
| A page load | `Skeleton` placeholders in the shape of the content, still. |
|
|
83
17
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
18
|
+
One wait gets one indicator. Separately progressing operations may each have
|
|
19
|
+
one. A request waiting for a person is not a wait: queued, paused, offline,
|
|
20
|
+
blocked, successful and failed conditions take the status or feedback
|
|
21
|
+
treatment. An account being active is not an activity.
|
|
22
|
+
|
|
23
|
+
## The pending label
|
|
24
|
+
|
|
25
|
+
The control keeps its place, its size and its icon; only its word changes, and
|
|
26
|
+
the caller marks the control `disabled` and `aria-busy` so the change is
|
|
27
|
+
announced as well as read.
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
import { PendingLabel } from "@nadicodeai/ui/components/pending-label";
|
|
88
31
|
|
|
89
|
-
<Button
|
|
90
|
-
{saving
|
|
91
|
-
|
|
32
|
+
<Button aria-busy={saving || undefined} disabled={saving} type="submit">
|
|
33
|
+
<PendingLabel pending={saving} pendingLabel="Salvataggio…">
|
|
34
|
+
Salva modifiche
|
|
35
|
+
</PendingLabel>
|
|
92
36
|
</Button>;
|
|
93
37
|
```
|
|
94
38
|
|
|
95
|
-
`
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
mean the underlying operation is paused. Product code unmounts the orb when
|
|
100
|
-
the operation ends or cannot proceed.
|
|
101
|
-
|
|
102
|
-
Nadia's initial HTML can use `mountActivityOrb(canvas, activity, size)` from
|
|
103
|
-
`@nadicodeai/ui/activity` before React loads. It is the renderer used by
|
|
104
|
-
`ActivityOrb`, with the same motion, palette and accessibility requirements.
|
|
105
|
-
The caller supplies the canvas and adjacent label, and calls `destroy()` when
|
|
106
|
-
the operation fails or React replaces the startup surface.
|
|
107
|
-
|
|
108
|
-
Import `@nadicodeai/ui/globals.css` as described in the
|
|
109
|
-
[consumer guide](consuming-cross-repo.md). The renderer inherits actual CSS
|
|
110
|
-
ink and reads canonical colour tokens. Nadia's entry screen wraps this renderer
|
|
111
|
-
in its own `Orb`, which fixes a dark appearance the shared renderer knows
|
|
112
|
-
nothing about; that wrapper lives in the desktop, not here.
|
|
113
|
-
|
|
114
|
-
## Accessibility and runtime
|
|
115
|
-
|
|
116
|
-
Reduced motion holds one representative frame and makes no animation requests.
|
|
117
|
-
A preference change takes effect while the component is mounted. The
|
|
118
|
-
operation's readable label remains. Pausing and resuming preserves the phase.
|
|
119
|
-
Offscreen or hidden activity stops rendering. Removing a component removes
|
|
120
|
-
its animation request and observers. DPR is capped at two. The renderer uses
|
|
121
|
-
Canvas 2D and requires no WebGL; without a 2D context, the accessible meaning
|
|
122
|
-
remains and the surrounding operation stays usable.
|
|
39
|
+
`pending` and `pendingLabel` are required; the children are the idle label. It
|
|
40
|
+
renders a `span` carrying `data-slot="pending-label"` and, while pending,
|
|
41
|
+
`data-pending="true"`. It adds no mark of its own: a control that had an icon
|
|
42
|
+
keeps that icon, unchanged, throughout the wait.
|
|
123
43
|
|
|
124
|
-
##
|
|
44
|
+
## The waiting line
|
|
45
|
+
|
|
46
|
+
A 2 px track of ink with a 32% segment crossing it linearly on the `wait`
|
|
47
|
+
token, after one second of waiting. Before that second the track is there and
|
|
48
|
+
empty, unannounced, so the line arriving moves nothing around it; a wait the
|
|
49
|
+
person barely notices does not deserve movement, and a control that flashed an
|
|
50
|
+
indicator for 200 ms reads as a glitch.
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
import { WaitingLine } from "@nadicodeai/ui/components/waiting-line";
|
|
54
|
+
|
|
55
|
+
<WaitingLine label="Caricamento delle fatture" />;
|
|
56
|
+
|
|
57
|
+
<div>
|
|
58
|
+
<p>Stiamo preparando il documento.</p>
|
|
59
|
+
<WaitingLine decorative />
|
|
60
|
+
</div>;
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
A meaningful standalone line takes `label` and announces itself as a status;
|
|
64
|
+
`decorative` removes its accessible name when the text beside it already says
|
|
65
|
+
what is happening. Width comes from the caller (`className="w-24"`, or the
|
|
66
|
+
full width of the region it belongs to); height, ink, segment and timing are
|
|
67
|
+
the component's and are not tunable. The one-second delay is
|
|
68
|
+
`WAITING_LINE_DELAY_MS`, exported so a test can name it rather than guess it.
|
|
69
|
+
|
|
70
|
+
Reduced motion drops the travel and breathes the full line in opacity, so a
|
|
71
|
+
wait still reads as a wait. The rule lives in
|
|
72
|
+
`packages/design-system/src/css/motion.css` as `.nc-anim-wait`, with the rest
|
|
73
|
+
of the motion vocabulary.
|
|
125
74
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
75
|
+
Product code unmounts the line when the operation ends or cannot proceed.
|
|
76
|
+
|
|
77
|
+
## Measurable and still
|
|
78
|
+
|
|
79
|
+
`Progress` carries work whose completed amount is known, always beside a
|
|
80
|
+
written count. When work will become measurable, reserve the progress
|
|
81
|
+
treatment from the start so the transition does not move the layout. Never
|
|
82
|
+
invent a percentage.
|
|
83
|
+
|
|
84
|
+
`Skeleton` is a still placeholder shaped like the content behind it. It does
|
|
85
|
+
not pulse. Do not show a skeleton and a waiting line for the same wait: the
|
|
86
|
+
placeholders already say the page is arriving.
|
|
87
|
+
|
|
88
|
+
## What retired
|
|
89
|
+
|
|
90
|
+
`ActivityOrb` and `mountActivityOrb`, `Spinner`, `GlyphSpinner`, Sonner's
|
|
91
|
+
spinning loading icon, the raw `LoaderCircle` spinners in `feedback-state`,
|
|
92
|
+
`installer-shell`, `automation-section` and `confirm-dialog`, the assistant-ui
|
|
93
|
+
attachment, tool-fallback and tool-group spinners, and the shimmer text on the
|
|
94
|
+
reasoning, tool-fallback and tool-group triggers. With them went the
|
|
95
|
+
`thinking-orbs` system-activity palette, the `tw-shimmer` dependency and the
|
|
96
|
+
duplicate `@utility shimmer`, and the unused `nc-anim-typing` and
|
|
97
|
+
`nc-anim-shimmer` hooks.
|
|
98
|
+
|
|
99
|
+
Where one of those marked a running state inside a component, the state is now
|
|
100
|
+
said in words and marked with a still glyph: an installer step and an
|
|
101
|
+
automation row take `CircleDotIcon`, and a running tool call says "Running
|
|
102
|
+
tool". A status badge never moves; its word and its mark carry the state.
|
|
103
|
+
|
|
104
|
+
## Ownership and source
|
|
130
105
|
|
|
131
|
-
The
|
|
106
|
+
The components own the delay, the geometry, the ink and the motion. The
|
|
107
|
+
application owns the request, the retry, the copy, the completion and the
|
|
108
|
+
recovery. The decision behind this page is
|
|
109
|
+
[the nadicode design system ADR](../../../docs/adr/2026-09-23-the-nadicode-design-system.md);
|
|
110
|
+
the design-system side of it is
|
|
111
|
+
[`DESIGN.md`, "## System activity"](../../design-system/DESIGN.md#system-activity).
|
|
132
112
|
The distinction between measured and unmeasured progress follows
|
|
133
113
|
[Apple's progress guidance](https://developer.apple.com/design/human-interface-guidelines/progress-indicators).
|
package/docs/agent-orb.md
CHANGED
|
@@ -16,7 +16,6 @@ uploads in Nadia is theirs, not an identity this package draws.
|
|
|
16
16
|
| `braid` | Interwoven strands | `weaving` |
|
|
17
17
|
| `morph` | Changing geometric contour | `shaping` |
|
|
18
18
|
|
|
19
|
-
**Target state** ([the nadicode design system ADR](../../../docs/adr/2026-09-23-the-nadicode-design-system.md)): an idle orb holds still and every surface passes the Agent's real state, so only a working Agent moves (#2260); under reduced motion a thinking or working orb breathes in opacity instead of freezing (#2260); the colours a person may choose are cobalto, verde and arancio beside the inherited default, and a stored rosso draws arancio, because rosso equals the error red (#2269). Until those land, the rest of this page describes what is built.
|
|
20
19
|
|
|
21
20
|
## Nadia
|
|
22
21
|
|
|
@@ -38,16 +37,30 @@ strings, server-safe so a server can resolve a row before it renders:
|
|
|
38
37
|
| Field | Stored as |
|
|
39
38
|
| --- | --- |
|
|
40
39
|
| `shape` | `orb:orbit`, `orb:ribbon`, `orb:lattice`, `orb:globe`, `orb:network`, `orb:braid`, `orb:morph` |
|
|
41
|
-
| `color` | The design system's identity hex of cobalto, verde
|
|
40
|
+
| `color` | The design system's identity hex of cobalto, verde or arancio, or null; or a rosso an Agent chose before rosso left the picker |
|
|
42
41
|
|
|
43
42
|
`resolveAgentOrb(stored, { root })` returns the form and colour to draw. The
|
|
44
43
|
root Agent is Nadia and draws `nadia` whatever is stored. An unknown or empty
|
|
45
44
|
shape draws `orbit`; an unknown or empty colour draws the inherited text
|
|
46
45
|
colour, which is also the default a picker's reset restores. Paint a colour
|
|
47
|
-
with `agentOrbColorTokens[color]`.
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
with `agentOrbColorTokens[color]`. Each retired `forma:` spelling resolves to
|
|
47
|
+
its own orb, so an Agent keeps a distinct look until someone changes it.
|
|
48
|
+
|
|
49
|
+
## The three colours
|
|
50
|
+
|
|
51
|
+
A person chooses cobalto, verde or arancio, or nothing, which leaves the orb
|
|
52
|
+
the inherited text colour. All three clear 3:1 against both the white and the
|
|
53
|
+
black canvas, so a chosen orb stays visible in either theme; giallo does not
|
|
54
|
+
(1.6:1 on white) and is not offered.
|
|
55
|
+
|
|
56
|
+
Rosso is not offered either. It is exactly the error red, so a red Agent beside
|
|
57
|
+
a red "Bloccato" badge read as a broken Agent rather than a chosen colour.
|
|
58
|
+
Nadia keeps rosso in her own stripes, where it is one of four and says nothing
|
|
59
|
+
on its own. An Agent that chose rosso before it left the picker keeps a colour:
|
|
60
|
+
`resolveAgentOrb` maps a stored `rosso`, by name or by the `#d3302f` hex, to
|
|
61
|
+
arancio, the nearest hue that is not a status. That is a mapping on the way in,
|
|
62
|
+
not an offer on the way out — `agentOrbColors` is what a picker shows, and it
|
|
63
|
+
has three entries.
|
|
51
64
|
|
|
52
65
|
The appearance is a person's choice, never derived: do not infer it from a name,
|
|
53
66
|
an id hash or a role. A machine check-in is not Agent activity, so a surface that
|
|
@@ -62,6 +75,7 @@ import { AgentOrb } from "@nadicodeai/ui/components/agent-orb";
|
|
|
62
75
|
|
|
63
76
|
<AgentOrb form="ribbon" color="var(--nc-identity-cobalto)" size={32} label="Research" />;
|
|
64
77
|
<AgentOrb form="nadia" size={32} label="Nadia" />;
|
|
78
|
+
<AgentOrb form="globe" presence="over-picture" size={96} state="working" label="Ricerca" />;
|
|
65
79
|
```
|
|
66
80
|
|
|
67
81
|
`form` is required. `color` accepts one CSS colour, including a customer-chosen
|
|
@@ -75,6 +89,15 @@ that single-colour identity, using the existing chart and warning tokens. Choose
|
|
|
75
89
|
colour visible on the intended background. A deliberately black pigment on a
|
|
76
90
|
black surface is not automatically recoloured.
|
|
77
91
|
|
|
92
|
+
A native startup screen paints an orb before React loads through
|
|
93
|
+
`mountAgentOrb(canvas, { form, size, presence, state, paused })` from
|
|
94
|
+
`@nadicodeai/ui/agent-orb`, the React-free entry beside
|
|
95
|
+
`@nadicodeai/ui/activity`. It is the renderer `AgentOrb` itself mounts, with
|
|
96
|
+
the same motion, states and presence; the caller supplies the canvas and the
|
|
97
|
+
adjacent name, and calls `destroy()` when React replaces the startup surface.
|
|
98
|
+
Import `@nadicodeai/ui/globals.css` with it: the renderer inherits the CSS ink
|
|
99
|
+
and reads the colour tokens from the element.
|
|
100
|
+
|
|
78
101
|
Sizes are 20, 24, 32, 40, 64, 96 and 160 CSS pixels. Menu sizes through 32 use
|
|
79
102
|
the upstream compact density; larger sizes use its detailed profile. `paused`
|
|
80
103
|
holds the current frame and resumes without resetting the appearance. An
|
|
@@ -84,16 +107,42 @@ API because the stock React component only offers monochrome light/dark ink,
|
|
|
84
107
|
not a configurable pigment.
|
|
85
108
|
|
|
86
109
|
Motion is limited to 30 painted frames per second. Offscreen and hidden orbs
|
|
87
|
-
stop scheduling animation.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
110
|
+
stop scheduling animation. Unmount removes the frame request and observers.
|
|
111
|
+
DPR is capped at two. Without Canvas 2D, the accessible name remains
|
|
112
|
+
available.
|
|
113
|
+
|
|
114
|
+
The engine paints the box the canvas occupies, not the `size` it was given: a
|
|
115
|
+
`ResizeObserver` follows the element, and the backing store and the geometry's
|
|
116
|
+
density profile both come from the measured CSS pixels. `size` sets that box
|
|
117
|
+
through `--nc-agent-orb-size` in a class, so a caller whose layout decides the
|
|
118
|
+
size overrides it with its own sizing class and the orb stays sharp at
|
|
119
|
+
whatever width it lands on. The declared size still stands in before layout
|
|
120
|
+
has measured anything, on a server render and in a test environment without
|
|
121
|
+
layout.
|
|
122
|
+
|
|
123
|
+
`presence` decides how loudly one orb reads on its ground, per mount, never
|
|
124
|
+
as a module setting: two orbs on one page can want different weights.
|
|
125
|
+
`plain`, the default, is the interface's own ink. `over-picture` multiplies
|
|
126
|
+
ink by 2.3 and every dot and line radius by 1.9, for an orb drawn on a
|
|
127
|
+
photograph, where the plain weights sink into the image. Nadia on open sky
|
|
128
|
+
keeps `plain`.
|
|
129
|
+
|
|
130
|
+
Reduced motion turns movement off and keeps opacity and colour. A thinking or
|
|
131
|
+
working orb breathes between full ink and 0.45 over 1.6 s, ease-in-out, so
|
|
132
|
+
busy still reads as busy; its geometry does not turn, and the state cue
|
|
133
|
+
breathes with the body. Every other state, idle, waiting, blocked and done
|
|
134
|
+
included, holds one still frame. The preference is observed live.
|
|
135
|
+
|
|
136
|
+
`state` accepts idle, working, waiting, blocked, thinking and done, and every
|
|
137
|
+
surface passes the Agent's real one: only Agents move on their own, so motion
|
|
138
|
+
on a screen means an Agent is working and a still orb means it is not. Idle
|
|
139
|
+
holds one still pose and schedules no frame after its first paint; a surface
|
|
140
|
+
that knows only check-ins draws idle, because a machine check-in is not Agent
|
|
141
|
+
activity. Geometry and state gestures have separate clocks. Each form has its
|
|
142
|
+
own geometry pace, shared across avatar sizes, which Working and Thinking
|
|
143
|
+
keep; Morph holds a contour for about 1.6 seconds and changes it over one
|
|
144
|
+
second. Waiting holds its pose; Blocked makes one gentle interrupted effort
|
|
145
|
+
and stops.
|
|
97
146
|
V7 keeps the material free-standing and intact:
|
|
98
147
|
no gear, thought bubble, pause, exclamation mark or check is cut into the form.
|
|
99
148
|
Working and Thinking preserve the native geometry: do not stretch, flatten,
|
|
@@ -104,14 +153,16 @@ with sequential opacity and slight size pulses on a 3.6-second loop.
|
|
|
104
153
|
The distinct symbols remain visible throughout both cycles. Done repeats
|
|
105
154
|
the ribbon in three celebratory sweeps and then rests. Changing `motionKey`
|
|
106
155
|
replays it. These exterior cues use the celebration palette; the body keeps
|
|
107
|
-
its configured pigment.
|
|
156
|
+
its configured pigment.
|
|
108
157
|
No state has an enclosing circle. Keep a nearby status label where exact
|
|
109
158
|
state identification matters, including reduced motion and compact sizes.
|
|
110
|
-
Reduced motion holds the state pose and skips the celebration.
|
|
111
159
|
|
|
112
160
|
In the Portal, [`agent-identity.tsx`](../../../apps/portal/src/components/agent-identity.tsx)
|
|
113
161
|
draws every Agent, in its lists, Agent workspace and the sign-in, sign-up and
|
|
114
|
-
Get Nadia pages
|
|
115
|
-
|
|
162
|
+
Get Nadia pages, and `src/lib/agent-orb.ts` maps what a machine reported to
|
|
163
|
+
the state drawn. It also gives an orb a `travelId`, which wraps it in React's
|
|
164
|
+
`<ViewTransition>` so the same orb travels from a list row into the Agent's
|
|
165
|
+
page; `apps/portal/docs/design-doctrine.md` owns that rule. Inspect them in
|
|
166
|
+
the running local Portal for compact and full-size appearances.
|
|
116
167
|
|
|
117
168
|
[Upstream library and presets](https://libraries.dev/orbs), MIT licensed.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
This file records the ownership class for U4 product compositions. The package may render standard product UI, but consuming apps own app behavior, data, persistence, and product-specific promises.
|
|
4
4
|
|
|
5
5
|
If first-party shadcn or assistant-ui registry source already covers the same
|
|
6
|
-
generic product UI, do not add a parallel
|
|
6
|
+
generic product UI, do not add a parallel nadicode package API. Use the
|
|
7
7
|
registry item in the consuming app and adapt it there with app-owned data,
|
|
8
8
|
copy, and behavior.
|
|
9
9
|
|
|
@@ -20,8 +20,8 @@ copy, and behavior.
|
|
|
20
20
|
| Component | Classification | Built on | Required states | Package-owned accessibility | Fixture |
|
|
21
21
|
| --- | --- | --- | --- | --- | --- |
|
|
22
22
|
| `ActionMenu` | Canonical record-action composition. | shadcn `Button` and `DropdownMenu`. | closed, open, keyboard selection, focus return. | Required accessible trigger name; inherited menu mechanics. | `../src/components/action-menu.test.tsx` |
|
|
23
|
-
| `SettingsSection` |
|
|
24
|
-
| `SettingsField` |
|
|
23
|
+
| `SettingsSection` | nadicode product composition. | shadcn Card slots, Separator, and FieldGroup. | header, field group, and divided action footer. | Section structure; consumer owns the form transaction. | `../src/components/settings-section.test.tsx` |
|
|
24
|
+
| `SettingsField` | nadicode product composition. | shadcn Field, FieldLabel, FieldDescription, and FieldError. | valid, invalid, required, and disabled field rows. | Render callback supplies the control's label and message associations in server and client components. | `../src/components/settings-section.test.tsx` |
|
|
25
25
|
| `FeedbackState` | Net-new central product state composition adapted from shadcn empty-state patterns. | shadcn `Empty` and lucide status icons. | `empty`, `loading`, `saving`, `error`, `permission`, `offline`, `no-results`, `fatal`. | `role="status"` for loading/saving; `role="alert"` for error, permission, offline, and fatal. | `../tests/guards/product-compositions.test.ts` |
|
|
26
26
|
|
|
27
27
|
## App-Owned Boundaries
|
|
@@ -36,7 +36,7 @@ Keep these out of `@nadicodeai/ui`:
|
|
|
36
36
|
|
|
37
37
|
## Fixture Guidance
|
|
38
38
|
|
|
39
|
-
U4 fixtures should use
|
|
39
|
+
U4 fixtures should use nadicode-relevant work objects:
|
|
40
40
|
|
|
41
41
|
- briefing agents, review agents, approval queues, sessions, models, workspace defaults, files, pairing codes, and weekly approvals;
|
|
42
42
|
- controlled state examples for sorting, selection, visibility, validation, loading, saving, offline, permission, and fatal states;
|
|
@@ -82,22 +82,20 @@ the same value. Consumers may compose domain-specific components from the
|
|
|
82
82
|
public UI package; the rules govern package boundaries and design values, not
|
|
83
83
|
the shape of a consumer's JSX tree.
|
|
84
84
|
|
|
85
|
-
##
|
|
85
|
+
## nadicode logo
|
|
86
86
|
|
|
87
|
-
React surfaces
|
|
88
|
-
horizontal lockup from the UI package:
|
|
87
|
+
React surfaces name the company with the wordmark from the UI package:
|
|
89
88
|
|
|
90
89
|
```tsx
|
|
91
|
-
import {
|
|
90
|
+
import { BrandWordmark } from "@nadicodeai/ui/components/brand";
|
|
92
91
|
|
|
93
|
-
<
|
|
92
|
+
<BrandWordmark alt="nadicode" />;
|
|
94
93
|
```
|
|
95
94
|
|
|
96
|
-
Use `BrandMark
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
`packages/design-system/README.md`.
|
|
95
|
+
Use `BrandMark`, the plain n, where the name does not fit. The n is cut from the
|
|
96
|
+
wordmark, so never place the two together. Static consumers that need files
|
|
97
|
+
instead of React declare the design-system dependency directly and use the
|
|
98
|
+
documented SVG or PNG package routes in `packages/design-system/README.md`.
|
|
101
99
|
|
|
102
100
|
## Base UI API breaks (migrating from Radix-era components)
|
|
103
101
|
|
package/docs/contract.md
CHANGED
|
@@ -7,7 +7,7 @@ The normative invariants for the `@nadicodeai/ui` package: what may live here, h
|
|
|
7
7
|
- **Token-only, no raw literals or shadow aliases.** Components style through semantic shadcn utilities (`bg-background`, `text-foreground`, `border-input`, and the rest), or a canonical generated design-system token when no standard role is precise enough. The UI package does not mint screen-, component-, or product-specific color aliases. No raw `#hex` / `rgb()` / `hsl()` may appear in `.tsx`; a new source value goes to `packages/design-system/DESIGN.md` first and flows through generated output. A narrow protocol adapter may translate third-party classes directly to canonical tokens in `globals.css`, but it must not create another token vocabulary. Enforced by the raw-colour `no-restricted-syntax` selectors in the library ESLint config, `packages/ui/tests/guards/dark-semantic-roles.test.ts`, and `packages/ui/tests/guards/token-reference-integrity.test.ts`.
|
|
8
8
|
- **Dark-ready semantics, no component dark implementation.** Components use the same semantic role or canonical mode-aware token in every mode. They must not ship Tailwind `dark:` color utilities, component-local `.dark` blocks, OS dark-mode branching, or raw dark palette utilities such as `dark:bg-slate-950` and `dark:text-white`. An intentionally fixed-presentation technology surface, such as the dark terminal console, selects canonical fixed-mode tokens as one coherent component treatment rather than branching by app theme. Enforced by `packages/ui/tests/guards/no-dark.test.ts`, `packages/ui/tests/guards/dark-semantic-roles.test.ts`, and `packages/ui/tests/guards/token-reference-integrity.test.ts`. The generated mode and theme architecture lives only in [`packages/design-system/DESIGN.md`](../../design-system/DESIGN.md#css-architecture--token-pipeline).
|
|
9
9
|
- **Components inherit one complete React style interface.** `@nadicodeai/ui/globals.css` composes every style dependency owned by this package, including the complete design-system CSS module. Components carry no theme of their own, and React callers do not compose design-system stylesheets or partials beside it. Installation and source-scanning setup live in the [consumer setup guide](consuming-cross-repo.md). The package ships two stylesheets, split by who owns the page. `@nadicodeai/ui/globals.css` is for an application this design system styles whole: it imports Tailwind, the complete design system with its reset and base layer, and the second file. `@nadicodeai/ui/components.css` is for a host that already runs Tailwind over base styles of its own, such as the Nadia desktop inside Hermes's shell: it carries the `@source` lines, the `nc-*` utilities and the component-owned rules, and nothing that lands on a page. That host imports `@nadicodeai/design-system/css/host` before it, which adds the Tailwind keys only this design system names and leaves the host its shadcn roles, its radius scale and its palette. The components render in both from one source, which is what keeps the products consistent. A surface that loads no Tailwind layer takes the design system's token artifact and writes its own rules against it.
|
|
10
|
-
- **Design-system geometry remains the foundation.** React components compose the
|
|
10
|
+
- **Design-system geometry remains the foundation.** React components compose the shipped `nc-*` layout and display CSS components; they do not redefine the website's content column, its gutters, its step between sections, token values, or raw CSS geometry. Use parent-paints-plus-gap for bordered cell grids and keep every visible seam single-owner (doctrine home: `packages/design-system/DESIGN.md` "## Layout").
|
|
11
11
|
|
|
12
12
|
### Persistent notices
|
|
13
13
|
|
|
@@ -136,14 +136,15 @@ gone, is [`packages/design-system/DESIGN.md`, "## Status Vocabulary"](../../desi
|
|
|
136
136
|
|
|
137
137
|
## Package Shape Invariants
|
|
138
138
|
|
|
139
|
-
System activity
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
139
|
+
System activity is `PendingLabel` under a second, `WaitingLine` past one,
|
|
140
|
+
`Progress` with a written count when the amount is known, and a still
|
|
141
|
+
`Skeleton` for a page load; [activity.md](activity.md) owns selection,
|
|
142
|
+
rendering and accessibility. An orb means an Agent, so no system wait takes
|
|
143
|
+
one, and nothing here carries an outcome state.
|
|
143
144
|
|
|
144
145
|
- **Source-authored, built package.** Components are authored as shadcn-style source in `src/`, then emitted to `dist/` for consumption by other apps. Package exports must point at built JS, declarations, and CSS, never raw `src/*.tsx`, and `npm pack --dry-run` must include only intentional consumer artifacts.
|
|
145
146
|
- **Package surface is source-backed.** Public components stay flat under `src/components/`. Reviewed registry source under `src/internal/` is implementation, not a package namespace. Do not add top-level exports for recipes, blocks, agent, terminal, or vendor groupings unless a later package API decision adds concrete public source, built files, docs, and tests in the same change.
|
|
146
|
-
- **Agents is the client-only conversation interface.** `@nadicodeai/ui/agents` re-exports the complete `@assistant-ui/react` runtime and primitive API plus the reviewed, branded registry composition held under `src/internal/assistant-ui/`. Its built entry retains `"use client"`. Consumers receive Thread, attachments, Markdown, reasoning, tools, suggestions, providers, runtimes, hooks, and types from that one domain namespace. Agent identity components use their direct component subpaths so server compositions do not import the conversation runtime. The vendor name is not a public
|
|
147
|
+
- **Agents is the client-only conversation interface.** `@nadicodeai/ui/agents` re-exports the complete `@assistant-ui/react` runtime and primitive API plus the reviewed, branded registry composition held under `src/internal/assistant-ui/`. Its built entry retains `"use client"`. Consumers receive Thread, attachments, Markdown, reasoning, tools, suggestions, providers, runtimes, hooks, and types from that one domain namespace. Agent identity components use their direct component subpaths so server compositions do not import the conversation runtime. The vendor name is not a public nadicode subpath, and the package does not rename, wrap, or rebuild assistant-ui behavior.
|
|
147
148
|
- **Base UI is the active primitive base.** `components.json` must resolve through a Base style, currently `base-nova`, and `npx shadcn@latest info --json` must report `base: "base"`. Do not reintroduce `radix-ui`, `@radix-ui/*`, or `vaul` to package source, dependencies, or app optimizer configuration. Registry-owned shadcn primitives stay aligned with current `shadcn@latest` Base UI output; use Base UI `render` composition instead of Radix `asChild`. `cmdk` is allowed only for the stock shadcn Command component while the current `base-nova` registry declares that dependency; do not use it elsewhere or replace it without a shadcn/compatibility decision and tests.
|
|
148
149
|
- **Charts are stock shadcn charts.** Every chart and KPI here is a registry item, changed as little as possible: `chart.tsx` is shadcn's `chart` over Recharts; `chart-bar-stacked`, `chart-area-stacked`, `chart-bar-multiple`, and `chart-bar-horizontal` are the blocks of those names; `chart-sparkline` is `chart-line-linear` stripped of its card, axes, grid and tooltip; `kpi-card` is the `dashboard-01` block's section card; `chart-card` is their shared Card frame. Each pulled file names its registry item on line one. `base-nova` does not publish the chart gallery and the CLI search does not list it, so a chart the kit lacks is pulled from `https://ui.shadcn.com/r/styles/new-york-v4/<name>.json` (`files[0].content`) and added here. What deviates from stock, and why, is listed once in [`DESIGN.md`, "Chart source"](../../design-system/DESIGN.md#chart-source); a change to a pulled chart that is not on that list is drift. There is no hidden table twin, no mark inside a legend, and no second axis. Every chart component renders the whole card — `Card > CardHeader(CardTitle, CardDescription, CardAction) > CardContent(ChartContainer) > CardFooter?` — at a fixed plot height (`h-64`, `h-80` at `size="lg"`), legend below the plot, left-aligned and wrapping. An app composes these, never builds a chart card frame by hand, and never imports `recharts`, which this package alone declares. Which chart a reading question deserves is owned by [`skills/design/product-design/references/charts.md`](../../../skills/design/product-design/references/charts.md).
|
|
149
150
|
|
|
@@ -152,7 +153,7 @@ states to the orb.
|
|
|
152
153
|
|
|
153
154
|
## Admission Rules
|
|
154
155
|
|
|
155
|
-
Assistant conversation and runtime APIs enter through `@nadicodeai/ui/agents`; Agent identity enters through `@nadicodeai/ui/components/agent-orb`, its stored-appearance resolver `@nadicodeai/ui/components/agent-orb-appearance` (both owned by [`agent-orb.md`](agent-orb.md)), and `@nadicodeai/ui/components/agent-card`. The consuming application still constructs the runtime and owns transport, persistence, permissions, tools, approvals, and failure policy. Shared non-Agent product components (a shell, a settings surface, a generic section, a diff, or a file preview) are admitted only with a named consuming surface landing in the same change. App-bespoke UI and behavior (window chrome, PTY/xterm embeds, queues, approvals, and persistence) stay in the consuming app; they never become package abstractions. A component left unconsumed after its target migration ships gets removed.
|
|
156
|
+
Assistant conversation and runtime APIs enter through `@nadicodeai/ui/agents`; Agent identity enters through `@nadicodeai/ui/components/agent-orb`, its stored-appearance resolver `@nadicodeai/ui/components/agent-orb-appearance` (both owned by [`agent-orb.md`](agent-orb.md)), and `@nadicodeai/ui/components/agent-card`. `@nadicodeai/ui/agent-orb` and `@nadicodeai/ui/activity` are the two React-free entries: each exports the canvas renderer its component mounts, for a native startup screen that paints before React loads, and neither may import React. The consuming application still constructs the runtime and owns transport, persistence, permissions, tools, approvals, and failure policy. Shared non-Agent product components (a shell, a settings surface, a generic section, a diff, or a file preview) are admitted only with a named consuming surface landing in the same change. App-bespoke UI and behavior (window chrome, PTY/xterm embeds, queues, approvals, and persistence) stay in the consuming app; they never become package abstractions. A component left unconsumed after its target migration ships gets removed.
|
|
156
157
|
|
|
157
158
|
### Placement
|
|
158
159
|
|
|
@@ -177,8 +178,8 @@ product-domain `agent` object prop in the shared package.
|
|
|
177
178
|
|
|
178
179
|
- **Standard components, not app-owned product features.** This package ships primitives, standard UI components, assistant-ui compositions, brand adapters, React adapters, reusable sections, and presentational product components. It must not ship app-specific feature/use-case screens or names such as operator-login, portal activation, customer credential control, or customer management. Domain registries, command search providers, and chart dashboards bind app data and routes in the app; that binding is not a reason to copy reusable presentation. Portal's DataTable owns its Next.js query and registry protocol once, while consuming the shared UI foundation. Product-independent compositions belong here with a real consumer. The source-backed `chart-*` and `kpi-card` package surface is the plan-approved exception per issue #166; apps select charts and bind their titles, data, and navigation. A chart is named by the card title above it and navigated through Recharts' own accessibility layer; the kit ships no hidden table twin, because a component whose complete value is already available in visible text or `aria-valuetext` does not add a redundant table.
|
|
179
180
|
- **Auth routes are consumer-owned shadcn block work.** Login, signup, OTP, two-factor, magic-link, and provider-button flows start from the selected shadcn block/example in the consuming app, with app-owned Better Auth behavior. Do not ship generic auth, signup, OTP, federated-login, or provider abstractions from this package unless a later explicit boundary decision replaces the selected shadcn block.
|
|
180
|
-
- **Reusable sections and compositions live here after proof.**
|
|
181
|
-
- **Brand renderers live here for React consumers.** Logo geometry, asset generation, and usage semantics are owned by [`packages/design-system/DESIGN.md`, "Brand media authority"](../../design-system/DESIGN.md#brand-media-authority). `
|
|
181
|
+
- **Reusable sections and compositions live here after proof.** Media mounts, demo surfaces, section intros, CTA bands, proof slots, generic shells, and homepage/use-case sections belong in `@nadicodeai/ui` when a second concrete consumer, a plan-approved shared component, or a named validation slice proves the package boundary. Website, portal, and sibling Nadia routes pass data and media children into existing compositions instead of rebuilding layout locally.
|
|
182
|
+
- **Brand renderers live here for React consumers.** Logo geometry, asset generation, and usage semantics are owned by [`packages/design-system/DESIGN.md`, "Brand media authority"](../../design-system/DESIGN.md#brand-media-authority). `BrandWordmark` names the company and `BrandMark` is the plain n, for placements where the name does not fit. There is no lockup adapter: the n is cut from the wordmark, so a placement carrying both would draw the letter twice, and `tests/brand-logo-usage.test.ts` fails on one. Both render the package's public neutral geometry seam, which emits no DOM id, with dynamic theme paint and accessible names. Consuming routes use these adapters; they never import raw logo assets, draw brand SVG inline, mask or recolor assets, or compose a new logo form.
|
|
182
183
|
- **Third-party brand marks are generated, never hand-drawn and never hand-edited.** Other companies' marks live in `packages/ui/src/components/brand-icons/`, emitted from an explicit allow-list by `packages/ui/scripts/build-brand-icons.mjs` and exported through the `@nadicodeai/ui/components/brand-icons` subpath. They are identity images, not UI icons: a brand mark is exempt from the currentColor stroke system and from the raw-literal rule, it never stands in for a UI icon, and a UI icon never stands in for a brand. Marks drawn as one silhouette are stripped to `currentColor` by the generator; every other mark keeps its official colors verbatim. To add a brand, edit the generator's allow-list and run `npm run generate:brand-icons -w @nadicodeai/ui`; hand edits to the generated directory are lost and `packages/ui/tests/guards/brand-icons-codegen.test.ts` fails on them. Use is nominative only — naming a platform, an integration, or a provider — never adjacent to endorsement or partnership wording; that nominative posture is the licensing and trademark position, so a mark never appears where the copy implies endorsement.
|
|
183
184
|
The one script reads platform and app marks from the Iconify `logos` set (CC0-1.0), model identities from the LobeHub icon set (MIT, `@lobehub/icons-static-svg`), and a small reviewed supplemental set from the official or OpenRouter-published source recorded beside each input. Raster supplements are embedded into generated SVG components, so a consumer never fetches a logo at runtime. The emitted components carry no icon-data runtime dependency. The artwork itself does ship, so every upstream travels with its applicable licence or provenance notice in `LICENSES/` and `NOTICE`, and `tests/guards/brand-icons-codegen.test.ts` holds the allow-list to that: a new source cannot ship unattributed.
|
|
184
185
|
- **The house's own icons are Lucide components.** `@nadicodeai/ui/components/house-icons` exports `ArchIcon`, `ApprovalsIcon` and `AgentIcon`, built with lucide-react's `createLucideIcon` from the one geometry in `@nadicodeai/design-system/assets/house-icons`, so they take the `svg.lucide` house render and fit any `LucideIcon` slot. They name the company and its doors, work waiting on a person, and an Agent; a Lucide glyph never stands in for them. The render itself, a 1.5 px line held on screen and 1.25 px at 12 px, is `DESIGN.md` "Iconography".
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Icons as files
|
|
2
|
+
|
|
3
|
+
`@nadicodeai/ui` draws icons as React components. The same icons also ship as
|
|
4
|
+
plain SVG files, for a consumer that renders without React: a desktop shell, a
|
|
5
|
+
CSS mask, a mail template, an `<img>` tag.
|
|
6
|
+
|
|
7
|
+
Nothing in this set is drawn twice. Each brand file is its own committed
|
|
8
|
+
component rendered once at build time, and the house icons come from the static
|
|
9
|
+
set the design system generates, so a file and the component a page renders are
|
|
10
|
+
the same shapes.
|
|
11
|
+
|
|
12
|
+
## Where they are
|
|
13
|
+
|
|
14
|
+
| What | Path |
|
|
15
|
+
| --- | --- |
|
|
16
|
+
| Third-party brand marks | `@nadicodeai/ui/assets/brand/<slug>.svg` |
|
|
17
|
+
| The index over them | `@nadicodeai/ui/assets/brand/index.json` |
|
|
18
|
+
| The house's three icons | `@nadicodeai/design-system/icons/{arch,approvals,agent}.svg` |
|
|
19
|
+
| Lucide, under the house render | `@nadicodeai/design-system/icons/<name>.svg` |
|
|
20
|
+
|
|
21
|
+
`index.json` lists every brand mark, so the set's size is read from it rather
|
|
22
|
+
than copied into prose.
|
|
23
|
+
|
|
24
|
+
The house and Lucide icons live in the design system because that package owns
|
|
25
|
+
the static icon set (DESIGN.md `## Iconography`). `@nadicodeai/ui` pins it
|
|
26
|
+
exactly, so installing UI installs those files too. They are 24 px on Lucide's
|
|
27
|
+
24-unit grid, `fill="none"`, `stroke="currentColor"`, drawn with the house line
|
|
28
|
+
weight held on screen by `vector-effect="non-scaling-stroke"`.
|
|
29
|
+
|
|
30
|
+
A brand mark is an identity image, not a UI icon: it carries a third party's
|
|
31
|
+
artwork and is exempt from the stroke system. Each file is 24 px square, keeps
|
|
32
|
+
the brand's own colours, and names itself with `data-brand="<slug>"`. A mark the
|
|
33
|
+
set draws as one silhouette paints with `currentColor` instead, so it stays
|
|
34
|
+
visible on a dark surface; `index.json` says which marks those are. The files
|
|
35
|
+
carry no `aria-*` attributes: whoever places a mark labels it, or leaves it
|
|
36
|
+
decorative beside the text that names it.
|
|
37
|
+
|
|
38
|
+
## Resolving an app name
|
|
39
|
+
|
|
40
|
+
`index.json` is the set as data:
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"marks": [
|
|
45
|
+
{
|
|
46
|
+
"slug": "google-calendar",
|
|
47
|
+
"name": "Google Calendar",
|
|
48
|
+
"set": "app",
|
|
49
|
+
"mono": false,
|
|
50
|
+
"file": "google-calendar.svg",
|
|
51
|
+
"aliases": ["googlecalendar"]
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`set` says which allow-list the artwork was listed in: `platform`, `app`, or
|
|
58
|
+
`model`. `mono` is the silhouette rule above. `aliases` are the connector
|
|
59
|
+
spellings `appMarkFor` resolves to that mark, already squashed to lowercase
|
|
60
|
+
letters and digits.
|
|
61
|
+
|
|
62
|
+
To resolve a connector name the way `AppMark` does, squash the name the same
|
|
63
|
+
way and take an exact alias match; failing that, take the longest alias the
|
|
64
|
+
squashed name contains, so `GitHub MCP` is GitHub and never a shorter
|
|
65
|
+
accidental match. A name that matches nothing has no mark: show the app's
|
|
66
|
+
initial, never an invented logo and never a fetched favicon.
|
|
67
|
+
|
|
68
|
+
```js
|
|
69
|
+
import index from "@nadicodeai/ui/assets/brand/index.json" with { type: "json" };
|
|
70
|
+
|
|
71
|
+
const aliases = new Map(
|
|
72
|
+
index.marks.flatMap((mark) => mark.aliases.map((alias) => [alias, mark])),
|
|
73
|
+
);
|
|
74
|
+
const squash = (value) => value.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
75
|
+
|
|
76
|
+
export function markFor(app) {
|
|
77
|
+
const target = squash(app);
|
|
78
|
+
if (!target) return undefined;
|
|
79
|
+
if (aliases.has(target)) return aliases.get(target);
|
|
80
|
+
|
|
81
|
+
const alias = [...aliases.keys()]
|
|
82
|
+
.filter((key) => target.includes(key))
|
|
83
|
+
.sort((a, b) => b.length - a.length)[0];
|
|
84
|
+
return alias ? aliases.get(alias) : undefined;
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The table both sides read is `src/components/app-mark-aliases.ts`. Adding a
|
|
89
|
+
connector spelling there puts it in the next release's index.
|
|
90
|
+
|
|
91
|
+
## Keeping them true
|
|
92
|
+
|
|
93
|
+
`scripts/build-icon-assets.mjs` writes `dist/assets/brand/` as a build step, from
|
|
94
|
+
the built components and that alias table. There is nothing to regenerate by
|
|
95
|
+
hand and nothing committed to review: a new mark arrives by the ordinary route,
|
|
96
|
+
the allow-list in `scripts/build-brand-icons.mjs` and
|
|
97
|
+
`npm run generate:brand-icons -w @nadicodeai/ui`, and the files follow the
|
|
98
|
+
components it emits. `tests/guards/icon-assets.test.ts` rebuilds the set and
|
|
99
|
+
fails when the shipped files are not what the components render, when the index
|
|
100
|
+
does not name exactly the files beside it, or when an alias it publishes does
|
|
101
|
+
not resolve the way `appMarkFor` does.
|
|
102
|
+
|
|
103
|
+
## Nadia
|
|
104
|
+
|
|
105
|
+
Nadia's desktop reads these files by moving its exact pin on `@nadicodeai/ui` to
|
|
106
|
+
the release that carries them; nothing else in the package changes for it.
|