@ossy/app 3.2.0 → 3.4.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,6 @@
1
+ export const metadata = {
2
+ id: '@ossy/app/actions/close-mobile-shell-nav',
3
+ access: 'public',
4
+ prefix: 'close',
5
+ label: 'app.shell.header.closeNav',
6
+ }
@@ -1,10 +1,15 @@
1
- import React from 'react'
1
+ import React, { useEffect, useState } from 'react'
2
2
  import {
3
3
  PageSection,
4
4
  View,
5
5
  Slot,
6
6
  } from '@ossy/design-system'
7
- import { useCompactShellLayout, shellSlotUnset } from '@ossy/app/shell'
7
+ import {
8
+ useCompactShellLayout,
9
+ shellSlotUnset,
10
+ ShellHeaderRow,
11
+ compactAppShellStyle,
12
+ } from '@ossy/app/shell'
8
13
 
9
14
  export const metadata = { id: '@ossy/app/layout/default' }
10
15
 
@@ -20,6 +25,13 @@ export default function DefaultLayout ({
20
25
  maxWidth = 'xl',
21
26
  }) {
22
27
  const compact = useCompactShellLayout()
28
+ const [mobileNavOpen, setMobileNavOpen] = useState(false)
29
+ const showSidebar = !shellSlotUnset(shellSlots['app:sidebar'])
30
+ const showHeader = !shellSlotUnset(shellSlots['app:header'])
31
+
32
+ useEffect(() => {
33
+ if (!compact) setMobileNavOpen(false)
34
+ }, [compact])
23
35
 
24
36
  return (
25
37
  <>
@@ -27,12 +39,14 @@ export default function DefaultLayout ({
27
39
  <View
28
40
  surface="base"
29
41
  data-ossy-app-shell
30
- style={{
31
- boxSizing: 'border-box',
32
- height: '100%',
33
- minWidth: 0,
34
- padding: compact ? 0 : 'var(--space-m)',
35
- }}
42
+ style={compact
43
+ ? compactAppShellStyle()
44
+ : {
45
+ boxSizing: 'border-box',
46
+ height: '100%',
47
+ minWidth: 0,
48
+ padding: 'var(--space-m)',
49
+ }}
36
50
  >
37
51
  <PageSection
38
52
  maxWidth={maxWidth}
@@ -55,13 +69,17 @@ export default function DefaultLayout ({
55
69
  ...(compact ? { gap: '4px' } : {}),
56
70
  }}
57
71
  >
58
- {!shellSlotUnset(shellSlots['app:sidebar']) && (
72
+ {showSidebar && !compact && (
59
73
  <Slot region="sidebar-primary" view="app:sidebar" />
60
74
  )}
61
75
 
62
- {!shellSlotUnset(shellSlots['app:header']) && (
63
- <Slot region="header" view="app:header" />
64
- )}
76
+ <ShellHeaderRow
77
+ compact={compact}
78
+ showSidebar={showSidebar}
79
+ showHeader={showHeader}
80
+ mobileNavOpen={mobileNavOpen}
81
+ onMobileNavOpenChange={setMobileNavOpen}
82
+ />
65
83
 
66
84
  <View
67
85
  data-region="content"
@@ -40,7 +40,7 @@ export default function DefaultHeader ({
40
40
  gap: compact ? 'var(--space-xs)' : 'var(--space-s)',
41
41
  }}
42
42
  >
43
- <LanguageSelect />
43
+ <LanguageSelect compact={compact} />
44
44
  <ThemeSelect compact={compact} />
45
45
  <HeaderAuthActions compact={compact} />
46
46
  </View>
@@ -0,0 +1,6 @@
1
+ export const metadata = {
2
+ id: '@ossy/app/actions/open-mobile-shell-nav',
3
+ access: 'public',
4
+ prefix: 'menu',
5
+ label: 'app.shell.header.openNav',
6
+ }
@@ -2,6 +2,12 @@ import React, { useState, useMemo, useRef, useEffect, useCallback } from 'react'
2
2
  import { Button, View, Slot, useLocale } from '@ossy/design-system'
3
3
  import { useRouter } from '@ossy/router-react'
4
4
  import { useApp, buildSidebarNav, patchUserAppSettings, useCompactShellLayout, useShellWorkspace } from '@ossy/app/shell'
5
+ import {
6
+ isDrawerPresentation,
7
+ resolveSidebarBorderRadius,
8
+ resolveSidebarSmall,
9
+ shouldShowSidebarCollapseControl,
10
+ } from '../shell/sidebarChrome.js'
5
11
 
6
12
  export const metadata = { id: '@ossy/app/component/sidebar/default' }
7
13
 
@@ -47,6 +53,7 @@ function navLabelForItem (item, showLabels, t) {
47
53
 
48
54
  export default function DefaultSidebar ({
49
55
  small: smallProp = false,
56
+ presentation,
50
57
  ...rest
51
58
  }) {
52
59
  const [hoverRailExpanded, setHoverRailExpanded] = useState(false)
@@ -56,6 +63,7 @@ export default function DefaultSidebar ({
56
63
  const compactViewport = useCompactShellLayout()
57
64
  const initialSidebarCollapsed = app?.sidebarPrimaryCollapsed === true
58
65
  const [sidebarCollapsed, setSidebarCollapsed] = useState(initialSidebarCollapsed)
66
+ const isDrawer = isDrawerPresentation(presentation)
59
67
 
60
68
  const onToggleCollapsed = useCallback(() => {
61
69
  setSidebarCollapsed((collapsed) => {
@@ -65,16 +73,25 @@ export default function DefaultSidebar ({
65
73
  })
66
74
  }, [])
67
75
 
68
- const small = compactViewport || sidebarCollapsed || smallProp
76
+ const small = resolveSidebarSmall({
77
+ presentation,
78
+ compactViewport,
79
+ sidebarCollapsed,
80
+ smallProp,
81
+ })
69
82
  const { workspace } = useShellWorkspace()
70
83
  const router = useRouter()
71
84
  const { t } = useLocale()
72
85
 
73
- const desktopHoverRail = small && !compactViewport
86
+ const desktopHoverRail = small && !compactViewport && !isDrawer
74
87
  const showLabels = !small || (desktopHoverRail && hoverRailExpanded)
75
88
  const iconOnly = !showLabels
76
89
  const hoverExpandedDesktop = desktopHoverRail && hoverRailExpanded
77
90
  const narrowChrome = small
91
+ const showCollapseControl = shouldShowSidebarCollapseControl({
92
+ presentation,
93
+ compactViewport,
94
+ })
78
95
 
79
96
  const { shellItems, packageItems } = useMemo(
80
97
  () => buildSidebarNav({
@@ -186,6 +203,7 @@ export default function DefaultSidebar ({
186
203
  prefix={item.prefix}
187
204
  title={item.title}
188
205
  aria-current={item.selected ? 'page' : undefined}
206
+ data-ossy-sidebar-nav-item={item.key ?? item.href}
189
207
  style={{
190
208
  justifyContent: iconOnly ? 'center' : 'flex-start',
191
209
  padding: hoverExpandedDesktop ? '8px 24px' : (narrowChrome ? 'var(--space-s)' : '8px 24px'),
@@ -200,17 +218,18 @@ export default function DefaultSidebar ({
200
218
  {...(!desktopHoverRail ? rest : {})}
201
219
  surface="primary"
202
220
  gap={narrowChrome ? 's' : 'm'}
221
+ data-ossy-sidebar-presentation={isDrawer ? 'drawer' : undefined}
203
222
  style={{
204
223
  height: '100%',
205
- width: desktopHoverRail ? '100%' : 'auto',
224
+ width: isDrawer || desktopHoverRail ? '100%' : 'auto',
206
225
  minWidth: small ? 0 : undefined,
207
- maxHeight: small ? '100%' : undefined,
226
+ maxHeight: small || isDrawer ? '100%' : undefined,
208
227
  padding: hoverExpandedDesktop
209
228
  ? 'var(--space-m) var(--space-l) var(--space-m) var(--space-m)'
210
229
  : narrowChrome
211
230
  ? 'var(--space-s) var(--space-xs)'
212
231
  : 'var(--space-m) var(--space-l) var(--space-m) var(--space-m)',
213
- borderRadius: 'var(--space-l) var(--space-s) var(--space-s) var(--space-l)',
232
+ borderRadius: resolveSidebarBorderRadius(presentation),
214
233
  flexShrink: 0,
215
234
  boxSizing: 'border-box',
216
235
  }}
@@ -233,7 +252,7 @@ export default function DefaultSidebar ({
233
252
  {menuNear.map(renderButton)}
234
253
  </View>
235
254
 
236
- {onToggleCollapsed && !compactViewport && (
255
+ {onToggleCollapsed && showCollapseControl && (
237
256
  <View style={{ flexShrink: 0, marginTop: 'var(--space-s)' }}>
238
257
  <Button
239
258
  variant="link"
@@ -1,10 +1,15 @@
1
- import React from 'react'
1
+ import React, { useEffect, useState } from 'react'
2
2
  import {
3
3
  PageSection,
4
4
  View,
5
5
  Slot,
6
6
  } from '@ossy/design-system'
7
- import { useCompactShellLayout, shellSlotUnset } from '@ossy/app/shell'
7
+ import {
8
+ useCompactShellLayout,
9
+ shellSlotUnset,
10
+ ShellHeaderRow,
11
+ compactAppShellStyle,
12
+ } from '@ossy/app/shell'
8
13
 
9
14
  export const metadata = { id: '@ossy/app/layout/workspace' }
10
15
 
@@ -23,6 +28,13 @@ export default function WorkspaceLayout ({
23
28
  maxWidth = 'xl',
24
29
  }) {
25
30
  const compact = useCompactShellLayout()
31
+ const [mobileNavOpen, setMobileNavOpen] = useState(false)
32
+ const showSidebar = !shellSlotUnset(shellSlots['app:sidebar'])
33
+ const showHeader = !shellSlotUnset(shellSlots['app:header'])
34
+
35
+ useEffect(() => {
36
+ if (!compact) setMobileNavOpen(false)
37
+ }, [compact])
26
38
 
27
39
  return (
28
40
  <>
@@ -30,12 +42,14 @@ export default function WorkspaceLayout ({
30
42
  <View
31
43
  surface="base"
32
44
  data-ossy-app-shell
33
- style={{
34
- boxSizing: 'border-box',
35
- height: '100%',
36
- minWidth: 0,
37
- padding: compact ? 0 : 'var(--space-m)',
38
- }}
45
+ style={compact
46
+ ? compactAppShellStyle()
47
+ : {
48
+ boxSizing: 'border-box',
49
+ height: '100%',
50
+ minWidth: 0,
51
+ padding: 'var(--space-m)',
52
+ }}
39
53
  >
40
54
  <PageSection
41
55
  maxWidth={maxWidth}
@@ -58,13 +72,17 @@ export default function WorkspaceLayout ({
58
72
  ...(compact ? { gap: '4px' } : {}),
59
73
  }}
60
74
  >
61
- {!shellSlotUnset(shellSlots['app:sidebar']) && (
75
+ {showSidebar && !compact && (
62
76
  <Slot region="sidebar-primary" view="app:sidebar" />
63
77
  )}
64
78
 
65
- {!shellSlotUnset(shellSlots['app:header']) && (
66
- <Slot region="header" view="app:header" />
67
- )}
79
+ <ShellHeaderRow
80
+ compact={compact}
81
+ showSidebar={showSidebar}
82
+ showHeader={showHeader}
83
+ mobileNavOpen={mobileNavOpen}
84
+ onMobileNavOpenChange={setMobileNavOpen}
85
+ />
68
86
 
69
87
  <View
70
88
  data-region="content"
@@ -4,5 +4,8 @@
4
4
  "app.shell.header.languagePicker": "Språk",
5
5
  "app.shell.footer.languages": "Språk",
6
6
  "app.shell.header.themeSwitch": "{theme}-tema. Byt tema.",
7
- "app.shell.header.profile": "Profil"
7
+ "app.shell.header.profile": "Profil",
8
+ "app.shell.header.openNav": "Öppna navigation",
9
+ "app.shell.header.closeNav": "Stäng navigation",
10
+ "app.shell.header.nav": "Huvudnavigation"
8
11
  }