noecosystem-design 0.1.3 → 0.2.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/README.md +73 -35
- package/apps/showcase/src/catalog/catalog-index.tsx +3 -3
- package/apps/storybook/stories/catalog/card.stories.tsx +13 -0
- package/apps/storybook/stories/catalog/icon-system.stories.tsx +3 -2
- package/docs/adr/0006-icons8-icon-policy.md +4 -4
- package/docs/design-system/architecture.md +1 -1
- package/docs/design-system/ci-cd.md +22 -7
- package/docs/design-system/components.md +5 -0
- package/docs/design-system/foundations.md +9 -0
- package/docs/design-system/rtl.md +1 -1
- package/docs/design-system/surface-policy.md +59 -0
- package/llms.txt +1 -0
- package/package.json +1 -1
- package/packages/design-tokens/src/base.css +1 -1
- package/packages/design-tokens/src/tokens.css +12 -12
- package/packages/design-tokens/src/tokens.json +8 -8
- package/packages/design-tokens/src/tokens.mjs +8 -8
- package/packages/icons/package.json +3 -0
- package/packages/icons/src/adapters.tsx +4 -4
- package/packages/icons/src/iconsax.tsx +233 -0
- package/packages/icons/src/index.tsx +1 -103
- package/packages/registry/catalog-index.json +2 -2
- package/packages/registry/component-audit.json +1 -1
- package/packages/registry/docs-index.json +1 -1
- package/packages/registry/manifest.json +27 -14
- package/packages/registry/r/calendar.json +12 -1
- package/packages/registry/r/card.json +11 -5
- package/packages/registry/r/date-picker.json +12 -1
- package/packages/registry/r/icon-system.json +6 -1
- package/packages/registry/r/inline-cta.json +6 -1
- package/packages/registry/r/pagination.json +12 -1
- package/packages/registry/registry.json +8 -2
- package/packages/registry/search-index.json +21 -8
- package/packages/ui/src/card.tsx +14 -2
- package/packages/ui/src/theme-provider.browser.test.tsx +3 -2
- package/scripts/generate-manifest.mjs +92 -39
- package/scripts/validate-manifest.mjs +3 -29
- package/tests/e2e/catalog-typography.spec.ts +1 -2
- package/tests/icons.test.mjs +5 -5
- package/tests/tokens.test.mjs +14 -0
- package/apps/showcase/src/catalog/__screenshots__/catalog-shell.browser.test.tsx/filters-the-component-inventory-and-exposes-the-selected-audit-state-1.png +0 -0
- package/apps/showcase/src/catalog/__screenshots__/catalog-shell.browser.test.tsx/opens-a-component-detail-view-and-returns-to-the-grid-1.png +0 -0
- package/apps/showcase/src/catalog/__screenshots__/catalog-shell.browser.test.tsx/switching-locale-to-Persian-updates-document-direction-to-rtl-1.png +0 -0
- package/packages/ui/src/__screenshots__/button.browser.test.tsx/Button-preserves-native--busy--disabled--and-ref-contracts-1.png +0 -0
- package/packages/ui/src/__screenshots__/button.browser.test.tsx/a-disabled-polymorphic-Button-cannot-navigate-or-receive-focus-1.png +0 -0
- package/packages/ui/src/__screenshots__/date-picker.browser.test.tsx/DatePicker-Escape-closes-popover-and-returns-focus-to-input-1.png +0 -0
- package/packages/ui/src/__screenshots__/date-picker.browser.test.tsx/DatePicker-click-outside-closes-popover-1.png +0 -0
- package/packages/ui/src/__screenshots__/dialog.browser.test.tsx/Dialog-propagates-RTL-into-the-portal-and-traps-then-restores-focus-1.png +0 -0
package/README.md
CHANGED
|
@@ -1,21 +1,36 @@
|
|
|
1
1
|
# NOE Design System
|
|
2
2
|
|
|
3
|
-
NOE is a multilingual, bidirectional, theme-aware React design system.
|
|
4
|
-
|
|
5
|
-
registry metadata, reference apps, documentation, and verification
|
|
3
|
+
NOE is a multilingual, bidirectional, theme-aware React design system. The public
|
|
4
|
+
`noecosystem-design` package is an agent-readable source snapshot: semantic tokens,
|
|
5
|
+
component source, registry metadata, reference apps, documentation, and verification
|
|
6
|
+
contracts.
|
|
6
7
|
|
|
7
|
-
##
|
|
8
|
+
## Quick start
|
|
9
|
+
|
|
10
|
+
### Give a coding agent NOE context
|
|
8
11
|
|
|
9
12
|
```bash
|
|
10
|
-
# Give a coding agent the NOE source context.
|
|
11
13
|
npm install noecosystem-design
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The package is read-only source context, not a compiled runtime dependency. Start an
|
|
17
|
+
agent with these files, in this order:
|
|
12
18
|
|
|
13
|
-
|
|
19
|
+
```bash
|
|
14
20
|
cat node_modules/noecosystem-design/AGENTS.md
|
|
15
21
|
cat node_modules/noecosystem-design/llms.txt
|
|
16
22
|
cat node_modules/noecosystem-design/docs/design-system/gpt-agent-prompt.md
|
|
23
|
+
```
|
|
17
24
|
|
|
18
|
-
|
|
25
|
+
For GPT, copy
|
|
26
|
+
[`docs/design-system/gpt-agent-prompt.md`](docs/design-system/gpt-agent-prompt.md),
|
|
27
|
+
replace `<TARGET_REPOSITORY>` and `<DESCRIBE THE REQUESTED OUTCOME...>`, and send it
|
|
28
|
+
as one task. Keep the task section outcome-focused; the template already supplies
|
|
29
|
+
the stable NOE operating context.
|
|
30
|
+
|
|
31
|
+
### Work on NOE itself
|
|
32
|
+
|
|
33
|
+
```bash
|
|
19
34
|
git clone https://github.com/NOrchestration/noe-design-system.git
|
|
20
35
|
cd noe-design-system
|
|
21
36
|
corepack enable
|
|
@@ -24,38 +39,34 @@ pnpm check
|
|
|
24
39
|
```
|
|
25
40
|
|
|
26
41
|
Read [`AGENTS.md`](AGENTS.md) before changing code. Use [`llms.txt`](llms.txt) as the
|
|
27
|
-
retrieval map, then
|
|
28
|
-
catalog is [`packages/registry/manifest.json`](packages/registry/manifest.json).
|
|
42
|
+
retrieval map, then inspect the affected package and component records. The canonical
|
|
43
|
+
component catalog is [`packages/registry/manifest.json`](packages/registry/manifest.json).
|
|
29
44
|
|
|
30
|
-
|
|
31
|
-
[`docs/design-system/gpt-agent-prompt.md`](docs/design-system/gpt-agent-prompt.md),
|
|
32
|
-
replace `<TARGET_REPOSITORY>` and `<DESCRIBE THE REQUESTED OUTCOME...>`, and send it
|
|
33
|
-
as one task prompt. The template carries static NOE context once; put only the
|
|
34
|
-
requested outcome, scope, and non-negotiable constraints in its `Task` section.
|
|
45
|
+
## Package contract
|
|
35
46
|
|
|
36
|
-
|
|
47
|
+
| Use `noecosystem-design` for | Do not use it for |
|
|
48
|
+
| --- | --- |
|
|
49
|
+
| Giving an agent NOE source, rules, registry metadata, and examples | `import { Button } from "noecosystem-design"` |
|
|
50
|
+
| Reviewing or adapting NOE patterns in another repository | Replacing a published runtime component library |
|
|
51
|
+
| Finding reusable components before designing a new one | Assuming a public registry endpoint is deployed |
|
|
37
52
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
not published npm packages at this time.
|
|
43
|
-
- The shadcn-compatible `@noe` registry is locally generated and tested, but its
|
|
44
|
-
external site endpoint is not yet evidenced as deployed. Do not claim or assume
|
|
45
|
-
that `shadcn add @noe/<item>` works against the public domain.
|
|
53
|
+
Internal source packages use the `@noe/*` names. They are workspace boundaries, not
|
|
54
|
+
published npm packages. The shadcn-compatible `@noe` registry is locally generated
|
|
55
|
+
and tested, but its external endpoint is not deployment-proven; do not assume that
|
|
56
|
+
`shadcn add @noe/<item>` works against a public domain.
|
|
46
57
|
|
|
47
|
-
## Agent
|
|
58
|
+
## Agent workflow
|
|
48
59
|
|
|
49
60
|
1. Read `AGENTS.md`, then `llms.txt`.
|
|
50
|
-
2.
|
|
51
|
-
`
|
|
61
|
+
2. Locate the capability in `packages/registry/manifest.json`; read its `useWhen`,
|
|
62
|
+
`doNotUseWhen`, accessibility, i18n, and dependency contracts.
|
|
52
63
|
3. Reuse an existing `@noe` component before considering a foundation or new code.
|
|
53
|
-
4. Preserve semantic tokens, i18n, RTL/bidi, and portal
|
|
64
|
+
4. Preserve semantic tokens, i18n, RTL/bidi, and portal-direction contracts.
|
|
54
65
|
5. Update source, stories, tests, registry metadata, and documentation together.
|
|
55
|
-
6. Report only executed
|
|
56
|
-
|
|
66
|
+
6. Report only checks actually executed; local registry output is not evidence of a
|
|
67
|
+
deployed external installation path.
|
|
57
68
|
|
|
58
|
-
## Workspace
|
|
69
|
+
## Workspace checks
|
|
59
70
|
|
|
60
71
|
| Command | Purpose |
|
|
61
72
|
| --- | --- |
|
|
@@ -70,6 +81,28 @@ requested outcome, scope, and non-negotiable constraints in its `Task` section.
|
|
|
70
81
|
| `pnpm verify` | Registry, i18n, RTL, governance, and secret audits |
|
|
71
82
|
| `pnpm check` | Full local release gate |
|
|
72
83
|
|
|
84
|
+
## Automated npm publishing
|
|
85
|
+
|
|
86
|
+
The repository uses npm Trusted Publishing with GitHub Actions OIDC. After a change
|
|
87
|
+
is merged into `main`, the `ci` workflow must complete successfully before
|
|
88
|
+
[`publish.yml`](.github/workflows/publish.yml) publishes the package.
|
|
89
|
+
|
|
90
|
+
- Publishing uses short-lived OIDC credentials; no npm token is stored in GitHub.
|
|
91
|
+
- npm provenance attestations are unavailable while this GitHub repository is private.
|
|
92
|
+
- A version already present on npm is skipped, so a re-run cannot overwrite it.
|
|
93
|
+
- Bump the root `package.json` version before merging a release-worthy change.
|
|
94
|
+
- `workflow_dispatch` supports an intentional manual re-run from `main`.
|
|
95
|
+
|
|
96
|
+
The optional dependency-review job is disabled unless the repository variable
|
|
97
|
+
`ENABLE_DEPENDENCY_REVIEW` is set to `true` after Dependency Graph and GitHub
|
|
98
|
+
Advanced Security are enabled in repository settings.
|
|
99
|
+
|
|
100
|
+
CodeQL is similarly opt-in through `ENABLE_CODEQL=true`: first enable **Code
|
|
101
|
+
Security** for this private repository in GitHub’s security settings, then set the
|
|
102
|
+
variable. This avoids a misleading failed workflow when GitHub cannot accept SARIF
|
|
103
|
+
uploads. The workflows use Node 24; the runner’s Node 20 deprecation notice does not
|
|
104
|
+
require a compatibility override.
|
|
105
|
+
|
|
73
106
|
## Architecture
|
|
74
107
|
|
|
75
108
|
```text
|
|
@@ -84,8 +117,13 @@ packages/icons Icon policy and directional mirroring
|
|
|
84
117
|
packages/registry Canonical component catalog and install metadata
|
|
85
118
|
```
|
|
86
119
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
120
|
+
## Documentation
|
|
121
|
+
|
|
122
|
+
- [`docs/design-system/README.md`](docs/design-system/README.md): focused
|
|
123
|
+
documentation index
|
|
124
|
+
- [`docs/design-system/agent-guide.md`](docs/design-system/agent-guide.md): agent
|
|
125
|
+
workflow and verification expectations
|
|
126
|
+
- [`docs/design-system/gpt-agent-prompt.md`](docs/design-system/gpt-agent-prompt.md):
|
|
127
|
+
ready-to-paste GPT task wrapper
|
|
128
|
+
- [`packages/registry/manifest.json`](packages/registry/manifest.json): canonical
|
|
129
|
+
registry catalog and component contracts
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
PieChart,
|
|
24
24
|
RadarChart,
|
|
25
25
|
} from '@noe/data-ui';
|
|
26
|
-
import { ChevronIcon,
|
|
26
|
+
import { ChevronIcon, iconsaxFreeSource, NoeMark } from '@noe/icons';
|
|
27
27
|
import {
|
|
28
28
|
AboutPage,
|
|
29
29
|
Alert,
|
|
@@ -314,7 +314,7 @@ export const catalogEntries: readonly CatalogEntry[] = [
|
|
|
314
314
|
status: statusOf('icon-system'),
|
|
315
315
|
name: 'Icon System',
|
|
316
316
|
description:
|
|
317
|
-
'
|
|
317
|
+
'Iconsax Free interface icons delivered through the NOE wrapper with an explicit directional-mirroring policy for RTL layouts.',
|
|
318
318
|
package: '@noe/icons',
|
|
319
319
|
registryItem: null,
|
|
320
320
|
preview: () => (
|
|
@@ -336,7 +336,7 @@ export const catalogEntries: readonly CatalogEntry[] = [
|
|
|
336
336
|
</div>
|
|
337
337
|
</div>
|
|
338
338
|
<span className="font-mono text-[0.6875rem] text-muted-foreground">
|
|
339
|
-
{
|
|
339
|
+
{iconsaxFreeSource.provider} / {iconsaxFreeSource.package}
|
|
340
340
|
</span>
|
|
341
341
|
</div>
|
|
342
342
|
),
|
|
@@ -38,3 +38,16 @@ export const Default: Story = {
|
|
|
38
38
|
</Card>
|
|
39
39
|
),
|
|
40
40
|
};
|
|
41
|
+
|
|
42
|
+
export const Outlined: Story = {
|
|
43
|
+
render: () => (
|
|
44
|
+
<Card appearance="outlined" style={{ maxWidth: '24rem' }}>
|
|
45
|
+
<CardHeader>
|
|
46
|
+
<CardTitle>Selection boundary</CardTitle>
|
|
47
|
+
<CardDescription>
|
|
48
|
+
Use this only when a visible boundary conveys interaction or data-entry state.
|
|
49
|
+
</CardDescription>
|
|
50
|
+
</CardHeader>
|
|
51
|
+
</Card>
|
|
52
|
+
),
|
|
53
|
+
};
|
|
@@ -3,7 +3,7 @@ import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
|
3
3
|
import {
|
|
4
4
|
ChevronIcon,
|
|
5
5
|
iconDirectionPolicy,
|
|
6
|
-
|
|
6
|
+
iconsaxFreeSource,
|
|
7
7
|
NoeMark,
|
|
8
8
|
} from '../../../../packages/icons/src/index';
|
|
9
9
|
|
|
@@ -31,7 +31,8 @@ function IconGallery() {
|
|
|
31
31
|
<strong>Never mirror:</strong> {iconDirectionPolicy.neverMirror.join(', ')}
|
|
32
32
|
</div>
|
|
33
33
|
<div>
|
|
34
|
-
<strong>Interface source:</strong> {
|
|
34
|
+
<strong>Interface source:</strong> {iconsaxFreeSource.provider} /{' '}
|
|
35
|
+
{iconsaxFreeSource.package}
|
|
35
36
|
</div>
|
|
36
37
|
</div>
|
|
37
38
|
);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
# ADR 0006:
|
|
1
|
+
# ADR 0006: Iconsax Free icon policy
|
|
2
2
|
|
|
3
3
|
Status: Accepted
|
|
4
4
|
|
|
5
|
-
Earlier proposals locked Lucide as the product icon family. The repository
|
|
5
|
+
Earlier proposals locked Lucide as the product icon family. The repository now adopts Iconsax Free through the audited `@noe/icons` wrapper (`packages/icons/src/iconsax.tsx`, `iconsaxFreeSource`), with `NoeMark` registered as a separate NOE brand asset.
|
|
6
6
|
|
|
7
|
-
Decision: the product uses exactly one icon family,
|
|
7
|
+
Decision: the product uses exactly one provider icon family, Iconsax Free, plus NOE brand marks. Applications import from `@noe/icons`, never from `iconsax-react`. Directional icons use logical directions (`forward`/`backward`) and mirror only through the scoped `.noe-logical-icon` class under `iconDirectionPolicy`; brand marks never mirror. Lucide is not adopted and icon families must not be mixed.
|
|
8
8
|
|
|
9
|
-
Consequences: every added third-party icon records provider and source metadata in the style of `
|
|
9
|
+
Consequences: every added third-party icon records provider and source metadata in the style of `iconsaxFreeSource`; `NoeMark` is a NOE brand asset and carries no provider metadata; Iconsax Free's MIT license is part of adoption review; icon-related documentation and stories must reflect the mirroring policy rather than physical left/right semantics.
|
|
@@ -42,5 +42,5 @@ deployment gate in ADR 0007.
|
|
|
42
42
|
- No custom MCP server while the official shadcn MCP satisfies registry discovery.
|
|
43
43
|
- Registry publication and package release are separate operational gates (ADR 0007).
|
|
44
44
|
- `@noe/*` is the single package namespace for packages, registry items, diagrams and agent instructions (ADR 0005).
|
|
45
|
-
-
|
|
45
|
+
- Iconsax Free is the only third-party icon family, exposed through `@noe/icons`; NOE brand marks never mirror (ADR 0006).
|
|
46
46
|
- Capability libraries stay behind adapters; NOE tokens and `@noe/*` own product markup, style, RTL behavior and approval states (ADR 0008).
|
|
@@ -14,24 +14,37 @@ entry and push to the default branch:
|
|
|
14
14
|
| `ci / build-and-verify` | Workspace build + registry/i18n/RTL/governance audits |
|
|
15
15
|
| `ci / e2e-critical` | Playwright matrix: chromium en/fa/pseudo + firefox/webkit smoke |
|
|
16
16
|
|
|
17
|
-
The `security` workflow
|
|
18
|
-
|
|
17
|
+
The `security` workflow contains opt-in CodeQL analysis and dependency review.
|
|
18
|
+
For this private repository, GitHub must first have Code Security and Dependency
|
|
19
|
+
Graph/GitHub Advanced Security enabled. Set `ENABLE_CODEQL=true` and
|
|
20
|
+
`ENABLE_DEPENDENCY_REVIEW=true` repository variables only after the corresponding
|
|
21
|
+
GitHub features are available.
|
|
19
22
|
|
|
20
23
|
## Security controls
|
|
21
24
|
|
|
22
|
-
- Minimal `GITHUB_TOKEN` permissions
|
|
23
|
-
|
|
25
|
+
- Minimal `GITHUB_TOKEN` permissions. CodeQL receives `actions: read`,
|
|
26
|
+
`contents: read`, and `security-events: write`; dependency review receives only
|
|
27
|
+
`contents: read`.
|
|
24
28
|
- All third-party actions pinned to immutable full commit SHAs with the
|
|
25
29
|
upstream version documented beside them; Dependabot keeps SHAs updated.
|
|
26
30
|
- No secrets in logs; no privileged secrets available to untrusted PR code.
|
|
27
|
-
- Concurrency groups cancel superseded PR runs
|
|
28
|
-
|
|
31
|
+
- Concurrency groups cancel superseded PR runs. The npm publishing workflow is
|
|
32
|
+
serialized and is never cancelled mid-publish.
|
|
29
33
|
|
|
30
34
|
## Artifacts
|
|
31
35
|
|
|
32
36
|
Storybook static build, dist outputs, Playwright reports/traces/screenshots are
|
|
33
37
|
uploaded with 14-day retention on relevant outcomes.
|
|
34
38
|
|
|
39
|
+
## Publishing
|
|
40
|
+
|
|
41
|
+
`publish.yml` runs after a successful `ci` workflow on a push to `main`. It checks
|
|
42
|
+
out the verified commit, builds it, verifies the npm tarball, and publishes only if
|
|
43
|
+
the root `package.json` version is not already on npm. npm Trusted Publishing uses
|
|
44
|
+
GitHub Actions OIDC, so the workflow stores no npm token.
|
|
45
|
+
|
|
46
|
+
Manual `workflow_dispatch` publishing is restricted to `main`.
|
|
47
|
+
|
|
35
48
|
## Deployment
|
|
36
49
|
|
|
37
50
|
No deployment provider is invented. Storybook artifacts are produced on every
|
|
@@ -43,4 +56,6 @@ long-lived credentials.
|
|
|
43
56
|
|
|
44
57
|
Recommended required status checks once branch protection is active:
|
|
45
58
|
`ci / quality`, `ci / unit`, `ci / component`, `ci / storybook`,
|
|
46
|
-
`ci / build-and-verify`, `ci / e2e-critical
|
|
59
|
+
`ci / build-and-verify`, `ci / e2e-critical`. Add `security / codeql` only after
|
|
60
|
+
Code Security is enabled and `ENABLE_CODEQL=true`; otherwise it is intentionally
|
|
61
|
+
skipped rather than reported as a false failure.
|
|
@@ -42,6 +42,11 @@ matching the direction contract in `rtl.md`. Products consume the highest
|
|
|
42
42
|
layer that fits; screens should not reassemble primitives into ad-hoc page
|
|
43
43
|
scaffolds when a registered block exists.
|
|
44
44
|
|
|
45
|
+
For application pages, compose `app-frame`, `page-header`, `sidebar-navigation`,
|
|
46
|
+
`bottom-navigation`, `drawer`, and `Card` before creating a page-local shell.
|
|
47
|
+
Use the [flat surface and navigation policy](surface-policy.md) to decide surface
|
|
48
|
+
tone, CTA hierarchy, adaptive navigation, icon coloring, and review evidence.
|
|
49
|
+
|
|
45
50
|
Mapping to the Untitled UI reference taxonomy (honest as of 2026-08-27 — foundation stabilization):
|
|
46
51
|
|
|
47
52
|
| Untitled UI category | NOE coverage |
|
|
@@ -35,6 +35,15 @@ Typography is a language-aware semantic contract, not a per-component choice.
|
|
|
35
35
|
|
|
36
36
|
Radii are compact and semantic. Controls use shared heights. Cards are not nested merely to create hierarchy. Dense professional surfaces may use tighter spacing than consumer surfaces but share the same token scale.
|
|
37
37
|
|
|
38
|
+
## Surface hierarchy
|
|
39
|
+
|
|
40
|
+
NOE uses a flat surface hierarchy: page canvas and raised regions are separated by
|
|
41
|
+
semantic background tone, spacing, and radius—not decorative borders or shadows.
|
|
42
|
+
`Card` therefore defaults to a raised, borderless appearance. Its outlined
|
|
43
|
+
appearance is only for controls or data boundaries with a meaningful selection
|
|
44
|
+
state. See [Flat surface and navigation policy](surface-policy.md) for the
|
|
45
|
+
product-level contract.
|
|
46
|
+
|
|
38
47
|
## Responsive behavior
|
|
39
48
|
|
|
40
49
|
The reference app validates 390, 768, 1024, 1280 and 1440 pixel widths. Sidebars collapse by capability; data remains in logical DOM order; tables scroll rather than reverse data; agent artifacts progressively disclose on smaller layouts.
|
|
@@ -16,7 +16,7 @@ Use logical margin, padding, inset, border and text alignment. Maintain semantic
|
|
|
16
16
|
|
|
17
17
|
Forward/backward, next/previous, chevron, indent/outdent and panel-opening icons may mirror. Brand, play, pause, upload, download, search, settings, check, close, charts, code and service logos do not mirror automatically.
|
|
18
18
|
|
|
19
|
-
The shared `ChevronIcon` uses `
|
|
19
|
+
The shared `ChevronIcon` uses the `iconsaxFreeSource` wrapper and opts into this policy through the scoped `.noe-logical-icon` class. `NoeMark` remains a NOE brand asset and never mirrors.
|
|
20
20
|
|
|
21
21
|
## Mixed content
|
|
22
22
|
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Flat surface and navigation policy
|
|
2
|
+
|
|
3
|
+
This is the default NOE policy for application pages. It prevents corrective UI
|
|
4
|
+
passes caused by arbitrary shadows, card borders, or ambiguous mobile navigation.
|
|
5
|
+
|
|
6
|
+
## Surface hierarchy
|
|
7
|
+
|
|
8
|
+
1. The page canvas uses `color.background` or `color.surface`.
|
|
9
|
+
2. A top-level section or card uses `color.surfaceRaised`.
|
|
10
|
+
3. Grouping comes from the difference between those two tones, radius, and the
|
|
11
|
+
spacing scale—not a border or a shadow.
|
|
12
|
+
4. A nested region uses spacing first. Do not nest cards merely to create depth.
|
|
13
|
+
5. `Card` defaults to `appearance="raised"`, which has no visible stroke.
|
|
14
|
+
`appearance="outlined"` is reserved for a selection, data-entry, or comparison
|
|
15
|
+
boundary where a stroke conveys real meaning.
|
|
16
|
+
|
|
17
|
+
NOE shadow tokens are intentionally `none`. Do not add local `box-shadow` values
|
|
18
|
+
to product styles. A focus state is an outline/ring, not elevation.
|
|
19
|
+
|
|
20
|
+
## Actions
|
|
21
|
+
|
|
22
|
+
- One screen has one contained primary CTA.
|
|
23
|
+
- Secondary actions are outline or ghost actions. On a dark or colored surface,
|
|
24
|
+
a white outline action remains transparent with a white label and stroke; never
|
|
25
|
+
give it an opaque white fill that removes its hierarchy.
|
|
26
|
+
- Destructive actions retain an explicit label and confirmation/recovery path;
|
|
27
|
+
color alone is never the signal.
|
|
28
|
+
- Every focusable action keeps a visible `focus-visible` outline.
|
|
29
|
+
|
|
30
|
+
## Adaptive navigation
|
|
31
|
+
|
|
32
|
+
- Use a sidebar for application navigation at desktop widths and a labelled drawer
|
|
33
|
+
trigger at smaller widths.
|
|
34
|
+
- Mobile bottom navigation is only for top-level destinations and has at most five
|
|
35
|
+
labelled items. The active item has a text and icon state, not color alone.
|
|
36
|
+
- A drawer is secondary navigation, not the only route to a primary action.
|
|
37
|
+
- Every page frame exposes a skip link to its main landmark; a route change places
|
|
38
|
+
the reading start at that main region.
|
|
39
|
+
- Menu triggers include an icon and a visible label when surrounding layout does
|
|
40
|
+
not already make their purpose obvious.
|
|
41
|
+
|
|
42
|
+
## Icons and direction
|
|
43
|
+
|
|
44
|
+
- Use `@noe/icons` only. Icons inherit `currentColor` from their interactive
|
|
45
|
+
parent, with explicit `color` only for a semantic status.
|
|
46
|
+
- Keep icon size on the NOE token scale and icon-plus-label gaps logical.
|
|
47
|
+
- Use logical CSS properties. Do not solve RTL with global `row-reverse` or
|
|
48
|
+
blanket SVG mirroring.
|
|
49
|
+
|
|
50
|
+
## Product review checklist
|
|
51
|
+
|
|
52
|
+
- Test every route in Persian/RTL and English/LTR, in light and dark themes.
|
|
53
|
+
- Verify no page-level horizontal overflow at the mobile breakpoint.
|
|
54
|
+
- Verify every section/card/panel has `box-shadow: none` and no visible outer
|
|
55
|
+
stroke unless it is explicitly an outlined control.
|
|
56
|
+
- Verify interactive targets are at least 44 px on touch devices and have
|
|
57
|
+
accessible names.
|
|
58
|
+
- Test desktop sidebar and mobile drawer independently, including keyboard focus
|
|
59
|
+
and Escape dismissal.
|
package/llms.txt
CHANGED
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
- Agent workflow and retrieval: `docs/design-system/agent-guide.md`
|
|
33
33
|
- Components and catalog terms: `docs/design-system/components.md`
|
|
34
34
|
- Tokens and foundations: `docs/design-system/foundations.md`, `docs/design-system/tokens.md`
|
|
35
|
+
- Flat cards, action hierarchy and adaptive application navigation: `docs/design-system/surface-policy.md`
|
|
35
36
|
- Locale, RTL, and bidi: `docs/design-system/i18n.md`, `docs/design-system/rtl.md`
|
|
36
37
|
- Accessibility: `docs/design-system/accessibility.md`
|
|
37
38
|
- Agent and tool-state UI: `docs/design-system/agentic-ui.md`
|
package/package.json
CHANGED
|
@@ -173,7 +173,7 @@
|
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
/* Logical
|
|
176
|
+
/* Logical Iconsax chevrons opt into direction-aware motion. Brand and
|
|
177
177
|
* semantic glyphs do not receive a global transform. */
|
|
178
178
|
.noe-logical-icon[data-logical-direction="backward"],
|
|
179
179
|
[dir="rtl"] .noe-logical-icon[data-logical-direction="forward"] {
|
|
@@ -145,8 +145,8 @@
|
|
|
145
145
|
--noe-color-muted-foreground: var(--noe-primitive-color-ink-500);
|
|
146
146
|
--noe-color-border: rgba(23, 25, 24, 0.16);
|
|
147
147
|
--noe-color-border-strong: var(--noe-primitive-color-ink-300);
|
|
148
|
-
--noe-color-accent: var(--noe-primitive-color-
|
|
149
|
-
--noe-color-accent-hover: var(--noe-primitive-color-
|
|
148
|
+
--noe-color-accent: var(--noe-primitive-color-cyan-500);
|
|
149
|
+
--noe-color-accent-hover: var(--noe-primitive-color-cyan-500);
|
|
150
150
|
--noe-color-accent-foreground: var(--noe-primitive-color-paper-0);
|
|
151
151
|
--noe-color-signal: var(--noe-primitive-color-coral-500);
|
|
152
152
|
--noe-color-success: var(--noe-primitive-color-green-600);
|
|
@@ -159,8 +159,8 @@
|
|
|
159
159
|
--noe-color-info-foreground: var(--noe-primitive-color-paper-0);
|
|
160
160
|
--noe-color-focus-ring: var(--noe-primitive-color-alpha-focus-light);
|
|
161
161
|
--noe-color-overlay: var(--noe-primitive-color-alpha-overlay-light);
|
|
162
|
-
--noe-shadow-raised:
|
|
163
|
-
--noe-shadow-overlay:
|
|
162
|
+
--noe-shadow-raised: none;
|
|
163
|
+
--noe-shadow-overlay: none;
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
/* Semantic tokens: explicit dark theme. */
|
|
@@ -175,8 +175,8 @@
|
|
|
175
175
|
--noe-color-muted-foreground: var(--noe-primitive-color-ink-400);
|
|
176
176
|
--noe-color-border: rgba(246, 244, 242, 0.14);
|
|
177
177
|
--noe-color-border-strong: var(--noe-primitive-color-ink-600);
|
|
178
|
-
--noe-color-accent: var(--noe-primitive-color-
|
|
179
|
-
--noe-color-accent-hover: var(--noe-primitive-color-
|
|
178
|
+
--noe-color-accent: var(--noe-primitive-color-cyan-400);
|
|
179
|
+
--noe-color-accent-hover: var(--noe-primitive-color-cyan-400);
|
|
180
180
|
--noe-color-accent-foreground: var(--noe-primitive-color-ink-950);
|
|
181
181
|
--noe-color-signal: var(--noe-primitive-color-coral-400);
|
|
182
182
|
--noe-color-success: var(--noe-primitive-color-green-500);
|
|
@@ -189,8 +189,8 @@
|
|
|
189
189
|
--noe-color-info-foreground: var(--noe-primitive-color-ink-950);
|
|
190
190
|
--noe-color-focus-ring: var(--noe-primitive-color-alpha-focus-dark);
|
|
191
191
|
--noe-color-overlay: var(--noe-primitive-color-alpha-overlay-dark);
|
|
192
|
-
--noe-shadow-raised:
|
|
193
|
-
--noe-shadow-overlay:
|
|
192
|
+
--noe-shadow-raised: none;
|
|
193
|
+
--noe-shadow-overlay: none;
|
|
194
194
|
}
|
|
195
195
|
|
|
196
196
|
/* Semantic tokens: follow the OS only when no explicit theme is set. */
|
|
@@ -206,8 +206,8 @@
|
|
|
206
206
|
--noe-color-muted-foreground: var(--noe-primitive-color-ink-400);
|
|
207
207
|
--noe-color-border: rgba(246, 244, 242, 0.14);
|
|
208
208
|
--noe-color-border-strong: var(--noe-primitive-color-ink-600);
|
|
209
|
-
--noe-color-accent: var(--noe-primitive-color-
|
|
210
|
-
--noe-color-accent-hover: var(--noe-primitive-color-
|
|
209
|
+
--noe-color-accent: var(--noe-primitive-color-cyan-400);
|
|
210
|
+
--noe-color-accent-hover: var(--noe-primitive-color-cyan-400);
|
|
211
211
|
--noe-color-accent-foreground: var(--noe-primitive-color-ink-950);
|
|
212
212
|
--noe-color-signal: var(--noe-primitive-color-coral-400);
|
|
213
213
|
--noe-color-success: var(--noe-primitive-color-green-500);
|
|
@@ -220,8 +220,8 @@
|
|
|
220
220
|
--noe-color-info-foreground: var(--noe-primitive-color-ink-950);
|
|
221
221
|
--noe-color-focus-ring: var(--noe-primitive-color-alpha-focus-dark);
|
|
222
222
|
--noe-color-overlay: var(--noe-primitive-color-alpha-overlay-dark);
|
|
223
|
-
--noe-shadow-raised:
|
|
224
|
-
--noe-shadow-overlay:
|
|
223
|
+
--noe-shadow-raised: none;
|
|
224
|
+
--noe-shadow-overlay: none;
|
|
225
225
|
}
|
|
226
226
|
}
|
|
227
227
|
|
|
@@ -111,8 +111,8 @@
|
|
|
111
111
|
"mutedForeground": "{primitive.color.ink.500}",
|
|
112
112
|
"border": "rgba(23, 25, 24, 0.16)",
|
|
113
113
|
"borderStrong": "{primitive.color.ink.300}",
|
|
114
|
-
"accent": "{primitive.color.
|
|
115
|
-
"accentHover": "{primitive.color.
|
|
114
|
+
"accent": "{primitive.color.cyan.500}",
|
|
115
|
+
"accentHover": "{primitive.color.cyan.500}",
|
|
116
116
|
"accentForeground": "{primitive.color.paper.0}",
|
|
117
117
|
"signal": "{primitive.color.coral.500}",
|
|
118
118
|
"success": "{primitive.color.green.600}",
|
|
@@ -136,8 +136,8 @@
|
|
|
136
136
|
"mutedForeground": "{primitive.color.ink.400}",
|
|
137
137
|
"border": "rgba(246, 244, 242, 0.14)",
|
|
138
138
|
"borderStrong": "{primitive.color.ink.600}",
|
|
139
|
-
"accent": "{primitive.color.
|
|
140
|
-
"accentHover": "{primitive.color.
|
|
139
|
+
"accent": "{primitive.color.cyan.400}",
|
|
140
|
+
"accentHover": "{primitive.color.cyan.400}",
|
|
141
141
|
"accentForeground": "{primitive.color.ink.950}",
|
|
142
142
|
"signal": "{primitive.color.coral.400}",
|
|
143
143
|
"success": "{primitive.color.green.500}",
|
|
@@ -154,12 +154,12 @@
|
|
|
154
154
|
},
|
|
155
155
|
"shadow": {
|
|
156
156
|
"light": {
|
|
157
|
-
"raised": "
|
|
158
|
-
"overlay": "
|
|
157
|
+
"raised": "none",
|
|
158
|
+
"overlay": "none"
|
|
159
159
|
},
|
|
160
160
|
"dark": {
|
|
161
|
-
"raised": "
|
|
162
|
-
"overlay": "
|
|
161
|
+
"raised": "none",
|
|
162
|
+
"overlay": "none"
|
|
163
163
|
}
|
|
164
164
|
},
|
|
165
165
|
"font": {
|
|
@@ -112,8 +112,8 @@ export const tokens = {
|
|
|
112
112
|
"mutedForeground": "{primitive.color.ink.500}",
|
|
113
113
|
"border": "rgba(23, 25, 24, 0.16)",
|
|
114
114
|
"borderStrong": "{primitive.color.ink.300}",
|
|
115
|
-
"accent": "{primitive.color.
|
|
116
|
-
"accentHover": "{primitive.color.
|
|
115
|
+
"accent": "{primitive.color.cyan.500}",
|
|
116
|
+
"accentHover": "{primitive.color.cyan.500}",
|
|
117
117
|
"accentForeground": "{primitive.color.paper.0}",
|
|
118
118
|
"signal": "{primitive.color.coral.500}",
|
|
119
119
|
"success": "{primitive.color.green.600}",
|
|
@@ -137,8 +137,8 @@ export const tokens = {
|
|
|
137
137
|
"mutedForeground": "{primitive.color.ink.400}",
|
|
138
138
|
"border": "rgba(246, 244, 242, 0.14)",
|
|
139
139
|
"borderStrong": "{primitive.color.ink.600}",
|
|
140
|
-
"accent": "{primitive.color.
|
|
141
|
-
"accentHover": "{primitive.color.
|
|
140
|
+
"accent": "{primitive.color.cyan.400}",
|
|
141
|
+
"accentHover": "{primitive.color.cyan.400}",
|
|
142
142
|
"accentForeground": "{primitive.color.ink.950}",
|
|
143
143
|
"signal": "{primitive.color.coral.400}",
|
|
144
144
|
"success": "{primitive.color.green.500}",
|
|
@@ -155,12 +155,12 @@ export const tokens = {
|
|
|
155
155
|
},
|
|
156
156
|
"shadow": {
|
|
157
157
|
"light": {
|
|
158
|
-
"raised": "
|
|
159
|
-
"overlay": "
|
|
158
|
+
"raised": "none",
|
|
159
|
+
"overlay": "none"
|
|
160
160
|
},
|
|
161
161
|
"dark": {
|
|
162
|
-
"raised": "
|
|
163
|
-
"overlay": "
|
|
162
|
+
"raised": "none",
|
|
163
|
+
"overlay": "none"
|
|
164
164
|
}
|
|
165
165
|
},
|
|
166
166
|
"font": {
|
|
@@ -32,10 +32,10 @@ export const iconProvenance = Object.freeze({
|
|
|
32
32
|
license: 'Partner brand — check before publishing',
|
|
33
33
|
asset: 'integration icons',
|
|
34
34
|
},
|
|
35
|
-
|
|
36
|
-
source: '
|
|
37
|
-
license: '
|
|
38
|
-
asset: '
|
|
35
|
+
iconsaxFree: {
|
|
36
|
+
source: 'Iconsax Free',
|
|
37
|
+
license: 'MIT — https://github.com/rendinjast/iconsax-react',
|
|
38
|
+
asset: 'iconsax-react wrapper',
|
|
39
39
|
},
|
|
40
40
|
});
|
|
41
41
|
|