@abstraks-dev/ui-library 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +708 -0
  3. package/dist/__tests__/Anchor.test.js +145 -0
  4. package/dist/__tests__/ArrowRight.test.js +91 -0
  5. package/dist/__tests__/Avatar.test.js +123 -0
  6. package/dist/__tests__/Button.test.js +82 -0
  7. package/dist/__tests__/Card.test.js +198 -0
  8. package/dist/__tests__/CheckCircle.test.js +98 -0
  9. package/dist/__tests__/Checkbox.test.js +161 -0
  10. package/dist/__tests__/ChevronDown.test.js +73 -0
  11. package/dist/__tests__/Close.test.js +98 -0
  12. package/dist/__tests__/EditSquare.test.js +99 -0
  13. package/dist/__tests__/Error.test.js +74 -0
  14. package/dist/__tests__/Footer.test.js +66 -0
  15. package/dist/__tests__/Heading.test.js +227 -0
  16. package/dist/__tests__/Hero.test.js +74 -0
  17. package/dist/__tests__/Label.test.js +123 -0
  18. package/dist/__tests__/Loader.test.js +115 -0
  19. package/dist/__tests__/MenuHover.test.js +137 -0
  20. package/dist/__tests__/Paragraph.test.js +93 -0
  21. package/dist/__tests__/PlusCircle.test.js +99 -0
  22. package/dist/__tests__/Radio.test.js +153 -0
  23. package/dist/__tests__/Select.test.js +187 -0
  24. package/dist/__tests__/Tabs.test.js +162 -0
  25. package/dist/__tests__/TextArea.test.js +127 -0
  26. package/dist/__tests__/TextInput.test.js +181 -0
  27. package/dist/__tests__/Toggle.test.js +120 -0
  28. package/dist/__tests__/TrashX.test.js +99 -0
  29. package/dist/__tests__/useHeadingAccessibility.test.js +144 -0
  30. package/dist/components/Anchor.js +131 -0
  31. package/dist/components/Animation.js +129 -0
  32. package/dist/components/AnimationGroup.js +207 -0
  33. package/dist/components/AnimationToggle.js +216 -0
  34. package/dist/components/Avatar.js +153 -0
  35. package/dist/components/Button.js +218 -0
  36. package/dist/components/Card.js +222 -0
  37. package/dist/components/Checkbox.js +305 -0
  38. package/dist/components/Crud.js +564 -0
  39. package/dist/components/DragAndDrop.js +337 -0
  40. package/dist/components/Error.js +206 -0
  41. package/dist/components/Footer.js +99 -0
  42. package/dist/components/Form.js +412 -0
  43. package/dist/components/Header.js +372 -0
  44. package/dist/components/Heading.js +134 -0
  45. package/dist/components/Hero.js +181 -0
  46. package/dist/components/Label.js +256 -0
  47. package/dist/components/Loader.js +302 -0
  48. package/dist/components/MenuHover.js +114 -0
  49. package/dist/components/Paragraph.js +128 -0
  50. package/dist/components/Prompt.js +61 -0
  51. package/dist/components/Radio.js +254 -0
  52. package/dist/components/Select.js +422 -0
  53. package/dist/components/SideMenu.js +313 -0
  54. package/dist/components/Tabs.js +297 -0
  55. package/dist/components/TextArea.js +370 -0
  56. package/dist/components/TextInput.js +286 -0
  57. package/dist/components/Toggle.js +186 -0
  58. package/dist/components/crudFiles/CrudEditBase.js +150 -0
  59. package/dist/components/crudFiles/CrudViewBase.js +39 -0
  60. package/dist/components/crudFiles/crudDevelopment.js +118 -0
  61. package/dist/components/crudFiles/crudEditHandlers.js +50 -0
  62. package/dist/constants/animation.js +30 -0
  63. package/dist/icons/ArrowIcon.js +32 -0
  64. package/dist/icons/ArrowRight.js +33 -0
  65. package/dist/icons/CheckCircle.js +33 -0
  66. package/dist/icons/ChevronDown.js +28 -0
  67. package/dist/icons/Close.js +33 -0
  68. package/dist/icons/EditSquare.js +33 -0
  69. package/dist/icons/Ellipses.js +34 -0
  70. package/dist/icons/Hamburger.js +39 -0
  71. package/dist/icons/LoadingSpinner.js +42 -0
  72. package/dist/icons/PlusCircle.js +33 -0
  73. package/dist/icons/SaveIcon.js +32 -0
  74. package/dist/icons/TrashX.js +33 -0
  75. package/dist/icons/__tests__/CheckCircle.test.js +9 -0
  76. package/dist/icons/__tests__/ChevronDown.test.js +9 -0
  77. package/dist/icons/__tests__/Close.test.js +9 -0
  78. package/dist/icons/__tests__/EditSquare.test.js +9 -0
  79. package/dist/icons/__tests__/PlusCircle.test.js +9 -0
  80. package/dist/icons/__tests__/TrashX.test.js +9 -0
  81. package/dist/icons/index.js +89 -0
  82. package/dist/index.js +332 -0
  83. package/dist/setupTests.js +3 -0
  84. package/dist/styles/_variables.scss +286 -0
  85. package/dist/styles/anchor.scss +40 -0
  86. package/dist/styles/animation-accessibility.scss +96 -0
  87. package/dist/styles/animation-toggle.scss +233 -0
  88. package/dist/styles/animation.scss +3781 -0
  89. package/dist/styles/avatar.scss +285 -0
  90. package/dist/styles/button.scss +430 -0
  91. package/dist/styles/card.scss +210 -0
  92. package/dist/styles/checkbox.scss +160 -0
  93. package/dist/styles/crud.scss +474 -0
  94. package/dist/styles/dragAndDrop.scss +312 -0
  95. package/dist/styles/error.scss +232 -0
  96. package/dist/styles/footer.scss +58 -0
  97. package/dist/styles/form.scss +420 -0
  98. package/dist/styles/grid.scss +29 -0
  99. package/dist/styles/header.scss +276 -0
  100. package/dist/styles/heading.scss +118 -0
  101. package/dist/styles/hero.scss +185 -0
  102. package/dist/styles/htmlElements.scss +20 -0
  103. package/dist/styles/image.scss +9 -0
  104. package/dist/styles/label.scss +340 -0
  105. package/dist/styles/list-item.scss +5 -0
  106. package/dist/styles/loader.scss +354 -0
  107. package/dist/styles/logo.scss +19 -0
  108. package/dist/styles/main.css +9056 -0
  109. package/dist/styles/main.css.map +1 -0
  110. package/dist/styles/main.scss +0 -0
  111. package/dist/styles/menu-hover.scss +30 -0
  112. package/dist/styles/paragraph.scss +88 -0
  113. package/dist/styles/prompt.scss +51 -0
  114. package/dist/styles/radio.scss +202 -0
  115. package/dist/styles/select.scss +363 -0
  116. package/dist/styles/side-menu.scss +334 -0
  117. package/dist/styles/tabs.scss +540 -0
  118. package/dist/styles/text-area.scss +388 -0
  119. package/dist/styles/text-input.scss +171 -0
  120. package/dist/styles/toggle.scss +0 -0
  121. package/dist/styles/unordered-list.scss +8 -0
  122. package/dist/utils/ScrollHandler.js +30 -0
  123. package/dist/utils/accessibility.js +128 -0
  124. package/dist/utils/heroUtils.js +316 -0
  125. package/dist/utils/index.js +104 -0
  126. package/dist/utils/inputValidation.js +29 -0
  127. package/dist/utils/keyboardNavigation.js +536 -0
  128. package/dist/utils/labelUtils.js +708 -0
  129. package/dist/utils/loaderUtils.js +387 -0
  130. package/dist/utils/menuUtils.js +575 -0
  131. package/dist/utils/useHeadingAccessibility.js +298 -0
  132. package/dist/utils/useRadioGroup.js +260 -0
  133. package/dist/utils/useSelectAccessibility.js +426 -0
  134. package/dist/utils/useTabsAccessibility.js +278 -0
  135. package/dist/utils/useTextAreaAccessibility.js +255 -0
  136. package/dist/utils/useTextInputAccessibility.js +295 -0
  137. package/dist/utils/useTypographyAccessibility.js +168 -0
  138. package/dist/utils/useWindowSize.js +32 -0
  139. package/dist/utils/utils/ScrollHandler.js +26 -0
  140. package/dist/utils/utils/accessibility.js +133 -0
  141. package/dist/utils/utils/heroUtils.js +348 -0
  142. package/dist/utils/utils/index.js +9 -0
  143. package/dist/utils/utils/inputValidation.js +22 -0
  144. package/dist/utils/utils/keyboardNavigation.js +664 -0
  145. package/dist/utils/utils/labelUtils.js +772 -0
  146. package/dist/utils/utils/loaderUtils.js +436 -0
  147. package/dist/utils/utils/menuUtils.js +651 -0
  148. package/dist/utils/utils/useHeadingAccessibility.js +334 -0
  149. package/dist/utils/utils/useRadioGroup.js +311 -0
  150. package/dist/utils/utils/useSelectAccessibility.js +498 -0
  151. package/dist/utils/utils/useTabsAccessibility.js +316 -0
  152. package/dist/utils/utils/useTextAreaAccessibility.js +303 -0
  153. package/dist/utils/utils/useTextInputAccessibility.js +338 -0
  154. package/dist/utils/utils/useTypographyAccessibility.js +180 -0
  155. package/dist/utils/utils/useWindowSize.js +26 -0
  156. package/dist/utils/utils/validation.js +131 -0
  157. package/dist/utils/validation.js +139 -0
  158. package/package.json +90 -0
@@ -0,0 +1,285 @@
1
+ /* Avatar Component Styles */
2
+ /* Accessible and high contrast mode compatible */
3
+
4
+ @use 'variables' as *;
5
+
6
+ .avatar {
7
+ position: relative;
8
+ display: inline-block;
9
+ border-radius: 50%;
10
+ overflow: hidden;
11
+ background-color: $gray-100;
12
+ border: 2px solid transparent;
13
+ transition: all 0.2s ease-in-out;
14
+
15
+ /* Size variants */
16
+ &--xs {
17
+ .avatar__image,
18
+ .avatar__fallback,
19
+ .avatar__loading {
20
+ font-size: 10px;
21
+ }
22
+ }
23
+
24
+ &--sm {
25
+ .avatar__image,
26
+ .avatar__fallback,
27
+ .avatar__loading {
28
+ font-size: 12px;
29
+ }
30
+ }
31
+
32
+ &--md {
33
+ .avatar__image,
34
+ .avatar__fallback,
35
+ .avatar__loading {
36
+ font-size: 16px;
37
+ }
38
+ }
39
+
40
+ &--lg {
41
+ .avatar__image,
42
+ .avatar__fallback,
43
+ .avatar__loading {
44
+ font-size: 20px;
45
+ }
46
+ }
47
+
48
+ &--xl {
49
+ .avatar__image,
50
+ .avatar__fallback,
51
+ .avatar__loading {
52
+ font-size: 28px;
53
+ }
54
+ }
55
+
56
+ /* Clickable state */
57
+ &--clickable {
58
+ cursor: pointer;
59
+ min-height: 44px; /* Touch target size */
60
+ min-width: 44px; /* Touch target size */
61
+
62
+ &:hover {
63
+ transform: translateY(-2px);
64
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
65
+ border-color: $color-primary;
66
+ }
67
+
68
+ &:focus {
69
+ outline: 3px solid $focus-color;
70
+ outline-offset: 2px;
71
+ }
72
+
73
+ &:active {
74
+ transform: translateY(0);
75
+ }
76
+ }
77
+
78
+ /* Hoverable effects */
79
+ &--hoverable {
80
+ &:hover .avatar__hover-overlay {
81
+ opacity: 1;
82
+ }
83
+ }
84
+
85
+ /* Loading state */
86
+ &--loading {
87
+ .avatar__loading {
88
+ background-color: $gray-200;
89
+ }
90
+ }
91
+
92
+ /* Image element */
93
+ &__image {
94
+ width: 100%;
95
+ height: 100%;
96
+ object-fit: cover;
97
+ border-radius: 50%;
98
+ display: block;
99
+ transition: opacity 0.2s ease-in-out;
100
+ }
101
+
102
+ /* Fallback content */
103
+ &__fallback {
104
+ width: 100%;
105
+ height: 100%;
106
+ border-radius: 50%;
107
+ background-color: $gray-600;
108
+ color: $color-white;
109
+ display: flex;
110
+ align-items: center;
111
+ justify-content: center;
112
+ font-weight: 600;
113
+ text-transform: uppercase;
114
+ }
115
+
116
+ &__fallback-text {
117
+ font-size: 1.2em;
118
+ line-height: 1;
119
+ }
120
+
121
+ &__fallback-icon {
122
+ width: 60%;
123
+ height: 60%;
124
+ opacity: 0.8;
125
+ }
126
+
127
+ /* Hover overlay */
128
+ &__hover-overlay {
129
+ position: absolute;
130
+ top: 0;
131
+ left: 0;
132
+ width: 100%;
133
+ height: 100%;
134
+ background-color: rgba(0, 0, 0, 0.6);
135
+ border-radius: 50%;
136
+ opacity: 0;
137
+ transition: opacity 0.2s ease-in-out;
138
+ pointer-events: none;
139
+ display: flex;
140
+ align-items: center;
141
+ justify-content: center;
142
+
143
+ &::before {
144
+ content: '';
145
+ width: 50%;
146
+ height: 50%;
147
+ background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiPjxwYXRoIGQ9Ik0xMiAyQzYuNDggMiAyIDYuNDggMiAxMnM0LjQ4IDEwIDEwIDEwIDEwLTQuNDggMTAtMTBTMTcuNTIgMiAxMiAyem0tMiAxNWwtNS01IDEuNDEtMS40MUwxMCAxNC4xN2w3LjU5LTcuNTlMMTkgOGwtOSA5eiIvPjwvc3ZnPg==');
148
+ background-repeat: no-repeat;
149
+ background-position: center;
150
+ background-size: contain;
151
+ }
152
+ }
153
+
154
+ /* Loading state */
155
+ &__loading {
156
+ width: 100%;
157
+ height: 100%;
158
+ border-radius: 50%;
159
+ display: flex;
160
+ align-items: center;
161
+ justify-content: center;
162
+ background-color: $gray-200;
163
+ }
164
+
165
+ &__loading-spinner {
166
+ position: absolute;
167
+ left: 50%;
168
+ top: 50%;
169
+ transform: translate(-50%, -50%);
170
+ animation: avatar-spin 1s linear infinite;
171
+ color: $color-primary;
172
+
173
+ &__circle {
174
+ stroke: $gray-300;
175
+ }
176
+
177
+ &__path {
178
+ fill: $color-primary;
179
+ }
180
+ }
181
+
182
+ /* Responsive design */
183
+ @media #{$medium} {
184
+ /* Enhanced touch targets for tablets */
185
+ &--clickable {
186
+ min-height: 48px;
187
+ min-width: 48px;
188
+ }
189
+
190
+ /* Improved hover effects on larger screens */
191
+ &--hoverable {
192
+ &:hover .avatar__hover-overlay {
193
+ opacity: 0.8;
194
+ }
195
+ }
196
+ }
197
+
198
+ @media #{$large} {
199
+ /* Desktop optimizations */
200
+ &--clickable {
201
+ &:hover {
202
+ transform: translateY(-3px);
203
+ box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
204
+ }
205
+ }
206
+
207
+ /* Enhanced size variants for desktop */
208
+ &--xl {
209
+ .avatar__image,
210
+ .avatar__fallback,
211
+ .avatar__loading {
212
+ font-size: 32px;
213
+ }
214
+ }
215
+ }
216
+
217
+ @media #{$xlarge} {
218
+ /* Large screen optimizations */
219
+ &--xl {
220
+ .avatar__image,
221
+ .avatar__fallback,
222
+ .avatar__loading {
223
+ font-size: 36px;
224
+ }
225
+ }
226
+
227
+ /* Enhanced interactive effects */
228
+ &--clickable {
229
+ &:hover {
230
+ box-shadow: 0 8px 20px rgba(0, 0, 0, 0.25);
231
+ }
232
+ }
233
+ }
234
+
235
+ /* High contrast mode support */
236
+ @media (prefers-contrast: high) {
237
+ border-color: currentColor;
238
+
239
+ &--clickable:focus {
240
+ outline-color: currentColor;
241
+ outline-width: 3px;
242
+ }
243
+
244
+ .avatar__fallback {
245
+ background-color: currentColor;
246
+ color: $color-white;
247
+ }
248
+ }
249
+
250
+ /* Reduced motion support */
251
+ @media (prefers-reduced-motion: reduce) {
252
+ transition: none;
253
+
254
+ &--clickable:hover {
255
+ transform: none;
256
+ }
257
+
258
+ &__loading-spinner {
259
+ animation: none;
260
+ }
261
+ }
262
+ }
263
+
264
+ /* Screen reader only styles */
265
+ .sr-only {
266
+ position: absolute;
267
+ width: 1px;
268
+ height: 1px;
269
+ padding: 0;
270
+ margin: -1px;
271
+ overflow: hidden;
272
+ clip: rect(0, 0, 0, 0);
273
+ white-space: nowrap;
274
+ border: 0;
275
+ }
276
+
277
+ /* Spinner animation */
278
+ @keyframes avatar-spin {
279
+ 0% {
280
+ transform: rotate(0deg);
281
+ }
282
+ 100% {
283
+ transform: rotate(360deg);
284
+ }
285
+ }
@@ -0,0 +1,430 @@
1
+ @use 'variables' as *;
2
+
3
+ /* BASE STYLES */
4
+
5
+ [role='button'] {
6
+ cursor: pointer;
7
+ }
8
+
9
+ .button {
10
+ margin-bottom: 0;
11
+ font-weight: 500;
12
+ text-align: center;
13
+ vertical-align: middle;
14
+ touch-action: manipulation;
15
+ cursor: pointer;
16
+ background-image: none;
17
+ border: 2px solid transparent;
18
+ white-space: nowrap;
19
+ font-size: 16px;
20
+ line-height: 1.42857143;
21
+ border-radius: $border-radius-md;
22
+ user-select: none;
23
+ overflow: visible;
24
+ text-transform: none;
25
+ display: inline-flex;
26
+ align-items: center;
27
+ justify-content: center;
28
+ gap: 8px;
29
+ min-height: 44px; /* Touch target size */
30
+ min-width: 44px; /* Touch target size */
31
+ padding: 12px 24px;
32
+ position: relative;
33
+ transition: all 0.2s ease-in-out;
34
+ text-decoration: none;
35
+
36
+ &:focus,
37
+ &:active:focus {
38
+ outline: 3px solid $focus-color;
39
+ outline-offset: 2px;
40
+ }
41
+
42
+ &:hover,
43
+ &:focus {
44
+ text-decoration: none;
45
+ transform: translateY(-1px);
46
+ }
47
+
48
+ &:active,
49
+ .active {
50
+ outline: 0;
51
+ background-image: none;
52
+ transform: translateY(0);
53
+ }
54
+
55
+ /* Size variants */
56
+ &--xs {
57
+ font-size: 12px;
58
+ padding: 6px 12px;
59
+ min-height: 32px;
60
+ min-width: 32px;
61
+ border-radius: $border-radius-xs;
62
+ }
63
+
64
+ &--sm {
65
+ font-size: 14px;
66
+ padding: 8px 16px;
67
+ min-height: 36px;
68
+ min-width: 36px;
69
+ border-radius: $border-radius-sm;
70
+ }
71
+
72
+ &--md {
73
+ font-size: 16px;
74
+ padding: 12px 24px;
75
+ min-height: 44px;
76
+ min-width: 44px;
77
+ border-radius: $border-radius-md;
78
+ }
79
+
80
+ &--lg {
81
+ font-size: 18px;
82
+ padding: 16px 32px;
83
+ min-height: 52px;
84
+ min-width: 52px;
85
+ border-radius: $border-radius-lg;
86
+ }
87
+
88
+ &--xl {
89
+ font-size: 20px;
90
+ padding: 20px 40px;
91
+ min-height: 60px;
92
+ min-width: 60px;
93
+ border-radius: $border-radius-xl;
94
+ }
95
+
96
+ /* Full width variant */
97
+ &--full-width {
98
+ width: 100%;
99
+ }
100
+
101
+ /* Loading state */
102
+ &--loading {
103
+ pointer-events: none;
104
+ position: relative;
105
+ color: transparent;
106
+
107
+ .button__loading-text {
108
+ color: currentColor;
109
+ }
110
+ }
111
+
112
+ /* Disabled state */
113
+ &--disabled,
114
+ &[disabled] {
115
+ cursor: not-allowed;
116
+ opacity: 0.6;
117
+ pointer-events: none;
118
+ filter: grayscale(50%);
119
+ transform: none !important;
120
+ }
121
+
122
+ /* Color variants */
123
+ &--primary {
124
+ background-color: $color-primary;
125
+ border-color: $color-primary;
126
+ color: $color-white;
127
+ box-shadow: 0 2px 4px $shadow-primary;
128
+
129
+ &:hover:not(.button--disabled) {
130
+ background-color: $color-primary-hover;
131
+ border-color: $color-primary-hover;
132
+ box-shadow: 0 4px 8px $shadow-primary-hover;
133
+ }
134
+ }
135
+
136
+ &--secondary {
137
+ background-color: $color-secondary;
138
+ border-color: $color-secondary;
139
+ color: $color-white;
140
+ box-shadow: 0 2px 4px $shadow-secondary;
141
+
142
+ &:hover:not(.button--disabled) {
143
+ background-color: $color-secondary-hover;
144
+ border-color: $color-secondary-hover;
145
+ box-shadow: 0 4px 8px $shadow-secondary-hover;
146
+ }
147
+ }
148
+
149
+ &--success {
150
+ background-color: $color-success;
151
+ border-color: $color-success;
152
+ color: $color-black;
153
+ box-shadow: 0 2px 4px $shadow-success;
154
+
155
+ &:hover:not(.button--disabled) {
156
+ background-color: $color-success-hover;
157
+ border-color: $color-success-hover;
158
+ box-shadow: 0 4px 8px $shadow-success-hover;
159
+ }
160
+ }
161
+
162
+ &--error {
163
+ background-color: $color-error;
164
+ border-color: $color-error;
165
+ color: $color-white;
166
+ box-shadow: 0 2px 4px $shadow-error;
167
+
168
+ &:hover:not(.button--disabled) {
169
+ background-color: $color-error-hover;
170
+ border-color: $color-error-hover;
171
+ box-shadow: 0 4px 8px $shadow-error-hover;
172
+ }
173
+ }
174
+
175
+ &--warning {
176
+ background-color: $color-warning;
177
+ border-color: $color-warning;
178
+ color: $color-black;
179
+ box-shadow: 0 2px 4px $shadow-warning;
180
+
181
+ &:hover:not(.button--disabled) {
182
+ background-color: $color-warning-hover;
183
+ border-color: $color-warning-hover;
184
+ box-shadow: 0 4px 8px $shadow-warning-hover;
185
+ }
186
+ }
187
+
188
+ /* Outline variants */
189
+ &--outline {
190
+ background-color: transparent;
191
+ border-width: 2px;
192
+
193
+ &.button--primary {
194
+ color: $color-primary;
195
+ border-color: $color-primary;
196
+
197
+ &:hover:not(.button--disabled) {
198
+ background-color: $color-primary;
199
+ color: $color-white;
200
+ }
201
+ }
202
+
203
+ &.button--secondary {
204
+ color: $color-secondary;
205
+ border-color: $color-secondary;
206
+
207
+ &:hover:not(.button--disabled) {
208
+ background-color: $color-secondary;
209
+ color: $color-white;
210
+ }
211
+ }
212
+
213
+ &.button--success {
214
+ color: $color-success;
215
+ border-color: $color-success;
216
+
217
+ &:hover:not(.button--disabled) {
218
+ background-color: $color-success;
219
+ color: $color-black;
220
+ }
221
+ }
222
+
223
+ &.button--error {
224
+ color: $color-error;
225
+ border-color: $color-error;
226
+
227
+ &:hover:not(.button--disabled) {
228
+ background-color: $color-error;
229
+ color: $color-white;
230
+ }
231
+ }
232
+
233
+ &.button--warning {
234
+ color: $color-warning;
235
+ border-color: $color-warning;
236
+
237
+ &:hover:not(.button--disabled) {
238
+ background-color: $color-warning;
239
+ color: $color-black;
240
+ }
241
+ }
242
+ }
243
+
244
+ /* Icon styling */
245
+ &__icon {
246
+ display: inline-flex;
247
+ align-items: center;
248
+ justify-content: center;
249
+
250
+ &--leading {
251
+ margin-right: 4px;
252
+ }
253
+
254
+ &--trailing {
255
+ margin-left: 4px;
256
+ }
257
+
258
+ svg {
259
+ width: 1em;
260
+ height: 1em;
261
+ fill: currentColor;
262
+ }
263
+ }
264
+
265
+ /* Loading spinner */
266
+ &__loading-spinner {
267
+ position: absolute;
268
+ left: 50%;
269
+ top: 50%;
270
+ transform: translate(-50%, -50%);
271
+ animation: button-spin 1s linear infinite;
272
+
273
+ &__circle {
274
+ opacity: 0.25;
275
+ }
276
+
277
+ &__path {
278
+ opacity: 0.75;
279
+ }
280
+ }
281
+
282
+ /* Text content */
283
+ &__text {
284
+ display: inline-block;
285
+ }
286
+
287
+ &__loading-text {
288
+ opacity: 1;
289
+ }
290
+
291
+ /* Responsive design */
292
+ @media #{$medium} {
293
+ /* Enhanced touch targets for tablets */
294
+ &--xs {
295
+ min-height: 36px;
296
+ min-width: 36px;
297
+ }
298
+ &--sm {
299
+ min-height: 40px;
300
+ min-width: 40px;
301
+ }
302
+ &--md {
303
+ min-height: 48px;
304
+ min-width: 48px;
305
+ }
306
+ &--lg {
307
+ min-height: 56px;
308
+ min-width: 56px;
309
+ }
310
+ &--xl {
311
+ min-height: 64px;
312
+ min-width: 64px;
313
+ }
314
+
315
+ /* Enhanced hover effects */
316
+ &:hover:not(.button--disabled) {
317
+ transform: translateY(-2px);
318
+ }
319
+ }
320
+
321
+ @media #{$large} {
322
+ /* Desktop optimizations */
323
+ &:hover:not(.button--disabled) {
324
+ transform: translateY(-3px);
325
+
326
+ &.button--primary {
327
+ box-shadow: 0 6px 12px $shadow-primary-strong;
328
+ }
329
+ &.button--secondary {
330
+ box-shadow: 0 6px 12px $shadow-secondary-strong;
331
+ }
332
+ &.button--success {
333
+ box-shadow: 0 6px 12px $shadow-success-strong;
334
+ }
335
+ &.button--error {
336
+ box-shadow: 0 6px 12px $shadow-error-strong;
337
+ }
338
+ &.button--warning {
339
+ box-shadow: 0 6px 12px $shadow-warning-strong;
340
+ }
341
+ }
342
+
343
+ /* Larger font sizes for desktop */
344
+ &--lg {
345
+ font-size: 20px;
346
+ }
347
+ &--xl {
348
+ font-size: 24px;
349
+ }
350
+ }
351
+
352
+ @media #{$xlarge} {
353
+ /* Large screen optimizations */
354
+ &--xl {
355
+ font-size: 28px;
356
+ padding: 24px 48px;
357
+ min-height: 72px;
358
+ min-width: 72px;
359
+ }
360
+
361
+ /* Premium shadow effects */
362
+ &:hover:not(.button--disabled) {
363
+ &.button--primary {
364
+ box-shadow: 0 8px 16px $shadow-primary-strongest;
365
+ }
366
+ &.button--secondary {
367
+ box-shadow: 0 8px 16px $shadow-secondary-strongest;
368
+ }
369
+ &.button--success {
370
+ box-shadow: 0 8px 16px $shadow-success-strongest;
371
+ }
372
+ &.button--error {
373
+ box-shadow: 0 8px 16px $shadow-error-strongest;
374
+ }
375
+ &.button--warning {
376
+ box-shadow: 0 8px 16px $shadow-warning-strongest;
377
+ }
378
+ }
379
+ }
380
+
381
+ /* High contrast mode support */
382
+ @media (prefers-contrast: high) {
383
+ border-width: 3px;
384
+
385
+ &:focus {
386
+ outline-color: $focus-color;
387
+ outline-width: 4px;
388
+ }
389
+
390
+ &--outline {
391
+ border-width: 3px;
392
+ }
393
+ }
394
+
395
+ /* Reduced motion support */
396
+ @media (prefers-reduced-motion: reduce) {
397
+ transition: none;
398
+
399
+ &:hover {
400
+ transform: none;
401
+ }
402
+
403
+ .button__loading-spinner {
404
+ animation: none;
405
+ }
406
+ }
407
+ }
408
+
409
+ /* Screen reader only styles */
410
+ .sr-only {
411
+ position: absolute;
412
+ width: 1px;
413
+ height: 1px;
414
+ padding: 0;
415
+ margin: -1px;
416
+ overflow: hidden;
417
+ clip: rect(0, 0, 0, 0);
418
+ white-space: nowrap;
419
+ border: 0;
420
+ }
421
+
422
+ /* Spinner animation */
423
+ @keyframes button-spin {
424
+ 0% {
425
+ transform: translate(-50%, -50%) rotate(0deg);
426
+ }
427
+ 100% {
428
+ transform: translate(-50%, -50%) rotate(360deg);
429
+ }
430
+ }