orio-ui 0.1.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 (79) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +237 -0
  3. package/dist/module.cjs +5 -0
  4. package/dist/module.d.mts +3 -0
  5. package/dist/module.d.ts +3 -0
  6. package/dist/module.json +12 -0
  7. package/dist/module.mjs +16 -0
  8. package/dist/runtime/assets/css/animation.css +1 -0
  9. package/dist/runtime/assets/css/colors.css +1 -0
  10. package/dist/runtime/assets/css/cool-gradient-hover.css +23 -0
  11. package/dist/runtime/assets/css/main.css +1 -0
  12. package/dist/runtime/assets/css/scroll.css +1 -0
  13. package/dist/runtime/components/Button.vue +102 -0
  14. package/dist/runtime/components/CheckBox.vue +93 -0
  15. package/dist/runtime/components/ControlElement.vue +39 -0
  16. package/dist/runtime/components/DashedContainer.vue +59 -0
  17. package/dist/runtime/components/DatePicker.vue +30 -0
  18. package/dist/runtime/components/DateRangePicker.vue +73 -0
  19. package/dist/runtime/components/EmptyState.vue +81 -0
  20. package/dist/runtime/components/Icon.vue +40 -0
  21. package/dist/runtime/components/Input.vue +48 -0
  22. package/dist/runtime/components/LoadingSpinner.vue +6 -0
  23. package/dist/runtime/components/Modal.vue +69 -0
  24. package/dist/runtime/components/Popover.vue +249 -0
  25. package/dist/runtime/components/Selector.vue +208 -0
  26. package/dist/runtime/components/Tag.vue +21 -0
  27. package/dist/runtime/components/Textarea.vue +53 -0
  28. package/dist/runtime/components/view/Dates.vue +59 -0
  29. package/dist/runtime/components/view/Separator.vue +26 -0
  30. package/dist/runtime/components/view/Text.vue +79 -0
  31. package/dist/runtime/composables/index.d.ts +4 -0
  32. package/dist/runtime/composables/index.js +4 -0
  33. package/dist/runtime/composables/useApi.d.ts +10 -0
  34. package/dist/runtime/composables/useApi.js +9 -0
  35. package/dist/runtime/composables/useFuzzySearch.d.ts +10 -0
  36. package/dist/runtime/composables/useFuzzySearch.js +22 -0
  37. package/dist/runtime/composables/useModal.d.ts +15 -0
  38. package/dist/runtime/composables/useModal.js +28 -0
  39. package/dist/runtime/composables/useTheme.d.ts +6 -0
  40. package/dist/runtime/composables/useTheme.js +23 -0
  41. package/dist/runtime/index.d.ts +20 -0
  42. package/dist/runtime/index.js +20 -0
  43. package/dist/runtime/utils/icon-registry.d.ts +2 -0
  44. package/dist/runtime/utils/icon-registry.js +26 -0
  45. package/dist/types.d.mts +7 -0
  46. package/dist/types.d.ts +7 -0
  47. package/nuxt.config.ts +38 -0
  48. package/package.json +99 -0
  49. package/src/module.ts +16 -0
  50. package/src/runtime/assets/css/animation.css +88 -0
  51. package/src/runtime/assets/css/colors.css +142 -0
  52. package/src/runtime/assets/css/cool-gradient-hover.scss +33 -0
  53. package/src/runtime/assets/css/main.css +11 -0
  54. package/src/runtime/assets/css/scroll.css +46 -0
  55. package/src/runtime/components/Button.vue +110 -0
  56. package/src/runtime/components/CheckBox.vue +103 -0
  57. package/src/runtime/components/ControlElement.vue +42 -0
  58. package/src/runtime/components/DashedContainer.vue +60 -0
  59. package/src/runtime/components/DatePicker.vue +84 -0
  60. package/src/runtime/components/DateRangePicker.vue +74 -0
  61. package/src/runtime/components/EmptyState.vue +87 -0
  62. package/src/runtime/components/Icon.vue +51 -0
  63. package/src/runtime/components/Input.vue +54 -0
  64. package/src/runtime/components/LoadingSpinner.vue +6 -0
  65. package/src/runtime/components/Modal.vue +111 -0
  66. package/src/runtime/components/Popover.vue +249 -0
  67. package/src/runtime/components/Selector.vue +224 -0
  68. package/src/runtime/components/Tag.vue +45 -0
  69. package/src/runtime/components/Textarea.vue +59 -0
  70. package/src/runtime/components/view/Dates.vue +61 -0
  71. package/src/runtime/components/view/Separator.vue +30 -0
  72. package/src/runtime/components/view/Text.vue +83 -0
  73. package/src/runtime/composables/index.ts +4 -0
  74. package/src/runtime/composables/useApi.ts +26 -0
  75. package/src/runtime/composables/useFuzzySearch.ts +51 -0
  76. package/src/runtime/composables/useModal.ts +47 -0
  77. package/src/runtime/composables/useTheme.ts +31 -0
  78. package/src/runtime/index.ts +25 -0
  79. package/src/runtime/utils/icon-registry.ts +41 -0
@@ -0,0 +1,26 @@
1
+ export const iconRegistry = {
2
+ // Loading spinner (line-md:loading-loop)
3
+ "loading-loop": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><circle cx="12" cy="2" r="0"><animate attributeName="r" begin="0" calcMode="spline" dur="1s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" repeatCount="indefinite" values="0;2;0;0"/></circle><circle cx="12" cy="2" r="0" transform="rotate(45 12 12)"><animate attributeName="r" begin="0.125s" calcMode="spline" dur="1s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" repeatCount="indefinite" values="0;2;0;0"/></circle><circle cx="12" cy="2" r="0" transform="rotate(90 12 12)"><animate attributeName="r" begin="0.25s" calcMode="spline" dur="1s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" repeatCount="indefinite" values="0;2;0;0"/></circle><circle cx="12" cy="2" r="0" transform="rotate(135 12 12)"><animate attributeName="r" begin="0.375s" calcMode="spline" dur="1s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" repeatCount="indefinite" values="0;2;0;0"/></circle><circle cx="12" cy="2" r="0" transform="rotate(180 12 12)"><animate attributeName="r" begin="0.5s" calcMode="spline" dur="1s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" repeatCount="indefinite" values="0;2;0;0"/></circle><circle cx="12" cy="2" r="0" transform="rotate(225 12 12)"><animate attributeName="r" begin="0.625s" calcMode="spline" dur="1s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" repeatCount="indefinite" values="0;2;0;0"/></circle><circle cx="12" cy="2" r="0" transform="rotate(270 12 12)"><animate attributeName="r" begin="0.75s" calcMode="spline" dur="1s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" repeatCount="indefinite" values="0;2;0;0"/></circle><circle cx="12" cy="2" r="0" transform="rotate(315 12 12)"><animate attributeName="r" begin="0.875s" calcMode="spline" dur="1s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" repeatCount="indefinite" values="0;2;0;0"/></circle></svg>`,
4
+ // Chevron down (mdi-light:chevron-down)
5
+ "chevron-down": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6l-6-6z"/></svg>`,
6
+ // Chevron up
7
+ "chevron-up": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6l-6 6z"/></svg>`,
8
+ // Edit (material-symbols:edit-sharp)
9
+ "edit": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M3 21v-4.25L16.2 3.575q.3-.275.663-.425t.762-.15t.775.15t.65.45L20.425 5q.3.275.438.65T21 6.4q0 .4-.137.763t-.438.662L7.25 21zM17.6 7.8L19 6.4L17.6 5l-1.4 1.4z"/></svg>`,
10
+ // Check / Checkmark
11
+ "check": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M9 16.17L4.83 12l-1.42 1.41L9 19L21 7l-1.41-1.41z"/></svg>`,
12
+ // Plus / Add
13
+ "plus": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>`,
14
+ // Calendar
15
+ "calendar": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M19 4h-1V2h-2v2H8V2H6v2H5c-1.11 0-1.99.9-1.99 2L3 20a2 2 0 0 0 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2m0 16H5V10h14zm0-12H5V6h14zM7 12h5v5H7z"/></svg>`,
16
+ // Close / X
17
+ "close": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M19 6.41L17.59 5L12 10.59L6.41 5L5 6.41L10.59 12L5 17.59L6.41 19L12 13.41L17.59 19L19 17.59L13.41 12z"/></svg>`,
18
+ // Search / Magnifying glass
19
+ "search": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M15.5 14h-.79l-.28-.27A6.47 6.47 0 0 0 16 9.5A6.5 6.5 0 1 0 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5S14 7.01 14 9.5S11.99 14 9.5 14"/></svg>`,
20
+ // Upload
21
+ "upload": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M9 16h6v-6h4l-7-7l-7 7h4zm-4 2h14v2H5z"/></svg>`,
22
+ // Download
23
+ "download": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M19 9h-4V3H9v6H5l7 7zM5 18v2h14v-2z"/></svg>`,
24
+ // Delete / Trash
25
+ "delete": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6zm2.46-7.12l1.41-1.41L12 12.59l2.12-2.12l1.41 1.41L13.41 14l2.12 2.12l-1.41 1.41L12 15.41l-2.12 2.12l-1.41-1.41L10.59 14zM15.5 4l-1-1h-5l-1 1H5v2h14V4z"/></svg>`
26
+ };
@@ -0,0 +1,7 @@
1
+ import type { NuxtModule } from '@nuxt/schema'
2
+
3
+ import type { default as Module } from './module.js'
4
+
5
+ export type ModuleOptions = typeof Module extends NuxtModule<infer O> ? Partial<O> : Record<string, any>
6
+
7
+ export { default } from './module.js'
@@ -0,0 +1,7 @@
1
+ import type { NuxtModule } from '@nuxt/schema'
2
+
3
+ import type { default as Module } from './module'
4
+
5
+ export type ModuleOptions = typeof Module extends NuxtModule<infer O> ? Partial<O> : Record<string, any>
6
+
7
+ export { default } from './module'
package/nuxt.config.ts ADDED
@@ -0,0 +1,38 @@
1
+ // https://nuxt.com/docs/api/configuration/nuxt-config
2
+ export default defineNuxtConfig({
3
+ // Makes this a Nuxt Layer
4
+ extends: [],
5
+
6
+ css: ['./src/runtime/assets/css/main.css'],
7
+
8
+ // Auto-import components with Orio prefix
9
+ components: {
10
+ dirs: [
11
+ {
12
+ path: './src/runtime/components',
13
+ prefix: 'Orio',
14
+ pathPrefix: false
15
+ }
16
+ ]
17
+ },
18
+
19
+ // Auto-import composables
20
+ imports: {
21
+ dirs: ['./src/runtime/composables']
22
+ },
23
+
24
+ typescript: {
25
+ strict: true,
26
+ typeCheck: true
27
+ },
28
+
29
+ vite: {
30
+ css: {
31
+ preprocessorOptions: {
32
+ scss: {}
33
+ }
34
+ }
35
+ },
36
+
37
+ compatibilityDate: '2025-01-15'
38
+ })
package/package.json ADDED
@@ -0,0 +1,99 @@
1
+ {
2
+ "name": "orio-ui",
3
+ "version": "0.1.0",
4
+ "description": "Modern Nuxt component library with theme support",
5
+ "type": "module",
6
+ "main": "./dist/runtime/index.js",
7
+ "types": "./dist/runtime/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/runtime/index.d.ts",
11
+ "import": "./dist/runtime/index.js"
12
+ },
13
+ "./nuxt": {
14
+ "types": "./dist/module.d.ts",
15
+ "import": "./dist/module.mjs"
16
+ },
17
+ "./composables": {
18
+ "types": "./dist/runtime/composables/index.d.ts",
19
+ "import": "./dist/runtime/composables/index.js"
20
+ },
21
+ "./styles": "./dist/runtime/assets/css/main.css",
22
+ "./theme": "./dist/runtime/assets/css/colors.css"
23
+ },
24
+ "files": [
25
+ "dist",
26
+ "nuxt.config.ts",
27
+ "src"
28
+ ],
29
+ "scripts": {
30
+ "dev": "vitepress dev docs",
31
+ "build": "nuxt-module-build build",
32
+ "prepack": "npm run build",
33
+ "test": "vitest",
34
+ "test:unit": "vitest run",
35
+ "test:watch": "vitest watch",
36
+ "docs:dev": "vitepress dev docs",
37
+ "docs:build": "vitepress build docs",
38
+ "docs:preview": "vitepress preview docs",
39
+ "lint": "eslint .",
40
+ "typecheck": "nuxt typecheck"
41
+ },
42
+ "dependencies": {
43
+ "@nuxt/kit": "^3.15.3",
44
+ "@vueuse/core": "^11.0.0",
45
+ "@vueuse/integrations": "^11.0.0",
46
+ "fuse.js": "^7.0.0",
47
+ "nanoid": "^5.0.0",
48
+ "ofetch": "^1.5.1"
49
+ },
50
+ "devDependencies": {
51
+ "@eslint/js": "^9.39.2",
52
+ "@nuxt/eslint": "^1.12.1",
53
+ "@nuxt/module-builder": "^0.8.0",
54
+ "@vitejs/plugin-vue": "^6.0.3",
55
+ "@vitest/ui": "^2.1.8",
56
+ "@vue/eslint-config-prettier": "^10.2.0",
57
+ "@vue/eslint-config-typescript": "^14.6.0",
58
+ "@vue/test-utils": "^2.4.6",
59
+ "eslint": "^9.39.2",
60
+ "eslint-config-prettier": "^10.1.8",
61
+ "eslint-plugin-prettier": "^5.5.4",
62
+ "eslint-plugin-vue": "^10.6.2",
63
+ "globals": "^17.0.0",
64
+ "jsdom": "^25.0.1",
65
+ "nuxt": "^4.2.2",
66
+ "prettier": "^3.7.4",
67
+ "sass": "^1.70.0",
68
+ "typescript": "^5.9.3",
69
+ "typescript-eslint": "^8.52.0",
70
+ "vitepress": "^1.6.4",
71
+ "vitepress-sidebar": "^1.33.1",
72
+ "vitest": "^2.1.8",
73
+ "vue": "^3.5.13",
74
+ "vue-tsc": "^3.2.1"
75
+ },
76
+ "peerDependencies": {
77
+ "nuxt": "^3.0.0 || ^4.0.0",
78
+ "vue": "^3.3.0"
79
+ },
80
+ "keywords": [
81
+ "nuxt",
82
+ "nuxt-layer",
83
+ "vue",
84
+ "components",
85
+ "ui-library",
86
+ "theme",
87
+ "orio-ui"
88
+ ],
89
+ "author": "oriondor",
90
+ "license": "MIT",
91
+ "repository": {
92
+ "type": "git",
93
+ "url": "https://github.com/oriondor/orio-ui.git"
94
+ },
95
+ "homepage": "https://github.com/oriondor/orio-ui#readme",
96
+ "bugs": {
97
+ "url": "https://github.com/oriondor/orio-ui/issues"
98
+ }
99
+ }
package/src/module.ts ADDED
@@ -0,0 +1,16 @@
1
+ import { defineNuxtModule } from '@nuxt/kit'
2
+
3
+ export default defineNuxtModule({
4
+ meta: {
5
+ name: 'orio-ui',
6
+ configKey: 'orioUi',
7
+ compatibility: {
8
+ nuxt: '^3.0.0 || ^4.0.0'
9
+ }
10
+ },
11
+ defaults: {},
12
+ setup() {
13
+ // Module setup is handled by the layer (nuxt.config.ts)
14
+ // This module entry is required for the build process
15
+ }
16
+ })
@@ -0,0 +1,88 @@
1
+ :root {
2
+ /* --- motion tokens --- */
3
+ --motion-duration-short: 0.05s;
4
+ --motion-duration-medium: 0.15s;
5
+ --motion-distance-small: 0.15rem;
6
+ --motion-distance-medium: 2rem;
7
+ --motion-distance-large: 1rem;
8
+ --motion-ease-default: ease-in;
9
+ --motion-ease-smooth: cubic-bezier(0.22, 1, 0.36, 1);
10
+ }
11
+
12
+ /* fade */
13
+ .animate-fade-enter-active,
14
+ .animate-fade-leave-active {
15
+ transition:
16
+ opacity var(--motion-duration-short) var(--motion-ease-default),
17
+ transform var(--motion-duration-short) var(--motion-ease-default);
18
+ }
19
+
20
+ .animate-fade-enter-from,
21
+ .animate-fade-leave-to {
22
+ opacity: 0;
23
+ transform: translateY(calc(-1 * var(--motion-distance-small)));
24
+ }
25
+
26
+ /* fade-slide */
27
+ .animate-fade-slide-enter-active,
28
+ .animate-fade-slide-leave-active,
29
+ .animate-fade-slide-appear-active {
30
+ transition:
31
+ opacity var(--motion-duration-medium) var(--motion-ease-smooth),
32
+ transform var(--motion-duration-medium) var(--motion-ease-smooth);
33
+ transition-delay: calc(var(--index, 0) * 0.08s);
34
+ }
35
+
36
+ .animate-fade-slide-enter-from,
37
+ .animate-fade-slide-appear-from {
38
+ opacity: 0;
39
+ transform: translateY(var(--motion-distance-medium));
40
+ }
41
+
42
+ .animate-fade-slide-leave-to {
43
+ opacity: 0;
44
+ transform: translateY(calc(-1 * var(--motion-distance-large)));
45
+ }
46
+
47
+ .animate-fade-slide-move {
48
+ transition: transform var(--motion-duration-medium) ease;
49
+ }
50
+
51
+ /* fade-reverse */
52
+ .animate-fade-reverse-enter-active,
53
+ .animate-fade-reverse-leave-active {
54
+ transition:
55
+ opacity var(--motion-duration-short) var(--motion-ease-default),
56
+ transform var(--motion-duration-short) var(--motion-ease-default);
57
+ }
58
+
59
+ .animate-fade-reverse-enter-from,
60
+ .animate-fade-reverse-leave-to {
61
+ opacity: 0;
62
+ transform: translateY(var(--motion-distance-small));
63
+ }
64
+
65
+ /* fade-slide-reverse */
66
+ .animate-fade-slide-reverse-enter-active,
67
+ .animate-fade-slide-reverse-leave-active,
68
+ .animate-fade-slide-reverse-appear-active {
69
+ transition:
70
+ opacity var(--motion-duration-medium) var(--motion-ease-smooth),
71
+ transform var(--motion-duration-medium) var(--motion-ease-smooth);
72
+ transition-delay: calc(var(--index, 0) * 0.08s);
73
+ }
74
+
75
+ .animate-fade-slide-reverse-enter-from,
76
+ .animate-fade-slide-reverse-appear-from {
77
+ opacity: 0;
78
+ transform: translateY(calc(-1 * var(--motion-distance-medium)));
79
+ }
80
+
81
+ .animate-fade-slide-reverse-leave-to {
82
+ opacity: 0;
83
+ transform: translateY(var(--motion-distance-large));
84
+ }
85
+
86
+ .animate-fade-slide-reverse-move {
87
+ transition: transform var(--motion-duration-medium) ease;
88
+ }
@@ -0,0 +1,142 @@
1
+ /* 1) Role-based tokens (don’t change these names in CSS) */
2
+ :root {
3
+ --color-bg: #ffffff;
4
+ --color-surface: #f7f8fa;
5
+ --color-text: #0e1116;
6
+ --color-muted: #626a78;
7
+ --color-border: #bfbfc2;
8
+
9
+ /* Accent family */
10
+ --color-accent: #1f3a8a;
11
+ --color-accent-ink: #ffffff;
12
+ --color-accent-soft: #eef2ff;
13
+ --color-accent-border: #c7d2fe;
14
+ --color-accent-hover: color-mix(in srgb, var(--color-accent) 85%, black 15%);
15
+ --color-accent-active: color-mix(in srgb, var(--color-accent) 75%, black 25%);
16
+ }
17
+
18
+ /* 2) Category themes (light vs dark) */
19
+
20
+ /* Light (default, already matches your root) */
21
+ :root[data-mode="light"] {
22
+ --color-bg: #ffffff;
23
+ --color-surface: #f7f8fa;
24
+ --color-text: #0e1116;
25
+ --color-muted: #626a78;
26
+ --color-border: #bfbfc2;
27
+ }
28
+
29
+ /* Dark */
30
+ :root[data-mode="dark"] {
31
+ --color-bg: #0e1116;
32
+ --color-surface: #1a1d23;
33
+ --color-text: #ffffff;
34
+ --color-muted: #a0a7b5;
35
+ --color-border: #2e333d;
36
+
37
+ --color-accent-ink: #ffffff;
38
+ --color-accent-soft: color-mix(in srgb, var(--color-accent) 12%, #0e1116);
39
+ --color-accent-border: color-mix(in srgb, var(--color-accent) 40%, #0e1116);
40
+
41
+ --color-accent-hover: color-mix(in srgb, var(--color-accent) 30%, white 70%);
42
+ --color-accent-active: color-mix(in srgb, var(--color-accent) 80%, white 25%);
43
+ }
44
+
45
+ /* 3) Accent themes (just accents, independent of light/dark) */
46
+
47
+ :root[data-theme="navy"] {
48
+ --color-accent: hsl(219 20% 25%);
49
+ --color-accent-soft: hsl(221 100% 97%);
50
+ --color-accent-border: hsl(221 61% 84%);
51
+ }
52
+
53
+ :root[data-theme="teal"] {
54
+ --color-accent: hsl(174 72% 28%);
55
+ --color-accent-soft: hsl(174 55% 94%);
56
+ --color-accent-border: hsl(174 40% 75%);
57
+ }
58
+
59
+ :root[data-theme="forest"] {
60
+ --color-accent: hsl(152 45% 25%);
61
+ --color-accent-soft: hsl(152 45% 94%);
62
+ --color-accent-border: hsl(152 30% 72%);
63
+ }
64
+
65
+ :root[data-theme="wine"] {
66
+ --color-accent: hsl(350 55% 34%);
67
+ --color-accent-soft: hsl(350 60% 96%);
68
+ --color-accent-border: hsl(350 35% 78%);
69
+ }
70
+
71
+ :root[data-theme="royal"] {
72
+ --color-accent: hsl(230 60% 40%);
73
+ --color-accent-soft: hsl(230 65% 96%);
74
+ --color-accent-border: hsl(230 35% 78%);
75
+ }
76
+
77
+ /* Extra colors */
78
+ :root {
79
+ /* 🔴 Red */
80
+ --color-red: #dc2626;
81
+ --color-red-ink: #ffffff;
82
+ --color-red-soft: #fef2f2;
83
+ --color-red-border: #fecaca;
84
+ --color-red-hover: color-mix(in srgb, var(--color-red) 85%, black 15%);
85
+ --color-red-active: color-mix(in srgb, var(--color-red) 75%, black 25%);
86
+
87
+ /* 🟠 Orange */
88
+ --color-orange: #ea580c;
89
+ --color-orange-ink: #ffffff;
90
+ --color-orange-soft: #fff7ed;
91
+ --color-orange-border: #fed7aa;
92
+ --color-orange-hover: color-mix(in srgb, var(--color-orange) 85%, black 15%);
93
+ --color-orange-active: color-mix(in srgb, var(--color-orange) 75%, black 25%);
94
+
95
+ /* 🟡 Yellow */
96
+ --color-yellow: #ca8a04;
97
+ --color-yellow-ink: #ffffff;
98
+ --color-yellow-soft: #fefce8;
99
+ --color-yellow-border: #fef08a;
100
+ --color-yellow-hover: color-mix(in srgb, var(--color-yellow) 85%, black 15%);
101
+ --color-yellow-active: color-mix(in srgb, var(--color-yellow) 75%, black 25%);
102
+
103
+ /* 🟢 Green */
104
+ --color-green: #15803d;
105
+ --color-green-ink: #ffffff;
106
+ --color-green-soft: #f0fdf4;
107
+ --color-green-border: #bbf7d0;
108
+ --color-green-hover: color-mix(in srgb, var(--color-green) 85%, black 15%);
109
+ --color-green-active: color-mix(in srgb, var(--color-green) 75%, black 25%);
110
+
111
+ /* 🩵 Teal / Cyan */
112
+ --color-teal: #0d9488;
113
+ --color-teal-ink: #ffffff;
114
+ --color-teal-soft: #f0fdfa;
115
+ --color-teal-border: #99f6e4;
116
+ --color-teal-hover: color-mix(in srgb, var(--color-teal) 85%, black 15%);
117
+ --color-teal-active: color-mix(in srgb, var(--color-teal) 75%, black 25%);
118
+
119
+ /* 🔵 Blue */
120
+ --color-blue: #2563eb;
121
+ --color-blue-ink: #ffffff;
122
+ --color-blue-soft: #eff6ff;
123
+ --color-blue-border: #bfdbfe;
124
+ --color-blue-hover: color-mix(in srgb, var(--color-blue) 85%, black 15%);
125
+ --color-blue-active: color-mix(in srgb, var(--color-blue) 75%, black 25%);
126
+
127
+ /* 🟣 Purple */
128
+ --color-purple: #7e22ce;
129
+ --color-purple-ink: #ffffff;
130
+ --color-purple-soft: #faf5ff;
131
+ --color-purple-border: #e9d5ff;
132
+ --color-purple-hover: color-mix(in srgb, var(--color-purple) 85%, black 15%);
133
+ --color-purple-active: color-mix(in srgb, var(--color-purple) 75%, black 25%);
134
+
135
+ /* 💗 Pink */
136
+ --color-pink: #db2777;
137
+ --color-pink-ink: #ffffff;
138
+ --color-pink-soft: #fdf2f8;
139
+ --color-pink-border: #fbcfe8;
140
+ --color-pink-hover: color-mix(in srgb, var(--color-pink) 85%, black 15%);
141
+ --color-pink-active: color-mix(in srgb, var(--color-pink) 75%, black 25%);
142
+ }
@@ -0,0 +1,33 @@
1
+ .gradient-hover {
2
+ --gh-color: #fff;
3
+ --gh-angle: 120deg;
4
+ --gh-peek-x: 95%;
5
+ --gh-mix-base: black;
6
+
7
+ background-image: linear-gradient(
8
+ var(--gh-angle),
9
+ color-mix(in srgb, var(--gh-color) 90%, var(--gh-mix-base)) 0%,
10
+ var(--gh-color) 40%,
11
+ color-mix(in srgb, var(--gh-color) 90%, var(--gh-mix-base)) 80%
12
+ );
13
+ background-repeat: no-repeat;
14
+
15
+ background-size: 0% 0%;
16
+ background-position: 0% 0%;
17
+
18
+ transition:
19
+ background-position 0.8s ease,
20
+ border-color 0.2s ease;
21
+ will-change: background-size, background-position;
22
+ }
23
+
24
+ .gradient-hover:hover {
25
+ background-size: 200% 100%;
26
+ background-position: var(--gh-peek-x) 0;
27
+ }
28
+
29
+ /* Dark mode: now theme-aware */
30
+ :root[data-mode="dark"] .gradient-hover {
31
+ --gh-color: var(--color-accent); /* switch from static white to theme accent */
32
+ --gh-mix-base: var(--color-bg); /* blend into dark background */
33
+ }
@@ -0,0 +1,11 @@
1
+ /* Main entry point for i UI styles */
2
+ @import "./colors.css";
3
+ @import "./animation.css";
4
+ @import "./scroll.css";
5
+
6
+ /* Base reset for Orio components */
7
+ *,
8
+ *::before,
9
+ *::after {
10
+ box-sizing: border-box;
11
+ }
@@ -0,0 +1,46 @@
1
+ /* ===== Scrollbar (WebKit) ===== */
2
+ ::-webkit-scrollbar {
3
+ width: 12px;
4
+ height: 12px;
5
+ }
6
+
7
+ ::-webkit-scrollbar-track {
8
+ background: var(--color-surface);
9
+ border-left: 1px solid var(--color-border);
10
+ }
11
+
12
+ ::-webkit-scrollbar-thumb {
13
+ background-color: var(--color-accent-border);
14
+ border-radius: 8px;
15
+ border: 3px solid var(--color-surface);
16
+ transition: background-color 0.2s ease;
17
+ }
18
+
19
+ ::-webkit-scrollbar-thumb:hover {
20
+ background-color: var(--color-accent);
21
+ }
22
+
23
+ ::-webkit-scrollbar-corner {
24
+ background: var(--color-surface);
25
+ }
26
+
27
+ /* ===== Scrollbar (Firefox) ===== */
28
+ * {
29
+ scrollbar-width: thin;
30
+ scrollbar-color: var(--color-accent-border) var(--color-surface);
31
+ }
32
+
33
+ /* ===== Dark mode adjustments ===== */
34
+ :root[data-mode="dark"] ::-webkit-scrollbar-track {
35
+ background: var(--color-bg);
36
+ border-left: 1px solid var(--color-border);
37
+ }
38
+
39
+ :root[data-mode="dark"] ::-webkit-scrollbar-thumb {
40
+ background-color: var(--color-accent-border);
41
+ border: 3px solid var(--color-bg);
42
+ }
43
+
44
+ :root[data-mode="dark"] * {
45
+ scrollbar-color: var(--color-accent-border) var(--color-bg);
46
+ }
@@ -0,0 +1,110 @@
1
+ <script setup lang="ts">
2
+ import { computed, toRefs, useAttrs, useSlots } from 'vue';
3
+
4
+ interface Props {
5
+ type?: 'primary' | 'secondary' | 'subdued';
6
+ icon?: string;
7
+ loading?: boolean;
8
+ disabled?: boolean;
9
+ }
10
+
11
+ const props = withDefaults(defineProps<Props>(), {
12
+ type: 'primary',
13
+ });
14
+
15
+ const { loading, disabled } = toRefs(props);
16
+
17
+ const attrs = useAttrs();
18
+ const slots = useSlots();
19
+
20
+ const isIconOnly = computed(() => {
21
+ const hasIcon = !!props.icon || !!slots.icon;
22
+ const hasDefault = !!slots.default;
23
+ return hasIcon && !hasDefault;
24
+ });
25
+
26
+ const emit = defineEmits<{
27
+ (e: 'click', event: PointerEvent): void;
28
+ }>();
29
+
30
+ function click(event: PointerEvent) {
31
+ if (loading.value || disabled.value) return;
32
+ emit('click', event);
33
+ }
34
+ </script>
35
+
36
+ <template>
37
+ <orio-control-element>
38
+ <button
39
+ v-bind="attrs"
40
+ :class="[type, 'gradient-hover', { 'icon-only': isIconOnly }]"
41
+ @click="click"
42
+ >
43
+ <orio-loading-spinner v-if="loading" />
44
+ <slot v-else name="icon">
45
+ <orio-icon v-if="icon" :name="icon" />
46
+ </slot>
47
+ <slot />
48
+ </button>
49
+ </orio-control-element>
50
+ </template>
51
+
52
+ <style lang="scss" scoped>
53
+ button {
54
+ background-color: var(--color-accent);
55
+ color: var(--color-accent-ink);
56
+ border: 1px solid transparent;
57
+ border-radius: 4px;
58
+ padding: 8px 16px;
59
+ cursor: pointer;
60
+ display: inline-flex;
61
+ align-items: center;
62
+ gap: 0.5rem;
63
+ user-select: none;
64
+
65
+ &.icon-only {
66
+ padding: 0;
67
+ border-radius: 50%;
68
+ }
69
+
70
+ &:disabled {
71
+ background-color: var(--color-accent-soft);
72
+ color: var(--color-muted);
73
+ border-color: var(--color-accent-border);
74
+ cursor: not-allowed;
75
+ }
76
+
77
+ &:active {
78
+ border: 1px solid var(--color-accent-border);
79
+ }
80
+
81
+ &.primary {
82
+ --gh-color: var(--color-accent);
83
+ }
84
+
85
+ &.secondary {
86
+ background-color: transparent;
87
+ border: 1px solid var(--color-accent);
88
+ color: var(--color-accent);
89
+ &:hover {
90
+ color: var(--color-accent-hover);
91
+ }
92
+ }
93
+
94
+ &.subdued {
95
+ background-color: transparent;
96
+ color: var(--color-accent);
97
+ &:hover {
98
+ color: var(--color-accent-hover);
99
+ }
100
+ }
101
+
102
+ &:active {
103
+ border-color: var(--color-accent-border) !important;
104
+ }
105
+
106
+ &:hover {
107
+ color: var(--color-accent-ink);
108
+ }
109
+ }
110
+ </style>