@necrolab/dashboard 0.5.15 → 0.5.17
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/backend/api.js +2 -3
- package/eslint.config.js +46 -0
- package/index.html +2 -1
- package/package.json +5 -2
- package/src/App.vue +70 -566
- package/src/assets/css/base/mixins.scss +72 -0
- package/src/assets/css/base/reset.scss +0 -2
- package/src/assets/css/base/scroll.scss +43 -36
- package/src/assets/css/base/typography.scss +9 -10
- package/src/assets/css/base/variables.scss +43 -0
- package/src/assets/css/components/accessibility.scss +37 -0
- package/src/assets/css/components/buttons.scss +61 -74
- package/src/assets/css/components/forms.scss +31 -32
- package/src/assets/css/components/headers.scss +13 -21
- package/src/assets/css/components/modals.scss +2 -2
- package/src/assets/css/components/search-groups.scss +28 -22
- package/src/assets/css/components/tables.scss +5 -7
- package/src/assets/css/components/toasts.scss +7 -7
- package/src/assets/css/components/utilities.scss +295 -0
- package/src/assets/css/main.scss +55 -139
- package/src/components/Auth/LoginForm.vue +7 -86
- package/src/components/Console/ConsoleToolbar.vue +123 -0
- package/src/components/Editors/Account/Account.vue +12 -12
- package/src/components/Editors/Account/AccountView.vue +38 -111
- package/src/components/Editors/Account/CreateAccount.vue +11 -61
- package/src/components/Editors/Account/{AccountCreator.vue → CreateAccountBatch.vue} +28 -59
- package/src/components/Editors/AdminFileEditor.vue +179 -0
- package/src/components/Editors/Profile/CreateProfile.vue +77 -150
- package/src/components/Editors/Profile/Profile.vue +20 -21
- package/src/components/Editors/Profile/ProfileCountryChooser.vue +16 -60
- package/src/components/Editors/Profile/ProfileView.vue +41 -116
- package/src/components/Editors/ProxyFileEditor.vue +86 -0
- package/src/components/Editors/TagLabel.vue +16 -55
- package/src/components/Editors/TagToggle.vue +20 -8
- package/src/components/Filter/Filter.vue +66 -79
- package/src/components/Filter/FilterPreview.vue +153 -135
- package/src/components/Filter/PriceSortToggle.vue +36 -43
- package/src/components/Table/Header.vue +1 -1
- package/src/components/Table/Table.vue +45 -51
- package/src/components/Tasks/CheckStock.vue +7 -16
- package/src/components/Tasks/Controls/DesktopControls.vue +15 -60
- package/src/components/Tasks/Controls/MobileControls.vue +5 -20
- package/src/components/Tasks/CreateTaskAXS.vue +20 -118
- package/src/components/Tasks/CreateTaskTM.vue +33 -189
- package/src/components/Tasks/EventDetailRow.vue +21 -0
- package/src/components/Tasks/MassEdit.vue +6 -16
- package/src/components/Tasks/QuickSettings.vue +140 -216
- package/src/components/Tasks/ScrapeVenue.vue +4 -13
- package/src/components/Tasks/Stats.vue +20 -39
- package/src/components/Tasks/Task.vue +64 -270
- package/src/components/Tasks/TaskLabel.vue +9 -3
- package/src/components/Tasks/TaskView.vue +45 -64
- package/src/components/Tasks/Utilities.vue +10 -44
- package/src/components/Tasks/ViewTask.vue +23 -107
- package/src/components/icons/Close.vue +2 -8
- package/src/components/icons/Gear.vue +8 -8
- package/src/components/icons/Hash.vue +5 -0
- package/src/components/icons/Key.vue +2 -8
- package/src/components/icons/Pencil.vue +2 -8
- package/src/components/icons/Profile.vue +2 -8
- package/src/components/icons/Sell.vue +2 -8
- package/src/components/icons/Spinner.vue +4 -7
- package/src/components/icons/Wildcard.vue +2 -8
- package/src/components/icons/index.js +3 -5
- package/src/components/ui/ActionButtonGroup.vue +113 -52
- package/src/components/ui/BalanceIndicator.vue +60 -0
- package/src/components/ui/EmptyState.vue +24 -0
- package/src/components/ui/EnableDisableToggle.vue +23 -0
- package/src/components/ui/FormField.vue +49 -49
- package/src/components/ui/IconLabel.vue +23 -0
- package/src/components/ui/InfoRow.vue +21 -54
- package/src/components/ui/Modal.vue +161 -54
- package/src/components/ui/Navbar.vue +63 -44
- package/src/components/ui/ReadonlyFieldsSection.vue +31 -0
- package/src/components/ui/ReconnectIndicator.vue +111 -124
- package/src/components/ui/SectionCard.vue +6 -14
- package/src/components/ui/Splash.vue +2 -10
- package/src/components/ui/StatusBadge.vue +26 -28
- package/src/components/ui/TaskToggle.vue +54 -0
- package/src/components/ui/controls/CountryChooser.vue +29 -66
- package/src/components/ui/controls/EyeToggle.vue +1 -1
- package/src/components/ui/controls/atomic/Checkbox.vue +40 -121
- package/src/components/ui/controls/atomic/Dropdown.vue +103 -139
- package/src/components/ui/controls/atomic/MultiDropdown.vue +72 -120
- package/src/components/ui/controls/atomic/Switch.vue +21 -84
- package/src/composables/useCodeEditor.js +117 -0
- package/src/composables/useColorMapping.js +15 -0
- package/src/composables/useCopyToClipboard.js +1 -1
- package/src/composables/useDateFormatting.js +21 -0
- package/src/composables/useDeviceDetection.js +14 -0
- package/src/composables/useDropdownPosition.js +1 -4
- package/src/composables/useDynamicTableHeight.js +31 -0
- package/src/composables/useEnableDisable.js +6 -0
- package/src/composables/useFilterCSS.js +71 -0
- package/src/composables/useFormValidation.js +92 -0
- package/src/composables/useGetAllTags.js +9 -0
- package/src/composables/useIOSViewportHandling.js +76 -0
- package/src/composables/useNotchHandling.js +306 -0
- package/src/composables/useRowSelection.js +0 -3
- package/src/composables/useTableRender.js +23 -0
- package/src/composables/useTicketPricing.js +16 -0
- package/src/composables/useWindowDimensions.js +21 -0
- package/src/composables/useZoomPrevention.js +96 -0
- package/src/constants/tableLayout.js +14 -0
- package/src/libs/Filter.js +14 -20
- package/src/libs/panzoom.js +1 -5
- package/src/libs/utils/array.js +58 -0
- package/src/{stores/utils.js → libs/utils/dataGeneration.js} +2 -250
- package/src/libs/utils/eventUrl.js +40 -0
- package/src/libs/utils/string.js +3 -0
- package/src/libs/utils/time.js +20 -0
- package/src/libs/utils/validation.js +64 -0
- package/src/main.js +0 -2
- package/src/stores/connection.js +1 -29
- package/src/stores/logger.js +6 -12
- package/src/stores/sampleData.js +1 -2
- package/src/stores/ui.js +80 -71
- package/src/utils/tableHelpers.js +1 -0
- package/src/views/Accounts.vue +19 -38
- package/src/views/Console.vue +74 -253
- package/src/views/Editor.vue +47 -1114
- package/src/views/FilterBuilder.vue +190 -461
- package/src/views/Login.vue +3 -28
- package/src/views/Profiles.vue +17 -32
- package/src/views/Tasks.vue +51 -38
- package/tailwind.config.js +82 -71
- package/workbox-config.cjs +47 -5
- package/docs/plans/2026-02-08-tailwind-consolidation.md +0 -2438
- package/exit +0 -209
- package/run +0 -177
- package/src/assets/css/base/color-fallbacks.scss +0 -10
- package/src/assets/img/background.svg.backup +0 -11
- package/src/components/icons/SquareCheck.vue +0 -18
- package/src/components/icons/SquareUncheck.vue +0 -18
- package/src/components/ui/controls/atomic/LoadingButton.vue +0 -45
- package/switch-branch.sh +0 -41
- /package/public/{reconnect-logo.png → img/reconnect-logo.png} +0 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/* ==========================================================================
|
|
2
|
+
MIXINS - Reusable SCSS patterns
|
|
3
|
+
========================================================================== */
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Scale hover effect - subtle zoom on hover/active
|
|
7
|
+
* Used across buttons and interactive elements
|
|
8
|
+
*/
|
|
9
|
+
@mixin scale-hover {
|
|
10
|
+
&:hover {
|
|
11
|
+
transform: scale(1.03);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
&:active {
|
|
15
|
+
transform: scale(0.98);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Scale hover for elements with disabled state
|
|
21
|
+
* Only applies transform when not disabled
|
|
22
|
+
*/
|
|
23
|
+
@mixin scale-hover-safe {
|
|
24
|
+
&:hover:not(:disabled) {
|
|
25
|
+
transform: scale(1.03);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
&:active:not(:disabled) {
|
|
29
|
+
transform: scale(0.98);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Focus ring with accent green color
|
|
35
|
+
* Replaces repeated outline pattern across components
|
|
36
|
+
*/
|
|
37
|
+
@mixin focus-ring-accent {
|
|
38
|
+
@apply outline outline-1 outline-accent-green outline-offset-0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* User select control with vendor prefixes
|
|
43
|
+
* @param {string} $value - none, text, auto, all
|
|
44
|
+
*/
|
|
45
|
+
@mixin user-select($value) {
|
|
46
|
+
-webkit-user-select: $value;
|
|
47
|
+
-moz-user-select: $value;
|
|
48
|
+
-ms-user-select: $value;
|
|
49
|
+
user-select: $value;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Touch scroll reset for dropdowns and scrollable areas
|
|
54
|
+
* Enables smooth touch scrolling on mobile devices
|
|
55
|
+
*/
|
|
56
|
+
@mixin touch-scroll-reset {
|
|
57
|
+
overscroll-behavior: auto !important;
|
|
58
|
+
touch-action: pan-y !important;
|
|
59
|
+
-webkit-overflow-scrolling: touch !important;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Dark button base styling
|
|
64
|
+
* Common pattern for action buttons and modal controls
|
|
65
|
+
*/
|
|
66
|
+
@mixin dark-button-base {
|
|
67
|
+
@apply bg-dark-400 border border-dark-650 text-white;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@mixin transition-standard {
|
|
71
|
+
@apply transition-all duration-150;
|
|
72
|
+
}
|
|
@@ -17,7 +17,6 @@ button {
|
|
|
17
17
|
-webkit-tap-highlight-color: transparent;
|
|
18
18
|
-webkit-touch-callout: none;
|
|
19
19
|
outline: none;
|
|
20
|
-
/* Prevent zoom on input focus (mobile) */
|
|
21
20
|
font-size: 16px;
|
|
22
21
|
}
|
|
23
22
|
|
|
@@ -37,7 +36,6 @@ select:focus {
|
|
|
37
36
|
box-shadow: none !important;
|
|
38
37
|
}
|
|
39
38
|
|
|
40
|
-
/* Remove number input spinners */
|
|
41
39
|
input[type="number"] {
|
|
42
40
|
-moz-appearance: textfield;
|
|
43
41
|
}
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
SCROLL BEHAVIOR & TOUCH HANDLING
|
|
3
3
|
========================================================================== */
|
|
4
4
|
|
|
5
|
+
@use "mixins" as *;
|
|
6
|
+
|
|
5
7
|
html {
|
|
6
8
|
overflow: hidden !important;
|
|
7
9
|
overscroll-behavior: none !important;
|
|
8
10
|
height: 100% !important;
|
|
9
11
|
width: 100% !important;
|
|
10
|
-
/* Additional zoom prevention at CSS level */
|
|
11
12
|
-webkit-text-size-adjust: 100%;
|
|
12
13
|
-moz-text-size-adjust: 100%;
|
|
13
14
|
-ms-text-size-adjust: 100%;
|
|
@@ -16,22 +17,15 @@ html {
|
|
|
16
17
|
|
|
17
18
|
* {
|
|
18
19
|
@apply hidden-scrollbars;
|
|
19
|
-
|
|
20
|
-
-moz-user-select: none;
|
|
21
|
-
-ms-user-select: none;
|
|
22
|
-
user-select: none;
|
|
20
|
+
@include user-select(none);
|
|
23
21
|
overscroll-behavior: none !important;
|
|
24
22
|
}
|
|
25
23
|
|
|
26
24
|
textarea,
|
|
27
25
|
.code-editor,
|
|
28
26
|
.proxy-editor {
|
|
29
|
-
|
|
30
|
-
-
|
|
31
|
-
-ms-user-select: text !important;
|
|
32
|
-
user-select: text !important;
|
|
33
|
-
overscroll-behavior: auto !important;
|
|
34
|
-
touch-action: pan-y !important;
|
|
27
|
+
@include user-select(text);
|
|
28
|
+
@include touch-scroll-reset;
|
|
35
29
|
}
|
|
36
30
|
|
|
37
31
|
.dropdown-menu,
|
|
@@ -42,60 +36,42 @@ textarea,
|
|
|
42
36
|
.option-list *,
|
|
43
37
|
.console,
|
|
44
38
|
.console * {
|
|
45
|
-
|
|
46
|
-
touch-action: pan-y !important;
|
|
47
|
-
-webkit-overflow-scrolling: touch !important;
|
|
39
|
+
@include touch-scroll-reset;
|
|
48
40
|
}
|
|
49
41
|
|
|
50
|
-
/* Specific overrides for dropdown content portals */
|
|
51
42
|
.dropdown-content-portal {
|
|
52
43
|
overflow: auto !important;
|
|
53
44
|
overflow-y: auto !important;
|
|
54
|
-
|
|
55
|
-
touch-action: pan-y !important;
|
|
56
|
-
-webkit-overflow-scrolling: touch !important;
|
|
45
|
+
@include touch-scroll-reset;
|
|
57
46
|
scroll-behavior: smooth !important;
|
|
58
47
|
}
|
|
59
48
|
|
|
60
49
|
.dropdown-content-portal * {
|
|
61
50
|
overflow: auto !important;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
-webkit-overflow-scrolling: touch !important;
|
|
65
|
-
user-select: auto !important;
|
|
66
|
-
-webkit-user-select: auto !important;
|
|
67
|
-
-moz-user-select: auto !important;
|
|
68
|
-
-ms-user-select: auto !important;
|
|
51
|
+
@include touch-scroll-reset;
|
|
52
|
+
@include user-select(auto);
|
|
69
53
|
}
|
|
70
54
|
|
|
71
|
-
/* Ultra-specific overrides to beat the global * selector */
|
|
72
55
|
body .dropdown-content-portal,
|
|
73
56
|
html .dropdown-content-portal,
|
|
74
57
|
div .dropdown-content-portal {
|
|
75
58
|
overflow: auto !important;
|
|
76
59
|
overflow-y: auto !important;
|
|
77
|
-
|
|
78
|
-
touch-action: pan-y !important;
|
|
79
|
-
-webkit-overflow-scrolling: touch !important;
|
|
60
|
+
@include touch-scroll-reset;
|
|
80
61
|
}
|
|
81
62
|
|
|
82
|
-
/* Force scrolling on teleported dropdown content */
|
|
83
63
|
body > .dropdown-content-portal,
|
|
84
64
|
[data-v-app] .dropdown-content-portal {
|
|
85
65
|
overflow: auto !important;
|
|
86
66
|
overflow-y: auto !important;
|
|
87
|
-
|
|
88
|
-
touch-action: pan-y !important;
|
|
89
|
-
-webkit-overflow-scrolling: touch !important;
|
|
67
|
+
@include touch-scroll-reset;
|
|
90
68
|
}
|
|
91
69
|
|
|
92
70
|
.code-editor,
|
|
93
71
|
.proxy-editor,
|
|
94
72
|
.editor-container,
|
|
95
73
|
.proxy-editor-container {
|
|
96
|
-
|
|
97
|
-
touch-action: pan-y !important;
|
|
98
|
-
-webkit-overflow-scrolling: touch !important;
|
|
74
|
+
@include touch-scroll-reset;
|
|
99
75
|
}
|
|
100
76
|
|
|
101
77
|
/* ==========================================================================
|
|
@@ -117,3 +93,34 @@ body > .dropdown-content-portal,
|
|
|
117
93
|
touch-action: auto !important;
|
|
118
94
|
overscroll-behavior: auto !important;
|
|
119
95
|
}
|
|
96
|
+
|
|
97
|
+
/* ==========================================================================
|
|
98
|
+
CUSTOM SCROLLBAR CLASSES - DRY Principle
|
|
99
|
+
Base properties for smooth scrolling with hidden scrollbars
|
|
100
|
+
========================================================================== */
|
|
101
|
+
|
|
102
|
+
.custom-scrollbar {
|
|
103
|
+
overscroll-behavior: contain;
|
|
104
|
+
-webkit-overflow-scrolling: touch;
|
|
105
|
+
scrollbar-width: none;
|
|
106
|
+
-ms-overflow-style: none;
|
|
107
|
+
|
|
108
|
+
&::-webkit-scrollbar {
|
|
109
|
+
display: none;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.custom-scrollbar-y {
|
|
114
|
+
@extend .custom-scrollbar;
|
|
115
|
+
touch-action: pan-y;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.custom-scrollbar-x {
|
|
119
|
+
@extend .custom-scrollbar;
|
|
120
|
+
touch-action: pan-x;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.custom-scrollbar-xy {
|
|
124
|
+
@extend .custom-scrollbar;
|
|
125
|
+
touch-action: pan-x pan-y;
|
|
126
|
+
}
|
|
@@ -13,16 +13,15 @@ body {
|
|
|
13
13
|
height: 100%;
|
|
14
14
|
--toastify-toast-width: 520px;
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
--bg-
|
|
18
|
-
--bg-
|
|
19
|
-
--bg-
|
|
20
|
-
--
|
|
21
|
-
--
|
|
22
|
-
--
|
|
23
|
-
--text-
|
|
24
|
-
--text-
|
|
25
|
-
--text-muted: oklch(0.55 0 0);
|
|
16
|
+
--bg-base: var(--color-bg-base);
|
|
17
|
+
--bg-elevated: var(--color-bg-card);
|
|
18
|
+
--bg-input: var(--color-bg-input);
|
|
19
|
+
--bg-hover: var(--color-border);
|
|
20
|
+
--accent-green: var(--color-primary);
|
|
21
|
+
--border-base: var(--color-border);
|
|
22
|
+
--text-primary: var(--color-text-primary);
|
|
23
|
+
--text-secondary: var(--color-text-secondary);
|
|
24
|
+
--text-muted: var(--color-text-muted);
|
|
26
25
|
}
|
|
27
26
|
|
|
28
27
|
.editor-base {
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/* ==========================================================================
|
|
2
|
+
CSS VARIABLES
|
|
3
|
+
Shared color tokens to reduce duplication across SCSS files
|
|
4
|
+
========================================================================== */
|
|
5
|
+
|
|
6
|
+
:root {
|
|
7
|
+
// Color scheme
|
|
8
|
+
color-scheme: dark;
|
|
9
|
+
|
|
10
|
+
// Most common colors (for use in SCSS files)
|
|
11
|
+
--color-primary: oklch(0.72 0.15 145); // accent green - appears 60+ times
|
|
12
|
+
--color-border: oklch(0.26 0 0); // default border - appears 16+ times
|
|
13
|
+
--color-bg-base: oklch(0.1822 0 0); // dark-300 base background
|
|
14
|
+
--color-bg-card: oklch(0.2046 0 0); // dark-400 card backgrounds
|
|
15
|
+
--color-bg-input: oklch(0.2603 0 0); // dark-500 input backgrounds
|
|
16
|
+
--color-text-primary: oklch(0.9 0 0); // primary white text
|
|
17
|
+
--color-bg-darker: oklch(0.19 0 0); // appears 11× (dark-350)
|
|
18
|
+
--color-border-light: oklch(0.28 0 0); // appears 12× (dark-550)
|
|
19
|
+
--color-text-muted: oklch(0.65 0 0); // appears 7× (light-500)
|
|
20
|
+
--color-disabled: oklch(0.60 0.20 25); // appears 5× (disabled orange)
|
|
21
|
+
--color-text-secondary: oklch(0.82 0 0); // secondary text - light-400
|
|
22
|
+
--color-text-bright: oklch(0.85 0 0); // bright icon color
|
|
23
|
+
--color-text-dim: oklch(0.70 0 0); // dimmed text
|
|
24
|
+
--color-text-vivid: oklch(0.95 0 0); // very bright text
|
|
25
|
+
--color-text-almost-white: oklch(0.98 0 0); // almost white text
|
|
26
|
+
--color-bg-darker-alt: oklch(0.20 0 0); // slightly lighter than dark-350
|
|
27
|
+
--color-bg-modal: oklch(0.15 0 0); // modal/dropdown backgrounds
|
|
28
|
+
|
|
29
|
+
// Gradient colors
|
|
30
|
+
--color-gradient-start: oklch(0.22 0 0); // header card gradient start
|
|
31
|
+
--color-gradient-mid: oklch(0.23 0 0); // button hover gradient
|
|
32
|
+
--color-gradient-end: oklch(0.24 0 0); // header card gradient end
|
|
33
|
+
--color-gradient-blue-tint: oklch(0.19 0.02 264); // button active state blue tint
|
|
34
|
+
|
|
35
|
+
// Z-index scale (matches tailwind.config.js)
|
|
36
|
+
// dropdown: 100, dropdown-high: 200, tooltip: 2000, modal: 1000, modal-mask: 25000, max: 9999
|
|
37
|
+
--z-dropdown: 100;
|
|
38
|
+
--z-dropdown-high: 200;
|
|
39
|
+
--z-tooltip: 2000;
|
|
40
|
+
--z-modal: 1000;
|
|
41
|
+
--z-modal-mask: 25000;
|
|
42
|
+
--z-max: 9999;
|
|
43
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/* ==========================================================================
|
|
2
|
+
ACCESSIBILITY - Focus Visible & Keyboard Navigation
|
|
3
|
+
========================================================================== */
|
|
4
|
+
|
|
5
|
+
/* Global focus-visible styles for keyboard navigation */
|
|
6
|
+
*:focus-visible {
|
|
7
|
+
@apply outline outline-2 outline-primary outline-offset-2;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/* Remove default focus outline for mouse users */
|
|
11
|
+
*:focus:not(:focus-visible) {
|
|
12
|
+
outline: none;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/* Input-like elements need inline outline (offset-0) */
|
|
16
|
+
input:focus-visible,
|
|
17
|
+
textarea:focus-visible,
|
|
18
|
+
select:focus-visible,
|
|
19
|
+
.dropdown:focus-visible {
|
|
20
|
+
@apply border-primary outline outline-1 outline-primary;
|
|
21
|
+
outline-offset: 0;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* Modal content focus trap */
|
|
25
|
+
[role="dialog"]:focus {
|
|
26
|
+
outline: none;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* Skip to main content link (for screen readers) */
|
|
30
|
+
.skip-to-main {
|
|
31
|
+
@apply absolute -top-full left-0 bg-primary text-white px-4 py-2 rounded z-max;
|
|
32
|
+
transition: top 0.2s;
|
|
33
|
+
|
|
34
|
+
&:focus {
|
|
35
|
+
@apply top-0;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
BUTTON COMPONENTS - Shadcn-Inspired Design
|
|
3
3
|
========================================================================== */
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
@use "../base/mixins" as *;
|
|
6
|
+
|
|
6
7
|
.btn-primary {
|
|
7
|
-
@apply font-medium
|
|
8
|
-
@
|
|
9
|
-
@apply px-4 py-2 rounded-md;
|
|
10
|
-
@apply shadow-sm border-2 border-accent-green;
|
|
8
|
+
@apply font-medium bg-accent-green text-white px-4 py-2 rounded-md shadow-sm border-2 border-accent-green;
|
|
9
|
+
@include transition-standard;
|
|
11
10
|
|
|
12
11
|
&:hover {
|
|
13
12
|
@apply bg-green-400 border-green-400;
|
|
@@ -15,66 +14,14 @@
|
|
|
15
14
|
|
|
16
15
|
&:active {
|
|
17
16
|
@apply bg-green-500 border-accent-green;
|
|
18
|
-
@
|
|
17
|
+
@include focus-ring-accent;
|
|
19
18
|
}
|
|
20
19
|
}
|
|
21
20
|
|
|
22
|
-
/* Secondary Button - Transparent with green border, fills on hover */
|
|
23
|
-
.btn-secondary {
|
|
24
|
-
@apply font-medium transition-all duration-150;
|
|
25
|
-
@apply bg-transparent text-accent-green;
|
|
26
|
-
@apply px-4 py-2 rounded-md;
|
|
27
|
-
@apply border-2 border-accent-green;
|
|
28
21
|
|
|
29
|
-
&:hover {
|
|
30
|
-
@apply bg-accent-green text-white border-accent-green;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
&:active {
|
|
34
|
-
@apply bg-green-400 border-accent-green;
|
|
35
|
-
@apply outline outline-1 outline-accent-green outline-offset-0;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/* Ghost Button - No border, muted text, subtle hover */
|
|
40
|
-
.btn-ghost {
|
|
41
|
-
@apply font-medium transition-all duration-150;
|
|
42
|
-
@apply bg-transparent text-light-400;
|
|
43
|
-
@apply px-4 py-2 rounded-md;
|
|
44
|
-
@apply border-none;
|
|
45
|
-
|
|
46
|
-
&:hover {
|
|
47
|
-
@apply bg-dark-450 text-light-300;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
&:active {
|
|
51
|
-
@apply bg-dark-350;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/* Destructive Button - Red with clean shadow */
|
|
56
|
-
.btn-danger,
|
|
57
|
-
.btn-destructive {
|
|
58
|
-
@apply font-medium transition-all duration-150;
|
|
59
|
-
@apply bg-error-500 text-white;
|
|
60
|
-
@apply px-4 py-2 rounded-md;
|
|
61
|
-
@apply shadow-sm border-none;
|
|
62
|
-
|
|
63
|
-
&:hover {
|
|
64
|
-
@apply bg-error-400;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
&:active {
|
|
68
|
-
@apply bg-red-500;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/* Icon Button - Clean hover states */
|
|
73
22
|
.btn-icon {
|
|
74
|
-
@apply flex items-center justify-center
|
|
75
|
-
@
|
|
76
|
-
@apply bg-transparent text-light-400;
|
|
77
|
-
@apply border-none;
|
|
23
|
+
@apply flex items-center justify-center p-1 rounded-md bg-transparent text-light-400 border-none;
|
|
24
|
+
@include transition-standard;
|
|
78
25
|
|
|
79
26
|
&:hover {
|
|
80
27
|
@apply bg-dark-450 text-white;
|
|
@@ -85,13 +32,9 @@
|
|
|
85
32
|
}
|
|
86
33
|
}
|
|
87
34
|
|
|
88
|
-
/* Action Button - Similar to secondary but with specific sizing */
|
|
89
35
|
.btn-action {
|
|
90
|
-
@apply font-medium flex items-center justify-center gap-x-2
|
|
91
|
-
@
|
|
92
|
-
@apply px-4 h-10 rounded-md;
|
|
93
|
-
@apply border-2 border-accent-green;
|
|
94
|
-
@apply text-xs;
|
|
36
|
+
@apply font-medium flex items-center justify-center gap-x-2 bg-transparent text-accent-green px-4 h-10 rounded-md border-2 border-accent-green text-xs;
|
|
37
|
+
@include transition-standard;
|
|
95
38
|
|
|
96
39
|
&:hover {
|
|
97
40
|
@apply bg-accent-green text-white border-accent-green;
|
|
@@ -99,20 +42,19 @@
|
|
|
99
42
|
|
|
100
43
|
&:active {
|
|
101
44
|
@apply bg-green-400 border-accent-green;
|
|
102
|
-
@
|
|
45
|
+
@include focus-ring-accent;
|
|
103
46
|
}
|
|
104
47
|
}
|
|
105
48
|
|
|
106
|
-
/* Default Button - Base styling */
|
|
107
49
|
.button-default {
|
|
108
|
-
@apply font-medium
|
|
109
|
-
@
|
|
50
|
+
@apply font-medium flex items-center justify-center gap-x-2 h-14 rounded-lg text-white border-2 border-dark-550 text-sm px-6 w-48;
|
|
51
|
+
@include transition-standard;
|
|
110
52
|
|
|
111
53
|
svg {
|
|
112
54
|
@apply w-4 h-4 flex-shrink-0;
|
|
113
55
|
}
|
|
114
56
|
|
|
115
|
-
@
|
|
57
|
+
@screen md {
|
|
116
58
|
@apply h-12 text-sm font-medium w-full max-w-full;
|
|
117
59
|
|
|
118
60
|
svg {
|
|
@@ -120,8 +62,8 @@
|
|
|
120
62
|
}
|
|
121
63
|
}
|
|
122
64
|
|
|
123
|
-
@
|
|
124
|
-
@apply h-
|
|
65
|
+
@screen mobile-portrait {
|
|
66
|
+
@apply h-13;
|
|
125
67
|
|
|
126
68
|
svg {
|
|
127
69
|
@apply w-4 h-4;
|
|
@@ -134,7 +76,40 @@
|
|
|
134
76
|
|
|
135
77
|
&:active, &:focus {
|
|
136
78
|
@apply border-accent-green;
|
|
137
|
-
@
|
|
79
|
+
@include focus-ring-accent;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.btn-focus-ring {
|
|
84
|
+
&:active {
|
|
85
|
+
@apply border-accent-green;
|
|
86
|
+
@include focus-ring-accent;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
&:focus {
|
|
90
|
+
@apply border-accent-green;
|
|
91
|
+
@include focus-ring-accent;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.login-btn {
|
|
96
|
+
@apply flex items-center justify-center gap-2 h-12 rounded-lg font-semibold tracking-wider uppercase bg-accent-green border-2 border-accent-green text-white;
|
|
97
|
+
@include transition-standard;
|
|
98
|
+
font-size: theme('fontSize.base-');
|
|
99
|
+
|
|
100
|
+
&:hover:enabled {
|
|
101
|
+
@apply bg-green-500 border-green-500;
|
|
102
|
+
transform: translateY(-1px);
|
|
103
|
+
box-shadow: 0 4px 12px rgb(from theme('colors.accent.green') r g b / 0.3);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
&:active:enabled {
|
|
107
|
+
transform: translateY(0);
|
|
108
|
+
box-shadow: 0 2px 4px rgb(from theme('colors.accent.green') r g b / 0.2);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
&:disabled {
|
|
112
|
+
@apply opacity-70 cursor-not-allowed;
|
|
138
113
|
}
|
|
139
114
|
}
|
|
140
115
|
|
|
@@ -162,3 +137,15 @@
|
|
|
162
137
|
border-radius: 8px;
|
|
163
138
|
}
|
|
164
139
|
}
|
|
140
|
+
|
|
141
|
+
/* ==========================================================================
|
|
142
|
+
MODAL/ACTION BUTTON UTILITIES
|
|
143
|
+
========================================================================== */
|
|
144
|
+
|
|
145
|
+
.btn-modal {
|
|
146
|
+
@apply h-10 rounded-md text-xs flex items-center justify-center font-medium px-4 hover:border-dark-700 btn-focus-ring;
|
|
147
|
+
@include transition-standard;
|
|
148
|
+
@include dark-button-base;
|
|
149
|
+
@include scale-hover;
|
|
150
|
+
}
|
|
151
|
+
|