@omkarux/vela 0.2.0

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.
Files changed (45) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/LICENSE +21 -0
  3. package/README.md +112 -0
  4. package/dist/components/Button/Button.d.ts +32 -0
  5. package/dist/components/Button/Button.js +51 -0
  6. package/dist/components/Button/index.d.ts +2 -0
  7. package/dist/components/ContextualAlert/ContextualAlert.d.ts +18 -0
  8. package/dist/components/ContextualAlert/ContextualAlert.js +49 -0
  9. package/dist/components/ContextualAlert/index.d.ts +2 -0
  10. package/dist/components/Input/Input.d.ts +12 -0
  11. package/dist/components/Input/Input.js +31 -0
  12. package/dist/components/Input/index.d.ts +2 -0
  13. package/dist/components/StatusIndicator/StatusIndicator.d.ts +14 -0
  14. package/dist/components/StatusIndicator/StatusIndicator.js +31 -0
  15. package/dist/components/StatusIndicator/index.d.ts +2 -0
  16. package/dist/components/Tabs/Tabs.d.ts +44 -0
  17. package/dist/components/Tabs/Tabs.js +94 -0
  18. package/dist/components/Tabs/index.d.ts +2 -0
  19. package/dist/components/Toggle/Toggle.d.ts +23 -0
  20. package/dist/components/Toggle/Toggle.js +55 -0
  21. package/dist/components/Toggle/index.d.ts +2 -0
  22. package/dist/index.d.ts +24 -0
  23. package/dist/index.js +16 -0
  24. package/dist/lib/cn.d.ts +5 -0
  25. package/dist/lib/cn.js +6 -0
  26. package/dist/lib/icons.d.ts +7 -0
  27. package/dist/lib/icons.js +32 -0
  28. package/dist/tokens.css +610 -0
  29. package/dist/vela.css +897 -0
  30. package/guidelines/components/button.md +104 -0
  31. package/guidelines/components/contextual-alert.md +59 -0
  32. package/guidelines/components/input.md +65 -0
  33. package/guidelines/components/status-indicator.md +48 -0
  34. package/guidelines/components/tabs.md +71 -0
  35. package/guidelines/components/toggle.md +53 -0
  36. package/guidelines/foundations/color.md +67 -0
  37. package/guidelines/foundations/radius.md +17 -0
  38. package/guidelines/foundations/sizing.md +35 -0
  39. package/guidelines/foundations/spacing.md +28 -0
  40. package/guidelines/foundations/typography.md +34 -0
  41. package/guidelines/llms.txt +33 -0
  42. package/guidelines/overview.md +48 -0
  43. package/guidelines/setup.md +64 -0
  44. package/guidelines/tokens.md +69 -0
  45. package/package.json +84 -0
@@ -0,0 +1,48 @@
1
+ # Component overview
2
+
3
+ Pick the component by **what the user is doing**, not by what looks closest. Match the need
4
+ below, then open the per-component file for props, tokens, and anti-patterns.
5
+
6
+ ## Catalogue
7
+
8
+ | Component | Use it for | File |
9
+ |---|---|---|
10
+ | Button | Triggering an action (save, submit, delete, apply) | `components/button.md` |
11
+ | Toggle | A binary setting that takes effect immediately | `components/toggle.md` |
12
+ | Input | Single-line text entry | `components/input.md` |
13
+ | Contextual Alert | Inline severity banner (success/info/warning/minor/major/critical) | `components/contextual-alert.md` |
14
+ | Status Indicator | A health dot for one of five states | `components/status-indicator.md` |
15
+ | Tabs | Navigate between different content panels | `components/tabs.md` |
16
+
17
+ ## Disambiguations (where AI usually picks wrong)
18
+
19
+ - **Toggle vs Checkbox** — immediate effect (notifications on/off, dark mode) → **Toggle**.
20
+ Records intent until a Save click → **Checkbox**. Checkbox is not in this kit; flag the gap.
21
+ - **Tabs vs View Switcher** — different content sections → **Tabs**. The *same* dataset
22
+ rendered differently (Grid / Dashboard / Chart) → **View Switcher**, which is not in this
23
+ kit. If only the presentation of one dataset changes, do not reach for Tabs.
24
+ - **Contextual Alert vs Status Indicator** — an event the user must read → **Alert**.
25
+ An object's ongoing health, usually in a table cell → **Status Indicator**.
26
+ - **Severity vs Risk vs Status** — three taxonomies, never interchangeable.
27
+ Severity (6 levels) describes *events*. Risk (3 levels) describes *scoring*. Status
28
+ (5 states) is the dot only. There is no "high severity" and no "critical risk".
29
+
30
+ ## If no component fits
31
+
32
+ Do not invent one silently. State that the kit has no component for the need and pick the
33
+ closest match while flagging the gap. Not yet specced: Checkbox, Radio, Dropdown List,
34
+ Select List, Token Pill, Number Stepper, Text Area, Modal, Tooltip, Icon Button,
35
+ Actions Dropdown, View Switcher. Flag rather than guess.
36
+
37
+ ## How each component file is structured
38
+
39
+ Intent → When to use → Props (closed sets) → Hard constraints → Token bindings → Sizes →
40
+ Typography → States → Accessibility → Anti-patterns. Read the Anti-patterns block.
41
+
42
+ ## Cross-cutting rules
43
+
44
+ - **Bind semantic tokens**, never primitives or hex.
45
+ - **Numeric tokens carry their unit** — use directly, never `calc(... * 1px)`.
46
+ - **Closed prop sets** — never add variants, sizes or appearances beyond the Props table.
47
+ - **Both themes are real.** Never hardcode a colour that only works in light mode.
48
+ - **Colour is never the only signal** (WCAG 1.4.1) — always pair it with text or an icon.
@@ -0,0 +1,64 @@
1
+ # Setup
2
+
3
+ ## Install
4
+
5
+ ```bash
6
+ npm install @omkarux/vela
7
+ ```
8
+
9
+ `react` and `react-dom` (v18.3 or v19) are peer dependencies — the consuming app supplies
10
+ them. Vela has **zero runtime dependencies** of its own.
11
+
12
+ ## Import the stylesheet once, at the app root
13
+
14
+ ```tsx
15
+ import '@omkarux/vela/styles.css'
16
+ ```
17
+
18
+ The barrel deliberately does **not** import CSS, so the JS bundle carries no style side
19
+ effects and the consuming app keeps control of style ordering and SSR.
20
+
21
+ Need only the tokens (to style your own components against the same scale)?
22
+
23
+ ```tsx
24
+ import '@omkarux/vela/tokens.css'
25
+ ```
26
+
27
+ ## Wrap your app
28
+
29
+ ```tsx
30
+ <div className="vela-root">{children}</div>
31
+ ```
32
+
33
+ Base typography, colour and focus treatment are scoped to `.vela-root` so the kit never
34
+ fights a host app's global stylesheet. It can wrap the whole app or any subtree.
35
+
36
+ ## Theming
37
+
38
+ Three states, handled for you:
39
+
40
+ | Root attribute | Result |
41
+ |---|---|
42
+ | *(none)* | Follows the OS via `prefers-color-scheme` |
43
+ | `data-theme="light"` | Forced light, even if the OS is dark |
44
+ | `data-theme="dark"` | Forced dark, even if the OS is light |
45
+
46
+ ```tsx
47
+ document.documentElement.setAttribute('data-theme', 'dark')
48
+ ```
49
+
50
+ Dark mode is implemented by re-pointing semantic tokens onto a different part of the same
51
+ scale — **no primitive is redefined and no raw hex appears in the dark block**. A test
52
+ asserts this (`src/styles/contrast.test.ts`), because it is the property that makes a third
53
+ theme cheap rather than a rewrite.
54
+
55
+ ## Fonts
56
+
57
+ Open Sans (300/400/600) for UI text; Oswald for large stat displays. Both have system
58
+ fallbacks in the font stack, so the kit degrades rather than breaks if you do not load them.
59
+
60
+ ## Framework
61
+
62
+ React 18.3+ / 19. Components are plain functional components consuming `--vela-*` tokens.
63
+ There is no CSS-in-JS runtime, no Tailwind requirement, and no icon-library dependency —
64
+ the token layer is plain CSS custom properties and works in any framework.
@@ -0,0 +1,69 @@
1
+ # Token naming and lookup
2
+
3
+ Every token is `--vela-<layer>-<role>[-<modifier>]`. Learn the shape and you can find a token
4
+ without grepping the stylesheet.
5
+
6
+ ## The two layers
7
+
8
+ | Layer | Looks like | Bind it? |
9
+ |---|---|---|
10
+ | **Primitive** | `--vela-grey-700`, `--vela-red-500` | ❌ Almost never — only when no semantic covers the role |
11
+ | **Semantic** | `--vela-text-default`, `--vela-bg-severity-major` | ✅ Always |
12
+
13
+ Primitives exist so semantics can be re-pointed for theming. Binding a primitive directly is
14
+ what breaks dark mode, and it is the single most common drift in generated code.
15
+
16
+ ## Decision tree
17
+
18
+ 1. **What am I colouring?** → `text` / `bg` / `border` / `icon` / `signal`
19
+ 2. **In what context?** → nothing (global), `severity-*`, `risk-*`, `status-*`, `btn-*`, `control-*`
20
+ 3. **What state?** → nothing (default), `-hover`, `-active`, `-inactive`, `-disabled`
21
+
22
+ `--vela-` + step 1 + step 2 + step 3. Examples:
23
+
24
+ - Body copy → `--vela-text-default`
25
+ - The background of a critical alert → `--vela-bg-severity-critical`
26
+ - The border of an input while focused → `--vela-control-border-active`
27
+ - The dot for an unhealthy node → `--vela-signal-status-unhealthy`
28
+
29
+ ## Frequency: what you will actually reach for
30
+
31
+ These cover the overwhelming majority of real usage. Reach past them only deliberately.
32
+
33
+ | Token | Use |
34
+ |---|---|
35
+ | `--vela-text-default` | Almost all body text |
36
+ | `--vela-text-heading` | Headings only |
37
+ | `--vela-text-de-emphasized` | Secondary/meta text |
38
+ | `--vela-bg-global` | Page background |
39
+ | `--vela-bg-container` | Cards, panels, raised surfaces |
40
+ | `--vela-border-default` | Standard 1px borders |
41
+ | `--vela-border-subtle` | Dividers and rules |
42
+ | `--vela-space-10` / `-15` / `-20` | Most padding and gaps |
43
+ | `--vela-radius-4` | Default corner on every component |
44
+
45
+ ## Numeric tokens already carry their unit
46
+
47
+ ```css
48
+ padding: var(--vela-space-10); /* ✅ */
49
+ padding: calc(var(--vela-space-10) * 1px); /* ❌ produces "10px * 1px" */
50
+ ```
51
+
52
+ Applies to `--vela-space-*`, `--vela-icon-*`, `--vela-control-height-*`, `--vela-radius-*`
53
+ and every typography size / line-height.
54
+
55
+ ## Correct and incorrect
56
+
57
+ ```css
58
+ /* ✅ semantic, survives a theme change */
59
+ .thing { color: var(--vela-text-default); background: var(--vela-bg-container); }
60
+
61
+ /* ⚠️ primitive — only when genuinely no semantic covers the role */
62
+ .thing { color: var(--vela-grey-700); }
63
+
64
+ /* ❌ raw hex — invisible to theming, fails in dark mode */
65
+ .thing { color: #49555a; }
66
+
67
+ /* ❌ crossing taxonomies — there is no "high" severity */
68
+ .thing { background: var(--vela-bg-severity-high); }
69
+ ```
package/package.json ADDED
@@ -0,0 +1,84 @@
1
+ {
2
+ "name": "@omkarux/vela",
3
+ "version": "0.2.0",
4
+ "description": "A token-first React component kit: two-layer color architecture, separate severity and risk taxonomies, full light and dark theming, zero runtime dependencies.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "Omkar Khadamkar",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/omkarpkh/vela.git"
11
+ },
12
+ "homepage": "https://github.com/omkarpkh/vela#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/omkarpkh/vela/issues"
15
+ },
16
+ "sideEffects": [
17
+ "**/*.css"
18
+ ],
19
+ "main": "./dist/index.js",
20
+ "types": "./dist/index.d.ts",
21
+ "exports": {
22
+ ".": {
23
+ "types": "./dist/index.d.ts",
24
+ "import": "./dist/index.js"
25
+ },
26
+ "./styles.css": "./dist/vela.css",
27
+ "./tokens.css": "./dist/tokens.css",
28
+ "./guidelines/*": "./guidelines/*",
29
+ "./package.json": "./package.json"
30
+ },
31
+ "files": [
32
+ "dist",
33
+ "guidelines",
34
+ "README.md",
35
+ "CHANGELOG.md",
36
+ "LICENSE"
37
+ ],
38
+ "scripts": {
39
+ "clean": "rm -rf dist",
40
+ "build": "npm run clean && npm run build:js && npm run build:css",
41
+ "build:js": "vite build",
42
+ "build:css": "node scripts/build-css.mjs",
43
+ "predev": "npm run build:css",
44
+ "dev": "vite --config vite.demo.config.ts",
45
+ "predemo:build": "npm run build:css",
46
+ "demo:build": "vite build --config vite.demo.config.ts",
47
+ "test": "vitest run",
48
+ "test:watch": "vitest",
49
+ "typecheck": "tsc --noEmit",
50
+ "contrast": "node scripts/contrast-report.mjs",
51
+ "verify": "npm run typecheck && npm run test && npm run build && node scripts/verify-pack.mjs",
52
+ "prepublishOnly": "npm run verify"
53
+ },
54
+ "peerDependencies": {
55
+ "react": "^18.3 || ^19",
56
+ "react-dom": "^18.3 || ^19"
57
+ },
58
+ "devDependencies": {
59
+ "@testing-library/jest-dom": "^6.6.3",
60
+ "@testing-library/react": "^16.1.0",
61
+ "@testing-library/user-event": "^14.5.2",
62
+ "@types/node": "^26.5.0",
63
+ "@types/react": "^19.0.0",
64
+ "@types/react-dom": "^19.0.0",
65
+ "@vitejs/plugin-react": "^4.3.4",
66
+ "jsdom": "^26.0.0",
67
+ "react": "^19.0.0",
68
+ "react-dom": "^19.0.0",
69
+ "typescript": "^5.7.0",
70
+ "vite": "^6.0.0",
71
+ "vite-plugin-dts": "^4.5.4",
72
+ "vitest": "^3.0.0"
73
+ },
74
+ "keywords": [
75
+ "design-system",
76
+ "design-tokens",
77
+ "react",
78
+ "component-library",
79
+ "accessibility"
80
+ ],
81
+ "engines": {
82
+ "node": ">=18"
83
+ }
84
+ }