@keenmate/pure-admin-core 1.1.3 → 1.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.
@@ -0,0 +1,335 @@
1
+ /* ========================================
2
+ Detail Panel Components
3
+ Inline split-view and overlay detail panels
4
+ ======================================== */
5
+ @use '../variables' as *;
6
+
7
+ // Local CSS variables for detail panel (runtime state, modified by JS for resize)
8
+ :root {
9
+ --pa-local-detail-panel-width: #{$detail-panel-width};
10
+ --pa-local-detail-panel-max-width: #{$detail-panel-max-width};
11
+ }
12
+
13
+ // Detail panel content width - :where() for low specificity (utility classes can override)
14
+ :where(.pa-detail-view__panel) {
15
+ width: var(--pa-local-detail-panel-width);
16
+ max-width: var(--pa-local-detail-panel-max-width);
17
+ }
18
+
19
+ // ============================================================================
20
+ // INLINE SPLIT-VIEW MODE
21
+ // .pa-detail-view wraps a table (left) + panel (right)
22
+ // ============================================================================
23
+
24
+ .pa-detail-view {
25
+ display: flex;
26
+ gap: 0;
27
+ width: 100%;
28
+
29
+ // Left side: table/content area
30
+ &__main {
31
+ flex: 1;
32
+ min-width: 0;
33
+ overflow: auto;
34
+ }
35
+
36
+ // Right side: detail panel (hidden by default)
37
+ &__panel {
38
+ width: 0;
39
+ min-width: 0;
40
+ overflow: hidden;
41
+ flex-shrink: 0;
42
+ border-left: 0 solid var(--pa-border-color);
43
+
44
+ // Open state: show panel with configured width
45
+ &--open {
46
+ width: var(--pa-local-detail-panel-width);
47
+ min-width: $detail-panel-min-width;
48
+ max-width: var(--pa-local-detail-panel-max-width);
49
+ border-left-width: $border-width-base;
50
+ overflow: visible;
51
+ }
52
+ }
53
+ }
54
+
55
+ // ============================================================================
56
+ // CARD OVERLAY MODE
57
+ // .pa-detail-view--overlay: panel overlays the table within the card
58
+ // ============================================================================
59
+
60
+ .pa-detail-view--overlay {
61
+ position: relative;
62
+ overflow: hidden;
63
+
64
+ .pa-detail-view__panel {
65
+ position: absolute;
66
+ top: 0;
67
+ right: 0;
68
+ height: 100%;
69
+ z-index: 2;
70
+ }
71
+ }
72
+
73
+ // Backdrop for card overlay mode
74
+ .pa-detail-view__overlay {
75
+ position: absolute;
76
+ top: 0;
77
+ left: 0;
78
+ width: 100%;
79
+ height: 100%;
80
+ background-color: var(--pa-detail-panel-overlay-bg);
81
+ z-index: 1;
82
+ opacity: 0;
83
+ visibility: hidden;
84
+ cursor: pointer;
85
+
86
+ &--visible {
87
+ opacity: 1;
88
+ visibility: visible;
89
+ }
90
+ }
91
+
92
+ // ============================================================================
93
+ // OVERLAY MODE
94
+ // .pa-detail-panel--overlay is a fixed overlay (like profile panel)
95
+ // ============================================================================
96
+
97
+ .pa-detail-panel--overlay {
98
+ position: fixed;
99
+ top: 0;
100
+ right: 0;
101
+ height: 100vh;
102
+ z-index: var(--pa-detail-panel-z-index);
103
+ pointer-events: none;
104
+ opacity: 0;
105
+ visibility: hidden;
106
+
107
+ &.pa-detail-panel--open {
108
+ opacity: 1;
109
+ visibility: visible;
110
+ pointer-events: all;
111
+
112
+ .pa-detail-panel__content {
113
+ transform: translateX(0);
114
+ }
115
+ }
116
+ }
117
+
118
+ // ============================================================================
119
+ // SHARED PANEL STRUCTURE (used by both inline and overlay modes)
120
+ // ============================================================================
121
+
122
+ // Panel content wrapper (flex column: header/body/footer)
123
+ .pa-detail-panel__content {
124
+ display: flex;
125
+ flex-direction: column;
126
+ height: 100%;
127
+ background-color: var(--pa-card-bg);
128
+ position: relative;
129
+
130
+ // In overlay mode: slide-in from right
131
+ .pa-detail-panel--overlay & {
132
+ position: absolute;
133
+ top: 0;
134
+ right: 0;
135
+ height: 100vh;
136
+ width: var(--pa-local-detail-panel-width);
137
+ max-width: var(--pa-local-detail-panel-max-width);
138
+ box-shadow: $detail-panel-shadow;
139
+ transform: translateX(100%);
140
+ }
141
+ }
142
+
143
+ // Backdrop overlay (overlay mode only)
144
+ .pa-detail-panel__overlay {
145
+ position: absolute;
146
+ top: 0;
147
+ left: 0;
148
+ width: 100vw;
149
+ height: 100vh;
150
+ background-color: var(--pa-detail-panel-overlay-bg);
151
+ cursor: pointer;
152
+ }
153
+
154
+ // Panel header
155
+ .pa-detail-panel__header {
156
+ flex-shrink: 0;
157
+ display: flex;
158
+ align-items: center;
159
+ gap: $spacing-sm;
160
+ padding: $detail-panel-header-padding-v $detail-panel-header-padding-h;
161
+ border-bottom: $border-width-base solid var(--pa-border-color);
162
+ background-color: var(--pa-card-bg);
163
+ min-height: 0;
164
+ }
165
+
166
+ // Panel title
167
+ .pa-detail-panel__title {
168
+ flex: 1;
169
+ margin: 0;
170
+ font-size: $font-size-lg;
171
+ font-weight: $font-weight-semibold;
172
+ color: var(--pa-text-color-1);
173
+ overflow: hidden;
174
+ text-overflow: ellipsis;
175
+ white-space: nowrap;
176
+ }
177
+
178
+ // Close button
179
+ .pa-detail-panel__close {
180
+ width: $detail-panel-close-size;
181
+ height: $detail-panel-close-size;
182
+ flex-shrink: 0;
183
+ background: none;
184
+ border: none;
185
+ cursor: pointer;
186
+ display: flex;
187
+ align-items: center;
188
+ justify-content: center;
189
+ color: var(--pa-text-color-2);
190
+ border-radius: $border-radius;
191
+
192
+ &:hover {
193
+ background-color: var(--pa-accent-light);
194
+ color: var(--pa-accent);
195
+ }
196
+
197
+ &:focus {
198
+ outline: $focus-outline-width solid var(--pa-accent);
199
+ outline-offset: $focus-outline-offset;
200
+ }
201
+ }
202
+
203
+ // Panel tabs (between header and body, like profile panel)
204
+ .pa-detail-panel__tabs {
205
+ flex-shrink: 0;
206
+ padding: 0 $detail-panel-header-padding-h;
207
+ border-bottom: $border-width-base solid var(--pa-border-color);
208
+ background-color: var(--pa-card-bg);
209
+
210
+ .pa-tabs__item {
211
+ color: var(--pa-text-color-2);
212
+ border-bottom-color: transparent;
213
+
214
+ &:hover {
215
+ color: var(--pa-text-color-1);
216
+ background-color: var(--pa-accent-light);
217
+ }
218
+
219
+ &--active {
220
+ color: var(--pa-text-color-1);
221
+ border-bottom-color: var(--pa-accent);
222
+ }
223
+ }
224
+ }
225
+
226
+ // Panel body (scrollable)
227
+ .pa-detail-panel__body {
228
+ flex: 1;
229
+ overflow-y: auto;
230
+ padding: $detail-panel-body-padding-v $detail-panel-body-padding-h;
231
+ }
232
+
233
+ // Panel footer
234
+ .pa-detail-panel__footer {
235
+ flex-shrink: 0;
236
+ padding: $detail-panel-footer-padding-v $detail-panel-footer-padding-h;
237
+ border-top: $border-width-base solid var(--pa-border-color);
238
+ background-color: var(--pa-card-bg);
239
+ display: flex;
240
+ align-items: center;
241
+ gap: $spacing-sm;
242
+ }
243
+
244
+ // ============================================================================
245
+ // RESIZE HANDLE
246
+ // ============================================================================
247
+
248
+ .pa-detail-panel-resize {
249
+ position: absolute;
250
+ top: 0;
251
+ left: 0;
252
+ width: $detail-panel-resize-handle-width;
253
+ height: 100%;
254
+ cursor: col-resize;
255
+ z-index: 1;
256
+
257
+ &:hover,
258
+ &--active {
259
+ background-color: var(--pa-accent);
260
+ opacity: 0.3;
261
+ }
262
+ }
263
+
264
+ // Body class applied during resize drag
265
+ .pa-detail-panel-resizing {
266
+ cursor: col-resize !important;
267
+ user-select: none !important;
268
+ }
269
+
270
+ // ============================================================================
271
+ // TABLE ROW SELECTION
272
+ // ============================================================================
273
+
274
+ .pa-table tbody tr.is-selected {
275
+ background-color: var(--pa-detail-panel-selected-bg);
276
+
277
+ &:hover {
278
+ background-color: var(--pa-detail-panel-selected-bg);
279
+ }
280
+ }
281
+
282
+ // ============================================================================
283
+ // RESPONSIVE: Inline collapses to overlay on mobile
284
+ // ============================================================================
285
+
286
+ @media (max-width: $mobile-breakpoint) {
287
+ // Inline mode: hide the panel from the flex layout
288
+ .pa-detail-view__panel {
289
+ display: none;
290
+ }
291
+
292
+ // Mobile overlay: shown as fixed overlay instead
293
+ .pa-detail-panel--mobile-overlay {
294
+ display: block;
295
+ position: fixed;
296
+ top: 0;
297
+ right: 0;
298
+ height: 100vh;
299
+ z-index: var(--pa-detail-panel-z-index);
300
+ pointer-events: none;
301
+ opacity: 0;
302
+ visibility: hidden;
303
+
304
+ &.pa-detail-panel--open {
305
+ opacity: 1;
306
+ visibility: visible;
307
+ pointer-events: all;
308
+
309
+ .pa-detail-panel__content {
310
+ transform: translateX(0);
311
+ }
312
+ }
313
+
314
+ .pa-detail-panel__content {
315
+ position: absolute;
316
+ top: 0;
317
+ right: 0;
318
+ height: 100vh;
319
+ width: $detail-panel-mobile-width;
320
+ max-width: none;
321
+ box-shadow: $detail-panel-shadow;
322
+ transform: translateX(100%);
323
+ }
324
+
325
+ .pa-detail-panel__overlay {
326
+ position: absolute;
327
+ top: 0;
328
+ left: 0;
329
+ width: 100vw;
330
+ height: 100vh;
331
+ background-color: var(--pa-detail-panel-overlay-bg);
332
+ cursor: pointer;
333
+ }
334
+ }
335
+ }
@@ -173,6 +173,8 @@ $grid-columns-fractions: (
173
173
  .pa-col-#{$bp}-#{$size} {
174
174
  flex: 0 0 math.percentage(math.div($size, 100));
175
175
  max-width: math.percentage(math.div($size, 100));
176
+ padding-left: $grid-gutter;
177
+ padding-right: $grid-gutter;
176
178
  min-width: 0; // Prevent content overflow
177
179
  }
178
180
  }
@@ -182,6 +184,8 @@ $grid-columns-fractions: (
182
184
  .pa-col-#{$bp}-#{$name} {
183
185
  flex: 0 0 $width;
184
186
  max-width: $width;
187
+ padding-left: $grid-gutter;
188
+ padding-right: $grid-gutter;
185
189
  min-width: 0; // Prevent content overflow
186
190
  }
187
191
  }
@@ -13,6 +13,266 @@
13
13
  border-radius: $border-radius;
14
14
  border: $border-width-base solid var(--pa-border-color);
15
15
  background-color: var(--pa-table-bg);
16
+
17
+ // Panel modifier - card-like visual containment
18
+ &--panel {
19
+ box-shadow: $shadow-sm;
20
+ border-radius: $card-border-radius;
21
+ margin-bottom: $spacing-base;
22
+ transition: box-shadow $transition-fast $easing-snappy;
23
+
24
+ &:hover {
25
+ box-shadow: $shadow-lg;
26
+ }
27
+ }
28
+
29
+ // Header for panel tables
30
+ &__header {
31
+ display: flex;
32
+ align-items: center;
33
+ justify-content: space-between;
34
+ padding: $card-header-padding-v $card-header-padding-h;
35
+ min-height: $card-header-min-height;
36
+ border-bottom: $border-width-base solid var(--pa-border-color);
37
+ background: var(--pa-card-header-bg);
38
+ border-top-left-radius: $card-border-radius;
39
+ border-top-right-radius: $card-border-radius;
40
+ }
41
+
42
+ &__title {
43
+ font-size: $font-size-base;
44
+ font-weight: $font-weight-semibold;
45
+ margin: 0;
46
+ color: var(--pa-text-color-1);
47
+ }
48
+
49
+ &__actions {
50
+ display: flex;
51
+ align-items: center;
52
+ gap: $spacing-sm;
53
+
54
+ // Buttons in header - negative margin to prevent header height growth
55
+ .pa-btn {
56
+ margin-top: -0.25rem;
57
+ margin-bottom: -0.25rem;
58
+ }
59
+ }
60
+ }
61
+
62
+ // ============================================================================
63
+ // TABLE CARD
64
+ // Card-like container specifically designed for tables
65
+ // Similar to pa-card but with table as body content (no body padding)
66
+ // ============================================================================
67
+ .pa-table-card {
68
+ background: var(--pa-card-bg);
69
+ border: $card-border-width solid var(--pa-border-color);
70
+ border-radius: $card-border-radius;
71
+ margin-bottom: $spacing-base;
72
+ box-shadow: $shadow-sm;
73
+ transition: box-shadow $transition-fast $easing-snappy;
74
+ display: flex;
75
+ flex-direction: column;
76
+ overflow: hidden; // Ensure table respects border-radius
77
+
78
+ &:hover {
79
+ box-shadow: $shadow-lg;
80
+ }
81
+
82
+ &__header {
83
+ padding: $card-header-padding-v $card-header-padding-h;
84
+ min-height: $card-header-min-height;
85
+ border-top-left-radius: $card-border-radius;
86
+ border-top-right-radius: $card-border-radius;
87
+ border-bottom: $border-width-base solid var(--pa-border-color);
88
+ background: var(--pa-card-header-bg);
89
+ display: flex;
90
+ justify-content: space-between;
91
+ align-items: center;
92
+ min-width: 0;
93
+
94
+ h1, h2, h3, h4, h5, h6, p {
95
+ margin: 0;
96
+ padding: 0;
97
+ }
98
+
99
+ h1, h2, h3, h4, h5, h6 {
100
+ color: var(--pa-text-color-1);
101
+ font-size: $font-size-base;
102
+ font-weight: $font-weight-semibold;
103
+ }
104
+
105
+ .pa-btn {
106
+ margin-top: -0.25rem;
107
+ margin-bottom: -0.25rem;
108
+ }
109
+ }
110
+
111
+ &__title {
112
+ display: flex;
113
+ align-items: center;
114
+ gap: $spacing-sm;
115
+ min-width: 0;
116
+ flex: 1;
117
+
118
+ &-text {
119
+ overflow: hidden;
120
+ text-overflow: ellipsis;
121
+ white-space: nowrap;
122
+ margin: 0;
123
+ color: var(--pa-text-color-1);
124
+ font-size: $font-size-base;
125
+ font-weight: $font-weight-semibold;
126
+ line-height: 1;
127
+ }
128
+ }
129
+
130
+ &__actions {
131
+ display: flex;
132
+ gap: $spacing-sm;
133
+ align-items: center;
134
+ }
135
+
136
+ &__body {
137
+ flex: 1;
138
+ min-width: 0; // Allow body to shrink below content size for proper overflow
139
+
140
+ // Scrollable wrapper for tables (optional - use when table needs horizontal scroll)
141
+ &--scrollable {
142
+ overflow-x: auto;
143
+ }
144
+
145
+ // Table inside body
146
+ .pa-table {
147
+ border-radius: 0;
148
+
149
+ // Align first/last column with card header/footer padding
150
+ th:first-child,
151
+ td:first-child {
152
+ padding-left: $card-header-padding-h;
153
+ }
154
+
155
+ th:last-child,
156
+ td:last-child {
157
+ padding-right: $card-header-padding-h;
158
+ }
159
+
160
+ // Remove bottom border from last row (card border handles it)
161
+ tbody tr:last-child td {
162
+ border-bottom: none;
163
+ }
164
+ }
165
+ }
166
+
167
+ &__footer {
168
+ padding: $card-footer-padding-v $card-footer-padding-h;
169
+ border-top: $border-width-base solid var(--pa-border-color);
170
+ border-bottom-left-radius: $card-border-radius;
171
+ border-bottom-right-radius: $card-border-radius;
172
+ background: var(--pa-card-footer-bg);
173
+ display: flex;
174
+ justify-content: space-between;
175
+ align-items: center;
176
+ }
177
+
178
+ // Color variants
179
+ &--primary {
180
+ border-color: var(--pa-accent);
181
+
182
+ .pa-table-card__header {
183
+ background-color: var(--pa-accent);
184
+ color: var(--pa-btn-primary-text);
185
+
186
+ h1, h2, h3, h4, h5, h6 {
187
+ color: var(--pa-btn-primary-text);
188
+ }
189
+ }
190
+ }
191
+
192
+ &--success {
193
+ border-color: var(--pa-success-bg);
194
+
195
+ .pa-table-card__header {
196
+ background-color: var(--pa-success-bg);
197
+ color: var(--pa-btn-success-text);
198
+
199
+ h1, h2, h3, h4, h5, h6 {
200
+ color: var(--pa-btn-success-text);
201
+ }
202
+ }
203
+ }
204
+
205
+ &--warning {
206
+ border-color: var(--pa-warning-bg);
207
+
208
+ .pa-table-card__header {
209
+ background-color: var(--pa-warning-bg);
210
+ color: var(--pa-btn-warning-text);
211
+
212
+ h1, h2, h3, h4, h5, h6 {
213
+ color: var(--pa-btn-warning-text);
214
+ }
215
+ }
216
+ }
217
+
218
+ &--danger {
219
+ border-color: var(--pa-danger-bg);
220
+
221
+ .pa-table-card__header {
222
+ background-color: var(--pa-danger-bg);
223
+ color: var(--pa-btn-danger-text);
224
+
225
+ h1, h2, h3, h4, h5, h6 {
226
+ color: var(--pa-btn-danger-text);
227
+ }
228
+ }
229
+ }
230
+
231
+ // Theme color variants (color-1 through color-9)
232
+ @for $i from 1 through 9 {
233
+ &--color-#{$i} {
234
+ border-color: var(--pa-color-#{$i});
235
+
236
+ .pa-table-card__header {
237
+ background-color: var(--pa-color-#{$i});
238
+ color: var(--pa-color-#{$i}-text);
239
+
240
+ h1, h2, h3, h4, h5, h6 {
241
+ color: var(--pa-color-#{$i}-text);
242
+ }
243
+ }
244
+ }
245
+ }
246
+
247
+ // Plain variant - no card visual styling, just layout structure
248
+ &--plain {
249
+ background: transparent;
250
+ border: none;
251
+ box-shadow: none;
252
+ border-radius: 0;
253
+
254
+ &:hover {
255
+ box-shadow: none;
256
+ }
257
+
258
+ // Header in plain mode - simple text header without card styling
259
+ .pa-table-card__header {
260
+ background: transparent;
261
+ border-bottom: none;
262
+ border-radius: 0;
263
+ padding-left: 0;
264
+ padding-right: 0;
265
+ }
266
+
267
+ // Footer in plain mode
268
+ .pa-table-card__footer {
269
+ background: transparent;
270
+ border-top: none;
271
+ border-radius: 0;
272
+ padding-left: 0;
273
+ padding-right: 0;
274
+ }
275
+ }
16
276
  }
17
277
 
18
278
  .pa-table {
@@ -63,6 +323,23 @@
63
323
  }
64
324
  }
65
325
 
326
+ // Bordered variant - full cell borders
327
+ &--bordered {
328
+ border: $border-width-base solid var(--pa-border-color);
329
+
330
+ th,
331
+ td {
332
+ border: $border-width-base solid var(--pa-border-color);
333
+ }
334
+
335
+ // Keep last row border in bordered mode
336
+ &:not(&--responsive) {
337
+ tbody tr:last-child td {
338
+ border-bottom: $border-width-base solid var(--pa-border-color);
339
+ }
340
+ }
341
+ }
342
+
66
343
  // Size variants - synchronized with button/input sizes
67
344
  &--xs {
68
345
  th, td {
@@ -147,6 +147,26 @@ $profile-role-letter-spacing: 0.5px !default;
147
147
  $profile-panel-mobile-max-width: 40rem !default; // 400px (was 25rem)
148
148
  $profile-panel-content-padding: 1.6rem !default; // Matches sidebar-padding horizontal (16px)
149
149
 
150
+ // ============================================================================
151
+ // DETAIL PANEL SYSTEM
152
+ // ============================================================================
153
+ $detail-panel-width: 40rem !default;
154
+ $detail-panel-min-width: 28rem !default;
155
+ $detail-panel-max-width: 64rem !default;
156
+ $detail-panel-mobile-width: 90vw !default;
157
+ $detail-panel-header-padding-v: 1.2rem !default;
158
+ $detail-panel-header-padding-h: 1.6rem !default;
159
+ $detail-panel-body-padding-v: 1.2rem !default;
160
+ $detail-panel-body-padding-h: 1.6rem !default;
161
+ $detail-panel-footer-padding-v: 1.2rem !default;
162
+ $detail-panel-footer-padding-h: 1.6rem !default;
163
+ $detail-panel-overlay-bg: rgba(0, 0, 0, 0.3) !default;
164
+ $detail-panel-z-index: 4500 !default;
165
+ $detail-panel-shadow: $shadow-profile-panel !default;
166
+ $detail-panel-close-size: 3.2rem !default;
167
+ $detail-panel-resize-handle-width: 6px !default;
168
+ $detail-panel-selected-bg: rgba($accent-color, 0.08) !default;
169
+
150
170
  // ============================================================================
151
171
  // CARD SYSTEM
152
172
  // ============================================================================
@@ -535,3 +555,30 @@ $timeline-feed-time-width: 50px !default;
535
555
  $timeline-feed-time-font-size: $font-size-xs !default;
536
556
  $timeline-feed-time-padding-top: 6px !default;
537
557
  $timeline-feed-scroll-container-max-height: 400px !default;
558
+
559
+ // ============================================================================
560
+ // DATA DISPLAY (READ-ONLY FIELDS)
561
+ // ============================================================================
562
+ $field-label-font-size: $font-size-xs !default;
563
+ $field-label-font-weight: $font-weight-semibold !default;
564
+ $field-label-opacity: 0.55 !default;
565
+ $field-value-font-size: $font-size-sm !default;
566
+ $field-gap: $spacing-xs !default;
567
+ $field-horizontal-label-width: 14rem !default;
568
+ $fields-gap: $spacing-base !default;
569
+ $fields-relaxed-gap: $spacing-lg !default;
570
+ $fields-bordered-padding: $spacing-sm !default;
571
+ $fields-bordered-border-color: $border-color !default;
572
+ $fields-striped-bg: $table-stripe !default;
573
+ $fields-cols-gap: $spacing-base !default;
574
+ $fields-border-left: 3px solid $accent-color !default;
575
+ $fields-padding-left: $spacing-base !default;
576
+ $fields-filled-bg: rgba(128, 128, 128, 0.06) !default;
577
+ $fields-filled-padding: $spacing-base !default;
578
+
579
+ // Field group (labeled section of fields)
580
+ $field-group-gap: $spacing-sm !default;
581
+ $field-group-title-font-size: $font-size-sm !default;
582
+ $field-group-title-font-weight: $font-weight-semibold !default;
583
+ $field-group-title-border-color: $border-color !default;
584
+ $field-group-spacing: $spacing-lg !default;