ketekny-ui-kit 1.0.127 → 1.0.129

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/README.md CHANGED
@@ -205,7 +205,7 @@ Components:
205
205
  - `kSelectButton`, `kTags`, `kSearch`, `kArrayList`, `kList`, `kTextArea`
206
206
  - `kDialog`, `kDrawer`
207
207
  - `kAppHeader`, `kAppFooter`, `kAppMain`, `kHero`
208
- - `kSingleColPage`, `kTwoColPage`, `twoColLayout`, `legacyTwoColLayout`
208
+ - `kSingleColPage`, `kMultiColPage`, `twoColLayout`, `legacyTwoColLayout`
209
209
 
210
210
  Other exports:
211
211
 
@@ -242,4 +242,3 @@ ISC
242
242
 
243
243
  - Live demo/docs: https://ui.ketekny.gr
244
244
  - npm: https://www.npmjs.com/package/ketekny-ui-kit
245
-
package/index.js CHANGED
@@ -40,6 +40,7 @@ import kAppFooter from './src/layout/kAppFooter.vue'
40
40
  import kAppMain from './src/layout/kAppMain.vue'
41
41
  import kHero from './src/layout/kHero.vue'
42
42
  import kSingleColPage from './src/layout/kSingleColPage.vue'
43
+ import kMultiColPage from './src/layout/kMultiColPage.vue'
43
44
  import kTwoColPage from './src/layout/kTwoColPage.vue'
44
45
  import twoColLayout from './src/twoColLayout/components/TwoColLayout.vue'
45
46
  import legacyTwoColLayout from './src/layout/twoColLayout.vue'
@@ -66,7 +67,7 @@ export {
66
67
  kDialog, kDrawer,
67
68
 
68
69
  // Layout Components
69
- kAppHeader, kAppFooter, kAppMain, kHero, kSingleColPage, kTwoColPage, twoColLayout, legacyTwoColLayout,
70
+ kAppHeader, kAppFooter, kAppMain, kHero, kSingleColPage, kMultiColPage, kTwoColPage, twoColLayout, legacyTwoColLayout,
70
71
 
71
72
  // Plugins
72
73
  toastPlugin, confirmPlugin, alertPlugin, tooltipPlugin, inputDialogPlugin,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ketekny-ui-kit",
3
3
  "type": "module",
4
- "version": "1.0.127",
4
+ "version": "1.0.129",
5
5
  "description": "A Vue 3 UI component library with Tailwind CSS styling",
6
6
  "main": "index.js",
7
7
  "files": [
@@ -0,0 +1,5 @@
1
+ <script>
2
+ import kMultiColPage from './kTwoColPage.vue'
3
+
4
+ export default kMultiColPage
5
+ </script>
@@ -10,7 +10,7 @@
10
10
  v-if="showMobileOverlay"
11
11
  class="fixed inset-0 z-20 bg-slate-950/40 backdrop-blur-[1px] lg:hidden"
12
12
  :style="mobileOverlayStyle"
13
- @click="toggleMobileSidebar"
13
+ @click="closeMobileSidebar"
14
14
  />
15
15
 
16
16
  <section
@@ -59,31 +59,73 @@
59
59
  <div class="flex min-h-0 flex-1 flex-col overflow-hidden bg-slate-100 py-4">
60
60
  <div
61
61
  class="lg:hidden"
62
- :class="mobileSidebarOpen ? 'mx-auto flex w-full max-w-none px-4 pb-3 sm:px-6' : 'fixed left-0 top-1/2 z-20 -translate-y-1/2'"
62
+ :class="mobileSidebarOpen ? 'mx-auto flex w-full max-w-none items-center justify-between gap-3 px-4 pb-3 sm:px-6' : 'pointer-events-none fixed inset-x-0 top-1/2 z-20 flex -translate-y-1/2'"
63
63
  >
64
- <kButton
65
- :label="mobileSidebarOpen ? 'Hide sidebar' : 'Show sidebar'"
66
- :icon="mobileSidebarOpen ? 'PanelLeftClose' : 'PanelLeftOpen'"
67
- variant="soft"
68
- size="large"
69
- :icon-only="!mobileSidebarOpen"
70
- :aria-label="mobileSidebarOpen ? null : 'Show sidebar'"
71
- :class="mobileSidebarOpen ? '' : 'rounded-full text-slate-900 shadow-lg shadow-slate-900/15'"
72
- @click="toggleMobileSidebar"
73
- />
64
+ <button
65
+ v-if="hasLeftSidebar"
66
+ type="button"
67
+ :aria-label="mobileSidebarButtonAriaLabel('left')"
68
+ class="mobile-sidebar-trigger pointer-events-auto"
69
+ :class="mobileSidebarButtonClass('left')"
70
+ @click="toggleMobileSidebar('left')"
71
+ >
72
+ <kIcon
73
+ :name="mobileSidebarIconName('left')"
74
+ size="18"
75
+ />
76
+ <span v-if="mobileSidebarButtonShowsLabel('left')" class="mobile-sidebar-trigger__label">
77
+ {{ mobileSidebarButtonLabel('left') }}
78
+ </span>
79
+ </button>
80
+ <button
81
+ v-if="hasRightSidebar"
82
+ type="button"
83
+ :aria-label="mobileSidebarButtonAriaLabel('right')"
84
+ class="mobile-sidebar-trigger pointer-events-auto"
85
+ :class="mobileSidebarButtonClass('right')"
86
+ @click="toggleMobileSidebar('right')"
87
+ >
88
+ <kIcon
89
+ :name="mobileSidebarIconName('right')"
90
+ size="18"
91
+ />
92
+ <span v-if="mobileSidebarButtonShowsLabel('right')" class="mobile-sidebar-trigger__label">
93
+ {{ mobileSidebarButtonLabel('right') }}
94
+ </span>
95
+ </button>
74
96
  </div>
75
97
  <div class="mx-auto flex min-h-0 w-full max-w-none flex-1 gap-2">
76
98
  <aside
77
- v-if="showSidebar"
78
- class="min-h-0 shrink-0 overflow-y-auto bg-slate-100 px-4 sm:px-6 lg:ml-8 lg:pr-4 lg:pl-0"
79
- :class="mobileSidebarClass"
80
- :style="mobileSidebarStyle"
99
+ v-if="showLeftSidebar"
100
+ class="min-h-0 shrink-0 overflow-y-auto bg-slate-100"
101
+ :class="[mobileSidebarClass('left'), sidebarSurfaceClass('left')]"
102
+ :style="mobileSidebarStyle('left')"
81
103
  >
82
- <slot name="sidebar" />
104
+ <div v-if="effectiveSidebarLeftTitle" :class="sidebarTitleWrapClass('left')">
105
+ <p class="text-xs font-semibold uppercase tracking-[0.22em] text-slate-500">
106
+ {{ effectiveSidebarLeftTitle }}
107
+ </p>
108
+ </div>
109
+ <slot name="sidebar-left" v-bind="sidebarSlotProps('left')">
110
+ <slot name="sidebar" v-bind="sidebarSlotProps('left')" />
111
+ </slot>
83
112
  </aside>
84
113
  <section class="min-h-0 min-w-0 flex-1 overflow-y-auto px-2">
85
114
  <slot name="content" />
86
115
  </section>
116
+ <aside
117
+ v-if="showRightSidebar"
118
+ class="min-h-0 shrink-0 overflow-y-auto bg-slate-100"
119
+ :class="[mobileSidebarClass('right'), sidebarSurfaceClass('right')]"
120
+ :style="mobileSidebarStyle('right')"
121
+ >
122
+ <div v-if="sidebarRightTitle" :class="sidebarTitleWrapClass('right')">
123
+ <p class="text-xs font-semibold uppercase tracking-[0.22em] text-slate-500">
124
+ {{ sidebarRightTitle }}
125
+ </p>
126
+ </div>
127
+ <slot name="sidebar-right" v-bind="sidebarSlotProps('right')" />
128
+ </aside>
87
129
  </div>
88
130
  </div>
89
131
  </main>
@@ -92,6 +134,7 @@
92
134
  <script>
93
135
  import packageJson from '../../package.json'
94
136
  import kButton from '../ui/kButton.vue'
137
+ import kIcon from '../ui/kIcon.vue'
95
138
 
96
139
  const LG_VIEWPORT_QUERY = '(min-width: 1024px)'
97
140
  const MAIN_MENU_TOGGLE_EVENT = 'ketekny:two-col-layout-mobile-menu'
@@ -100,8 +143,8 @@ const MOBILE_SWIPE_OPEN_DISTANCE = 52
100
143
  const MOBILE_SWIPE_VERTICAL_TOLERANCE = 48
101
144
 
102
145
  export default {
103
- name: 'PageTwoColShell',
104
- components: { kButton },
146
+ name: 'MultiColPage',
147
+ components: { kButton, kIcon },
105
148
  props: {
106
149
  appTitle: {
107
150
  type: String,
@@ -123,13 +166,47 @@ export default {
123
166
  type: String,
124
167
  default: '300px',
125
168
  },
169
+ sidebarLeftWidth: {
170
+ type: String,
171
+ default: '',
172
+ },
173
+ sidebarDense: {
174
+ type: Boolean,
175
+ default: false,
176
+ },
177
+ sidebarLeftDense: {
178
+ type: Boolean,
179
+ default: false,
180
+ },
181
+ sidebarTitle: {
182
+ type: String,
183
+ default: '',
184
+ },
185
+ sidebarLeftTitle: {
186
+ type: String,
187
+ default: '',
188
+ },
189
+ sidebarRightWidth: {
190
+ type: String,
191
+ default: '',
192
+ },
193
+ sidebarRightDense: {
194
+ type: Boolean,
195
+ default: false,
196
+ },
197
+ sidebarRightTitle: {
198
+ type: String,
199
+ default: '',
200
+ },
126
201
  },
127
202
  data() {
128
203
  return {
129
204
  isDesktopViewport: true,
130
205
  mobileSidebarOpen: false,
206
+ mobileSidebarSide: 'left',
131
207
  viewportQuery: null,
132
208
  touchGesture: {
209
+ side: 'left',
133
210
  startX: 0,
134
211
  startY: 0,
135
212
  currentX: 0,
@@ -151,33 +228,42 @@ export default {
151
228
  if (!target) return ''
152
229
  return target.replace(/^https?:\/\//i, '').replace(/\/$/, '')
153
230
  },
154
- sidebarStyle() {
231
+ hasLeftSidebar() {
232
+ return Boolean(this.$slots['sidebar-left'] || this.$slots.sidebar)
233
+ },
234
+ hasRightSidebar() {
235
+ return Boolean(this.$slots['sidebar-right'])
236
+ },
237
+ effectiveSidebarLeftWidth() {
238
+ return this.sidebarLeftWidth || this.sidebarWidth || '300px'
239
+ },
240
+ effectiveSidebarLeftTitle() {
241
+ return this.sidebarLeftTitle || this.sidebarTitle
242
+ },
243
+ effectiveSidebarLeftDense() {
244
+ return this.sidebarLeftDense || this.sidebarDense
245
+ },
246
+ effectiveSidebarRightWidth() {
247
+ return this.sidebarRightWidth || this.effectiveSidebarLeftWidth
248
+ },
249
+ sidebarLeftStyle() {
155
250
  return {
156
- minWidth: this.sidebarWidth,
157
- maxWidth: this.sidebarWidth,
251
+ minWidth: this.effectiveSidebarLeftWidth,
252
+ maxWidth: this.effectiveSidebarLeftWidth,
158
253
  }
159
254
  },
160
- mobileSidebarClass() {
161
- if (this.isDesktopViewport) return ''
162
- return 'fixed left-0 top-0 z-20 h-full max-w-[85vw] border-r border-slate-200 bg-slate-100 py-4 shadow-xl shadow-slate-900/20 transition-transform duration-200 ease-out'
255
+ sidebarRightStyle() {
256
+ return {
257
+ minWidth: this.effectiveSidebarRightWidth,
258
+ maxWidth: this.effectiveSidebarRightWidth,
259
+ }
163
260
  },
164
261
  dragOffset() {
165
262
  if (!this.touchGesture.trackingEdgeSwipe) return 0
166
- return Math.max(0, this.touchGesture.currentX - this.touchGesture.startX)
167
- },
168
- mobileSidebarStyle() {
169
- const baseStyle = this.sidebarStyle
170
- if (this.isDesktopViewport || this.mobileSidebarOpen || !this.touchGesture.trackingEdgeSwipe) {
171
- return baseStyle
172
- }
173
- const widthValue = Number.parseFloat(this.sidebarWidth)
174
- const effectiveWidth = Number.isFinite(widthValue) ? widthValue : 300
175
- const clampedOffset = Math.min(this.dragOffset, effectiveWidth)
176
- return {
177
- ...baseStyle,
178
- transform: `translateX(${clampedOffset - effectiveWidth}px)`,
179
- transition: 'none',
263
+ if (this.touchGesture.side === 'right') {
264
+ return Math.max(0, this.touchGesture.startX - this.touchGesture.currentX)
180
265
  }
266
+ return Math.max(0, this.touchGesture.currentX - this.touchGesture.startX)
181
267
  },
182
268
  showMobileOverlay() {
183
269
  return !this.isDesktopViewport && (this.mobileSidebarOpen || this.touchGesture.trackingEdgeSwipe)
@@ -189,8 +275,13 @@ export default {
189
275
  opacity: String(progress),
190
276
  }
191
277
  },
192
- showSidebar() {
193
- return this.isDesktopViewport || this.mobileSidebarOpen || this.touchGesture.trackingEdgeSwipe
278
+ showLeftSidebar() {
279
+ if (!this.hasLeftSidebar) return false
280
+ return this.showSidebarForSide('left')
281
+ },
282
+ showRightSidebar() {
283
+ if (!this.hasRightSidebar) return false
284
+ return this.showSidebarForSide('right')
194
285
  },
195
286
  },
196
287
  mounted() {
@@ -206,10 +297,116 @@ export default {
206
297
  window.removeEventListener(MAIN_MENU_TOGGLE_EVENT, this.handleMainMenuToggle)
207
298
  },
208
299
  methods: {
300
+ sidebarSlotProps(side) {
301
+ return {
302
+ side,
303
+ title: side === 'right' ? this.sidebarRightTitle : this.effectiveSidebarLeftTitle,
304
+ dense: side === 'right' ? this.sidebarRightDense : this.effectiveSidebarLeftDense,
305
+ isDesktopViewport: this.isDesktopViewport,
306
+ mobileSidebarOpen: this.mobileSidebarOpen,
307
+ mobileSidebarSide: this.mobileSidebarSide,
308
+ isMobileSidebarActive: this.mobileSidebarOpen && this.mobileSidebarSide === side,
309
+ toggleMobileSidebar: () => this.toggleMobileSidebar(side),
310
+ closeMobileSidebar: this.closeMobileSidebar,
311
+ }
312
+ },
313
+ showSidebarForSide(side) {
314
+ if (this.isDesktopViewport) return true
315
+ return (
316
+ (this.mobileSidebarOpen && this.mobileSidebarSide === side) ||
317
+ (this.touchGesture.trackingEdgeSwipe && this.touchGesture.side === side)
318
+ )
319
+ },
320
+ mobileSidebarClass(side) {
321
+ if (this.isDesktopViewport) return ''
322
+ const horizontalClass = side === 'right'
323
+ ? 'fixed right-0 top-0 border-l border-slate-200'
324
+ : 'fixed left-0 top-0 border-r border-slate-200'
325
+ return `${horizontalClass} z-20 h-full max-w-[85vw] bg-slate-100 py-4 shadow-xl shadow-slate-900/20 transition-transform duration-200 ease-out`
326
+ },
327
+ mobileSidebarStyle(side) {
328
+ const baseStyle = side === 'right' ? this.sidebarRightStyle : this.sidebarLeftStyle
329
+ if (
330
+ this.isDesktopViewport ||
331
+ this.mobileSidebarOpen ||
332
+ !this.touchGesture.trackingEdgeSwipe ||
333
+ this.touchGesture.side !== side
334
+ ) {
335
+ return baseStyle
336
+ }
337
+ const widthValue = Number.parseFloat(
338
+ side === 'right' ? this.effectiveSidebarRightWidth : this.effectiveSidebarLeftWidth
339
+ )
340
+ const effectiveWidth = Number.isFinite(widthValue) ? widthValue : 300
341
+ const clampedOffset = Math.min(this.dragOffset, effectiveWidth)
342
+ const hiddenOffset = effectiveWidth - clampedOffset
343
+ const direction = side === 'right' ? hiddenOffset : clampedOffset - effectiveWidth
344
+ return {
345
+ ...baseStyle,
346
+ transform: `translateX(${direction}px)`,
347
+ transition: 'none',
348
+ }
349
+ },
350
+ mobileSidebarButtonClass(side) {
351
+ if (this.mobileSidebarOpen) {
352
+ return side === 'right' ? 'ml-auto' : ''
353
+ }
354
+ const title = this.sidebarTitleForSide(side)
355
+ const edgeClass = side === 'right'
356
+ ? 'ml-auto rounded-l-xl rounded-r-none border-r-0'
357
+ : 'rounded-l-none rounded-r-xl border-l-0'
358
+ if (title) {
359
+ return `${edgeClass} mobile-sidebar-trigger--titled min-h-0 min-w-0 px-2 py-3`
360
+ }
361
+ return side === 'right'
362
+ ? 'ml-auto rounded-full'
363
+ : 'rounded-full'
364
+ },
365
+ sidebarTitleForSide(side) {
366
+ return side === 'right' ? this.sidebarRightTitle : this.effectiveSidebarLeftTitle
367
+ },
368
+ sidebarDenseForSide(side) {
369
+ return side === 'right' ? this.sidebarRightDense : this.effectiveSidebarLeftDense
370
+ },
371
+ sidebarSurfaceClass(side) {
372
+ if (this.sidebarDenseForSide(side)) {
373
+ return ''
374
+ }
375
+ return side === 'right'
376
+ ? 'px-4 sm:px-6 lg:mr-8 lg:pl-4 lg:pr-0'
377
+ : 'px-4 sm:px-6 lg:ml-8 lg:pr-4 lg:pl-0'
378
+ },
379
+ sidebarTitleWrapClass(side) {
380
+ return this.sidebarDenseForSide(side) ? '' : 'pb-3'
381
+ },
382
+ mobileSidebarButtonLabel(side) {
383
+ if (this.mobileSidebarOpen && this.mobileSidebarSide === side) {
384
+ return 'Hide sidebar'
385
+ }
386
+ return this.sidebarTitleForSide(side) || 'Show sidebar'
387
+ },
388
+ mobileSidebarButtonAriaLabel(side) {
389
+ if (this.mobileSidebarOpen && this.mobileSidebarSide === side) return null
390
+ return this.sidebarTitleForSide(side) || 'Show sidebar'
391
+ },
392
+ mobileSidebarButtonShowsLabel(side) {
393
+ if (this.mobileSidebarOpen && this.mobileSidebarSide === side) return true
394
+ return Boolean(this.sidebarTitleForSide(side))
395
+ },
396
+ mobileSidebarIconName(side) {
397
+ if (side === 'right') {
398
+ return this.mobileSidebarOpen && this.mobileSidebarSide === side
399
+ ? 'PanelRightClose'
400
+ : 'PanelRightOpen'
401
+ }
402
+ return this.mobileSidebarOpen && this.mobileSidebarSide === side
403
+ ? 'PanelLeftClose'
404
+ : 'PanelLeftOpen'
405
+ },
209
406
  handleMainMenuToggle(event) {
210
407
  if (this.isDesktopViewport) return
211
408
  if (event?.detail?.open) {
212
- this.mobileSidebarOpen = false
409
+ this.closeMobileSidebar()
213
410
  }
214
411
  },
215
412
  handleViewportChange(event) {
@@ -218,13 +415,22 @@ export default {
218
415
  },
219
416
  syncSidebarForViewport() {
220
417
  if (!this.isDesktopViewport) {
221
- this.mobileSidebarOpen = false
222
- this.resetTouchState()
418
+ this.closeMobileSidebar()
223
419
  }
224
420
  },
225
- toggleMobileSidebar() {
421
+ toggleMobileSidebar(side = 'left') {
226
422
  if (this.isDesktopViewport) return
227
- this.mobileSidebarOpen = !this.mobileSidebarOpen
423
+ if ((side === 'left' && !this.hasLeftSidebar) || (side === 'right' && !this.hasRightSidebar)) return
424
+ if (this.mobileSidebarOpen && this.mobileSidebarSide === side) {
425
+ this.mobileSidebarOpen = false
426
+ } else {
427
+ this.mobileSidebarOpen = true
428
+ this.mobileSidebarSide = side
429
+ }
430
+ this.resetTouchState()
431
+ },
432
+ closeMobileSidebar() {
433
+ this.mobileSidebarOpen = false
228
434
  this.resetTouchState()
229
435
  },
230
436
  handleTouchStart(event) {
@@ -234,11 +440,19 @@ export default {
234
440
  }
235
441
  const touch = event.touches?.[0]
236
442
  if (!touch) return
443
+ const viewportWidth = typeof window === 'undefined' ? 0 : window.innerWidth
444
+ const isLeftEdge = this.hasLeftSidebar && touch.clientX <= MOBILE_EDGE_SWIPE_THRESHOLD
445
+ const isRightEdge = this.hasRightSidebar && viewportWidth - touch.clientX <= MOBILE_EDGE_SWIPE_THRESHOLD
446
+ if (!isLeftEdge && !isRightEdge) {
447
+ this.resetTouchState()
448
+ return
449
+ }
237
450
  this.touchGesture = {
451
+ side: isRightEdge ? 'right' : 'left',
238
452
  startX: touch.clientX,
239
453
  startY: touch.clientY,
240
454
  currentX: touch.clientX,
241
- trackingEdgeSwipe: touch.clientX <= MOBILE_EDGE_SWIPE_THRESHOLD,
455
+ trackingEdgeSwipe: true,
242
456
  }
243
457
  },
244
458
  handleTouchMove(event) {
@@ -255,14 +469,18 @@ export default {
255
469
  this.resetTouchState()
256
470
  return
257
471
  }
258
- const deltaX = this.touchGesture.currentX - this.touchGesture.startX
472
+ const deltaX = this.touchGesture.side === 'right'
473
+ ? this.touchGesture.startX - this.touchGesture.currentX
474
+ : this.touchGesture.currentX - this.touchGesture.startX
259
475
  if (deltaX >= MOBILE_SWIPE_OPEN_DISTANCE) {
260
476
  this.mobileSidebarOpen = true
477
+ this.mobileSidebarSide = this.touchGesture.side
261
478
  }
262
479
  this.resetTouchState()
263
480
  },
264
481
  resetTouchState() {
265
482
  this.touchGesture = {
483
+ side: 'left',
266
484
  startX: 0,
267
485
  startY: 0,
268
486
  currentX: 0,
@@ -277,3 +495,56 @@ export default {
277
495
  },
278
496
  }
279
497
  </script>
498
+
499
+ <style scoped>
500
+ .mobile-sidebar-trigger {
501
+ display: inline-flex;
502
+ align-items: center;
503
+ justify-content: center;
504
+ gap: 0.5rem;
505
+ min-height: 3.5rem;
506
+ padding: 0.875rem;
507
+ border: 1px solid rgb(203 213 225);
508
+ background: rgb(239 246 255);
509
+ color: rgb(15 23 42);
510
+ box-shadow: 0 10px 25px -15px rgba(15, 23, 42, 0.45);
511
+ }
512
+
513
+ .mobile-sidebar-trigger--titled {
514
+ flex-direction: column;
515
+ width: 3rem;
516
+ min-height: 8.5rem;
517
+ padding: 0.75rem 0.35rem;
518
+ }
519
+
520
+ .mobile-sidebar-trigger:focus-visible {
521
+ outline: 2px solid rgb(37 99 235);
522
+ outline-offset: 2px;
523
+ }
524
+
525
+ .mobile-sidebar-trigger__label {
526
+ display: inline-block;
527
+ font-size: 0.625rem;
528
+ font-weight: 700;
529
+ letter-spacing: 0.08em;
530
+ text-transform: uppercase;
531
+ white-space: nowrap;
532
+ }
533
+
534
+ .mobile-sidebar-trigger--titled .mobile-sidebar-trigger__label {
535
+ writing-mode: vertical-rl;
536
+ text-orientation: mixed;
537
+ line-height: 1;
538
+ }
539
+
540
+ .mobile-sidebar-trigger--titled :deep(svg) {
541
+ width: 0.9rem;
542
+ height: 0.9rem;
543
+ flex-shrink: 0;
544
+ display: block;
545
+ }
546
+
547
+ .mobile-sidebar-trigger--titled.rounded-l-none .mobile-sidebar-trigger__label {
548
+ transform: rotate(180deg);
549
+ }
550
+ </style>