@shohojdhara/atomix 0.2.8 → 0.3.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 (50) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +40 -1
  3. package/dist/atomix.css +96 -39
  4. package/dist/atomix.min.css +2 -2
  5. package/dist/index.d.ts +632 -2
  6. package/dist/index.esm.js +1306 -95
  7. package/dist/index.esm.js.map +1 -1
  8. package/dist/index.js +1330 -94
  9. package/dist/index.js.map +1 -1
  10. package/dist/index.min.js +1 -1
  11. package/dist/index.min.js.map +1 -1
  12. package/dist/themes/applemix.css +96 -39
  13. package/dist/themes/applemix.min.css +2 -2
  14. package/dist/themes/boomdevs.css +96 -39
  15. package/dist/themes/boomdevs.min.css +2 -2
  16. package/dist/themes/esrar.css +96 -39
  17. package/dist/themes/esrar.min.css +2 -2
  18. package/dist/themes/flashtrade.css +97 -40
  19. package/dist/themes/flashtrade.min.css +2 -2
  20. package/dist/themes/mashroom.css +96 -39
  21. package/dist/themes/mashroom.min.css +3 -3
  22. package/dist/themes/shaj-default.css +96 -39
  23. package/dist/themes/shaj-default.min.css +2 -2
  24. package/package.json +13 -2
  25. package/src/components/Breadcrumb/Breadcrumb.tsx +8 -3
  26. package/src/components/Card/Card.tsx +9 -4
  27. package/src/components/Footer/Footer.stories.tsx +1 -2
  28. package/src/components/Footer/Footer.tsx +0 -5
  29. package/src/components/Footer/FooterLink.tsx +3 -2
  30. package/src/components/Footer/FooterSection.tsx +0 -7
  31. package/src/components/Navigation/Nav/NavItem.tsx +8 -3
  32. package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +301 -13
  33. package/src/components/Navigation/SideMenu/SideMenu.tsx +236 -9
  34. package/src/components/Navigation/SideMenu/SideMenuItem.tsx +9 -4
  35. package/src/lib/composables/useSideMenu.ts +89 -30
  36. package/src/lib/index.ts +5 -0
  37. package/src/lib/theme/ThemeContext.tsx +17 -0
  38. package/src/lib/theme/ThemeManager.stories.tsx +472 -0
  39. package/src/lib/theme/ThemeManager.test.ts +186 -0
  40. package/src/lib/theme/ThemeManager.ts +501 -0
  41. package/src/lib/theme/ThemeProvider.tsx +227 -0
  42. package/src/lib/theme/index.ts +56 -0
  43. package/src/lib/theme/types.ts +247 -0
  44. package/src/lib/theme/useTheme.test.tsx +66 -0
  45. package/src/lib/theme/useTheme.ts +80 -0
  46. package/src/lib/theme/utils.test.ts +140 -0
  47. package/src/lib/theme/utils.ts +398 -0
  48. package/src/lib/types/components.ts +32 -0
  49. package/src/styles/06-components/_components.card.scss +39 -24
  50. package/src/styles/06-components/_components.side-menu.scss +79 -18
package/CHANGELOG.md CHANGED
@@ -7,6 +7,66 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.3.0] - 2025-12-03
11
+
12
+ ### Added
13
+
14
+ #### Theme Manager System
15
+ - **Theme Manager Class**: Core theme management for vanilla JavaScript applications
16
+ - Dynamic theme loading with CSS file management
17
+ - Theme persistence using localStorage
18
+ - Event system for theme changes (`themeChange`, `themeLoad`, `themeError`)
19
+ - Theme preloading for faster switching
20
+ - SSR-safe implementation
21
+ - Comprehensive error handling
22
+
23
+ - **React Integration**:
24
+ - `ThemeProvider` component for React applications
25
+ - `useTheme` hook for accessing theme state
26
+ - `ThemeContext` for context-based state management
27
+ - Loading and error states
28
+ - Automatic cleanup on unmount
29
+
30
+ - **TypeScript Support**:
31
+ - Complete type definitions for all theme utilities
32
+ - `ThemeMetadata`, `ThemeManagerConfig`, `ThemeChangeEvent` interfaces
33
+ - Type-safe event system
34
+ - Full IntelliSense support
35
+
36
+ - **Package Exports**:
37
+ - `@shohojdhara/atomix/theme` - Theme manager utilities
38
+ - `@shohojdhara/atomix/themes/config` - Theme configuration
39
+
40
+ - **Documentation**:
41
+ - Comprehensive theme manager guide (`docs/THEME_MANAGER.md`)
42
+ - React usage examples
43
+ - Vanilla JavaScript examples
44
+ - API reference
45
+ - Migration guide
46
+ - Troubleshooting section
47
+
48
+ - **Runtime Configuration**:
49
+ - Added runtime section to `themes.config.js`
50
+ - Support for CDN paths
51
+ - Theme preloading configuration
52
+ - Theme dependencies mapping
53
+
54
+ ### Changed
55
+ - Updated `README.md` with theme manager usage examples
56
+ - Enhanced `themes.config.js` with runtime configuration options
57
+ - Updated `src/lib/index.ts` to export theme utilities
58
+
59
+ ### Features
60
+ - 🎨 Dynamic theme switching without page reload
61
+ - 💾 Automatic theme persistence across sessions
62
+ - ⚡ Theme preloading for instant switching
63
+ - 🔒 Full TypeScript support
64
+ - ♿ SSR compatible (Next.js, Remix, etc.)
65
+ - 🎯 Works with React and vanilla JavaScript
66
+ - 📦 Zero breaking changes to existing API
67
+
68
+ ## [0.2.9] - 2025-01-29
69
+
10
70
  ## [0.2.8] - 2025-01-28
11
71
 
12
72
  ## [0.2.7] - 2025-01-27
package/README.md CHANGED
@@ -32,7 +32,6 @@ npm install @shohojdhara/atomix
32
32
 
33
33
  ### React
34
34
 
35
- ```jsx
36
35
  import { Button } from '@shohojdhara/atomix';
37
36
  import '@shohojdhara/atomix/css';
38
37
 
@@ -41,6 +40,46 @@ function App() {
41
40
  }
42
41
  ```
43
42
 
43
+ ### Theme Management
44
+
45
+ Atomix includes a powerful theme manager for dynamic theme switching:
46
+
47
+ ```jsx
48
+ import { ThemeProvider, useTheme } from '@shohojdhara/atomix/theme';
49
+ import { themesConfig } from '@shohojdhara/atomix/themes/config';
50
+
51
+ function App() {
52
+ return (
53
+ <ThemeProvider themes={themesConfig.metadata} defaultTheme="shaj-default">
54
+ <YourApp />
55
+ </ThemeProvider>
56
+ );
57
+ }
58
+
59
+ function ThemeSwitcher() {
60
+ const { theme, setTheme, availableThemes } = useTheme();
61
+
62
+ return (
63
+ <select value={theme} onChange={(e) => setTheme(e.target.value)}>
64
+ {availableThemes.map(t => (
65
+ <option key={t.class} value={t.class}>{t.name}</option>
66
+ ))}
67
+ </select>
68
+ );
69
+ }
70
+ ```
71
+
72
+ **Available Themes:**
73
+ - `shaj-default` - Default theme (stable)
74
+ - `flashtrade` - Crypto trading platform theme (stable)
75
+ - `boomdevs` - BoomDevs theme (beta)
76
+ - `esrar` - Esrar theme (beta)
77
+ - `mashroom` - Mashroom theme (beta)
78
+ - `applemix` - Apple-inspired glass morphism theme (experimental)
79
+
80
+ For detailed theme manager documentation, see [Theme Manager Guide](docs/THEME_MANAGER.md).
81
+
82
+
44
83
  ## Styles
45
84
 
46
85
  Atomix provides comprehensive styling through CSS or SCSS:
package/dist/atomix.css CHANGED
@@ -3028,6 +3028,10 @@ a, a:hover {
3028
3028
  .c-card--filled {
3029
3029
  background-color: var(--atomix-card-bg);
3030
3030
  }
3031
+ .c-card--glass {
3032
+ max-width: none;
3033
+ background-color: color-mix(in srgb, var(--atomix-card-bg) 50%, transparent);
3034
+ }
3031
3035
  .c-card--outlined {
3032
3036
  background-color: transparent;
3033
3037
  border-width: var(--atomix-card-border-width);
@@ -3037,22 +3041,22 @@ a, a:hover {
3037
3041
  border: none;
3038
3042
  }
3039
3043
  .c-card--elevated {
3040
- box-shadow: var(--atomix-box-shadow-md, 0 4px 6px rgba(0, 0, 0, 0.1));
3044
+ box-shadow: var(--atomix-box-shadow-md);
3041
3045
  }
3042
3046
  .c-card--elevation-none {
3043
3047
  box-shadow: none;
3044
3048
  }
3045
3049
  .c-card--elevation-sm {
3046
- box-shadow: var(--atomix-box-shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.05));
3050
+ box-shadow: var(--atomix-box-shadow-sm);
3047
3051
  }
3048
3052
  .c-card--elevation-md {
3049
- box-shadow: var(--atomix-box-shadow-md, 0 4px 6px rgba(0, 0, 0, 0.1));
3053
+ box-shadow: var(--atomix-box-shadow-md);
3050
3054
  }
3051
3055
  .c-card--elevation-lg {
3052
- box-shadow: var(--atomix-box-shadow-lg, 0 10px 15px rgba(0, 0, 0, 0.1));
3056
+ box-shadow: var(--atomix-box-shadow-lg);
3053
3057
  }
3054
3058
  .c-card--elevation-xl {
3055
- box-shadow: var(--atomix-box-shadow-xl, 0 20px 25px rgba(0, 0, 0, 0.1));
3059
+ box-shadow: var(--atomix-box-shadow-xl);
3056
3060
  }
3057
3061
  .c-card--disabled {
3058
3062
  opacity: 0.6;
@@ -3074,7 +3078,7 @@ a, a:hover {
3074
3078
  content: "";
3075
3079
  position: absolute;
3076
3080
  inset: 0;
3077
- background-color: rgba(255, 255, 255, 0.7);
3081
+ background-color: var(--atomix-card-bg-hover);
3078
3082
  -webkit-backdrop-filter: blur(1px);
3079
3083
  backdrop-filter: blur(1px);
3080
3084
  z-index: 1;
@@ -3086,7 +3090,7 @@ a, a:hover {
3086
3090
  .c-card--selected {
3087
3091
  --atomix-card-border-color: var(--atomix-brand-border-subtle);
3088
3092
  --atomix-card-border-width: 2px;
3089
- box-shadow: var(--atomix-box-shadow-md, 0 4px 6px rgba(0, 0, 0, 0.1));
3093
+ box-shadow: var(--atomix-box-shadow-md);
3090
3094
  }
3091
3095
  .c-card--interactive {
3092
3096
  cursor: pointer;
@@ -3094,7 +3098,7 @@ a, a:hover {
3094
3098
  }
3095
3099
  .c-card--interactive:hover:not(.c-card--interactive--disabled) {
3096
3100
  transform: translateY(-2px);
3097
- box-shadow: var(--atomix-box-shadow-lg, 0 10px 15px rgba(0, 0, 0, 0.1));
3101
+ box-shadow: var(--atomix-box-shadow-lg);
3098
3102
  }
3099
3103
  .c-card--interactive:active:not(.c-card--interactive--disabled) {
3100
3104
  transform: translateY(0);
@@ -3104,54 +3108,66 @@ a, a:hover {
3104
3108
  --atomix-card-bg-hover: var(--atomix-brand-bg-subtle);
3105
3109
  --atomix-card-border-color: var(--atomix-brand-border-subtle);
3106
3110
  --atomix-card-title-color: var(--atomix-brand-text-emphasis);
3111
+ --atomix-card-icon-bg: var(--atomix-brand-text-emphasis);
3112
+ --atomix-card-icon-color: var(--atomix-brand-bg-subtle);
3107
3113
  }
3108
3114
  .c-card--secondary {
3109
3115
  --atomix-card-bg: var(--atomix-secondary-bg-subtle);
3110
3116
  --atomix-card-bg-hover: var(--atomix-secondary-bg-subtle);
3111
3117
  --atomix-card-border-color: var(--atomix-secondary-border-subtle);
3112
3118
  --atomix-card-title-color: var(--atomix-secondary-text-emphasis);
3119
+ --atomix-card-icon-bg: var(--atomix-secondary-text-emphasis);
3120
+ --atomix-card-icon-color: var(--atomix-secondary-bg-subtle);
3113
3121
  }
3114
3122
  .c-card--success {
3115
3123
  --atomix-card-bg: var(--atomix-success-bg-subtle);
3116
3124
  --atomix-card-bg-hover: var(--atomix-success-bg-subtle);
3117
3125
  --atomix-card-border-color: var(--atomix-success-border-subtle);
3118
3126
  --atomix-card-title-color: var(--atomix-success-text-emphasis);
3127
+ --atomix-card-icon-bg: var(--atomix-success-text-emphasis);
3128
+ --atomix-card-icon-color: var(--atomix-success-bg-subtle);
3119
3129
  }
3120
3130
  .c-card--info {
3121
3131
  --atomix-card-bg: var(--atomix-info-bg-subtle);
3122
3132
  --atomix-card-bg-hover: var(--atomix-info-bg-subtle);
3123
3133
  --atomix-card-border-color: var(--atomix-info-border-subtle);
3124
3134
  --atomix-card-title-color: var(--atomix-info-text-emphasis);
3135
+ --atomix-card-icon-bg: var(--atomix-info-text-emphasis);
3136
+ --atomix-card-icon-color: var(--atomix-info-bg-subtle);
3125
3137
  }
3126
3138
  .c-card--warning {
3127
3139
  --atomix-card-bg: var(--atomix-warning-bg-subtle);
3128
3140
  --atomix-card-bg-hover: var(--atomix-warning-bg-subtle);
3129
3141
  --atomix-card-border-color: var(--atomix-warning-border-subtle);
3130
3142
  --atomix-card-title-color: var(--atomix-warning-text-emphasis);
3143
+ --atomix-card-icon-bg: var(--atomix-warning-text-emphasis);
3144
+ --atomix-card-icon-color: var(--atomix-warning-bg-subtle);
3131
3145
  }
3132
3146
  .c-card--error {
3133
3147
  --atomix-card-bg: var(--atomix-error-bg-subtle);
3134
3148
  --atomix-card-bg-hover: var(--atomix-error-bg-subtle);
3135
3149
  --atomix-card-border-color: var(--atomix-error-border-subtle);
3136
3150
  --atomix-card-title-color: var(--atomix-error-text-emphasis);
3151
+ --atomix-card-icon-bg: var(--atomix-error-text-emphasis);
3152
+ --atomix-card-icon-color: var(--atomix-error-bg-subtle);
3137
3153
  }
3138
3154
  .c-card--light {
3139
3155
  --atomix-card-bg: var(--atomix-light);
3140
3156
  --atomix-card-bg-hover: var(--atomix-light-hover);
3141
3157
  --atomix-card-border-color: var(--atomix-light);
3142
3158
  --atomix-card-title-color: var(--atomix-dark);
3143
- --atomix-card-text-color: rgba(0, 0, 0, 0.7);
3159
+ --atomix-card-text-color: var(--atomix-dark);
3160
+ --atomix-card-icon-bg: var(--atomix-dark);
3161
+ --atomix-card-icon-color: var(--atomix-light);
3144
3162
  }
3145
3163
  .c-card--dark {
3146
3164
  --atomix-card-bg: var(--atomix-dark);
3147
3165
  --atomix-card-bg-hover: var(--atomix-dark-hover);
3148
3166
  --atomix-card-border-color: var(--atomix-dark);
3149
3167
  --atomix-card-title-color: var(--atomix-light);
3150
- --atomix-card-text-color: rgba(255, 255, 255, 0.8);
3151
- }
3152
- .c-card--glass {
3153
- max-width: none;
3154
- background-color: color-mix(in srgb, var(--atomix-card-bg) 50%, transparent);
3168
+ --atomix-card-text-color: var(--atomix-light);
3169
+ --atomix-card-icon-bg: var(--atomix-light);
3170
+ --atomix-card-icon-color: var(--atomix-dark);
3155
3171
  }
3156
3172
  .c-card__loading {
3157
3173
  position: absolute;
@@ -3168,8 +3184,8 @@ a, a:hover {
3168
3184
  height: 2.5rem;
3169
3185
  border: 4px solid;
3170
3186
  border-color: var(--atomix-border-primary, rgba(0, 0, 0, 0.15));
3171
- border-top-color: var(--atomix-brand-text-emphasis, var(--atomix-primary, #7c3aed));
3172
- border-right-color: var(--atomix-brand-text-emphasis, var(--atomix-primary, #7c3aed));
3187
+ border-top-color: var(--atomix-brand-text-emphasis, var(--atomix-primary));
3188
+ border-right-color: var(--atomix-brand-text-emphasis, var(--atomix-primary));
3173
3189
  border-radius: 50%;
3174
3190
  animation: spin 0.8s linear infinite;
3175
3191
  background-color: transparent;
@@ -9401,30 +9417,30 @@ a, a:hover {
9401
9417
  padding: 1rem 1rem;
9402
9418
  }
9403
9419
  }
9404
- @media (max-width: 991.98px) {
9405
- .c-side-menu__wrapper {
9406
- height: 0px;
9407
- overflow: hidden;
9408
- -webkit-user-select: none;
9409
- -moz-user-select: none;
9410
- user-select: none;
9411
- transition: var(--atomix-side-menu-wrapper-transition);
9412
- }
9420
+ .c-side-menu__wrapper {
9421
+ overflow: hidden;
9422
+ -webkit-user-select: none;
9423
+ -moz-user-select: none;
9424
+ user-select: none;
9425
+ transition: var(--atomix-side-menu-wrapper-transition);
9426
+ height: 0px;
9413
9427
  }
9414
- @media (max-width: 991.98px) {
9415
- .c-side-menu__inner {
9416
- padding-top: var(--atomix-side-menu-inner-padding-top);
9417
- }
9428
+ .c-side-menu__inner {
9429
+ padding-top: var(--atomix-side-menu-inner-padding-top);
9418
9430
  }
9419
9431
  .c-side-menu__title {
9420
9432
  color: var(--atomix-side-menu-title-color);
9421
9433
  font-size: var(--atomix-side-menu-title-font-size);
9422
9434
  font-weight: var(--atomix-side-menu-title-font-weight);
9435
+ margin: 0;
9423
9436
  margin-bottom: var(--atomix-side-menu-title-spacer-y);
9424
- margin: 0 0 var(--atomix-side-menu-title-spacer-y) 0;
9437
+ }
9438
+ .c-side-menu__toggler .c-side-menu__title {
9439
+ margin-bottom: 0;
9440
+ flex: 1 1;
9425
9441
  }
9426
9442
  .c-side-menu__toggler {
9427
- display: none;
9443
+ display: flex;
9428
9444
  align-items: center;
9429
9445
  justify-content: space-between;
9430
9446
  width: 100%;
@@ -9438,19 +9454,18 @@ a, a:hover {
9438
9454
  user-select: none;
9439
9455
  transition: var(--atomix-side-menu-toggler-transition);
9440
9456
  text-align: left;
9441
- }
9442
- @media (max-width: 991.98px) {
9443
- .c-side-menu__toggler {
9444
- display: flex;
9445
- }
9457
+ margin: 0;
9446
9458
  }
9447
9459
  .c-side-menu__toggler:hover {
9448
9460
  background-color: var(--atomix-side-menu-toggler-hover-bg);
9449
9461
  }
9450
- .c-side-menu__toggler:focus {
9462
+ .c-side-menu__toggler:focus-visible {
9451
9463
  outline: 2px solid var(--atomix-focus-ring-color);
9452
9464
  outline-offset: 2px;
9453
9465
  }
9466
+ .c-side-menu__toggler:focus:not(:focus-visible) {
9467
+ outline: none;
9468
+ }
9454
9469
  .c-side-menu__toggler:active {
9455
9470
  transform: scale(0.98);
9456
9471
  }
@@ -9462,6 +9477,23 @@ a, a:hover {
9462
9477
  .c-side-menu__toggler-icon {
9463
9478
  transition: var(--atomix-side-menu-toggler-transition);
9464
9479
  font-size: 0.875em;
9480
+ flex-shrink: 0;
9481
+ display: inline-flex;
9482
+ align-items: center;
9483
+ justify-content: center;
9484
+ transform-origin: center;
9485
+ }
9486
+ .c-side-menu__toggler--nested {
9487
+ margin-bottom: var(--atomix-side-menu-item-gap);
9488
+ }
9489
+ .c-side-menu__nested-wrapper {
9490
+ overflow: hidden;
9491
+ transition: var(--atomix-side-menu-wrapper-transition);
9492
+ height: 0px;
9493
+ margin: 0;
9494
+ }
9495
+ .c-side-menu__nested-inner {
9496
+ display: block;
9465
9497
  }
9466
9498
  .c-side-menu__list {
9467
9499
  list-style: none;
@@ -9474,6 +9506,9 @@ a, a:hover {
9474
9506
  .c-side-menu__list:last-child {
9475
9507
  margin-bottom: 0;
9476
9508
  }
9509
+ .c-side-menu__item {
9510
+ display: block;
9511
+ }
9477
9512
  .c-side-menu__link {
9478
9513
  display: flex;
9479
9514
  align-items: center;
@@ -9489,16 +9524,20 @@ a, a:hover {
9489
9524
  text-decoration: none;
9490
9525
  cursor: pointer;
9491
9526
  transition: var(--atomix-side-menu-item-transition);
9527
+ position: relative;
9492
9528
  }
9493
9529
  .c-side-menu__link:hover {
9494
9530
  color: var(--atomix-side-menu-item-hover-color);
9495
9531
  background-color: var(--atomix-side-menu-item-hover-bg);
9496
9532
  text-decoration: none;
9497
9533
  }
9498
- .c-side-menu__link:focus {
9534
+ .c-side-menu__link:focus-visible {
9499
9535
  outline: 2px solid var(--atomix-focus-ring-color);
9500
9536
  outline-offset: 2px;
9501
9537
  }
9538
+ .c-side-menu__link:focus:not(:focus-visible) {
9539
+ outline: none;
9540
+ }
9502
9541
  .c-side-menu__link:active {
9503
9542
  transform: scale(0.98);
9504
9543
  }
@@ -9525,9 +9564,15 @@ a, a:hover {
9525
9564
  background-color: transparent;
9526
9565
  border-bottom: none;
9527
9566
  }
9528
- .c-side-menu.is-open .c-side-menu__toggler-icon {
9567
+ .c-side-menu.is-open .c-side-menu__toggler .c-side-menu__toggler-icon {
9529
9568
  transform: rotate(90deg);
9530
9569
  }
9570
+ .c-side-menu__toggler--nested.is-open .c-side-menu__toggler-icon {
9571
+ transform: rotate(90deg);
9572
+ }
9573
+ .c-side-menu__toggler--nested.is-open + .c-side-menu__nested-wrapper {
9574
+ height: auto;
9575
+ }
9531
9576
  .dark-mode .c-side-menu {
9532
9577
  --atomix-side-menu-bg: var(--atomix-gray-9);
9533
9578
  --atomix-side-menu-border-color: var(--atomix-gray-7);
@@ -9545,6 +9590,18 @@ a, a:hover {
9545
9590
  .c-side-menu .c-side-menu__toggler-icon {
9546
9591
  transition: none;
9547
9592
  }
9593
+ .c-side-menu .c-side-menu__toggler:active {
9594
+ transform: none;
9595
+ }
9596
+ .c-side-menu .c-side-menu__link:active {
9597
+ transform: none;
9598
+ }
9599
+ }
9600
+ @media (prefers-contrast: high) {
9601
+ .c-side-menu .c-side-menu__toggler:focus-visible,
9602
+ .c-side-menu .c-side-menu__link:focus-visible {
9603
+ outline-width: 3px;
9604
+ }
9548
9605
  }
9549
9606
  .c-skeleton {
9550
9607
  --atomix-skeleton-width: 100%;