@wordpress/boot 0.3.1-next.8b30e05b0.0 → 0.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.
Files changed (44) hide show
  1. package/build-module/components/app/router.js +25 -21
  2. package/build-module/components/app/router.js.map +2 -2
  3. package/build-module/components/app/use-route-title.js +50 -0
  4. package/build-module/components/app/use-route-title.js.map +7 -0
  5. package/build-module/components/canvas/back-button.js +3 -3
  6. package/build-module/components/canvas/back-button.js.map +1 -1
  7. package/build-module/components/navigation/navigation-item/index.js +2 -2
  8. package/build-module/components/navigation/navigation-item/index.js.map +1 -1
  9. package/build-module/components/root/index.js +291 -37
  10. package/build-module/components/root/index.js.map +2 -2
  11. package/build-module/components/root/single-page.js +164 -7
  12. package/build-module/components/root/single-page.js.map +2 -2
  13. package/build-module/components/site-hub/index.js +3 -3
  14. package/build-module/components/site-hub/index.js.map +1 -1
  15. package/build-module/components/site-icon/index.js +2 -2
  16. package/build-module/components/site-icon/index.js.map +1 -1
  17. package/build-module/components/site-icon-link/index.js +3 -3
  18. package/build-module/components/site-icon-link/index.js.map +1 -1
  19. package/build-module/index.js +108 -46
  20. package/build-module/index.js.map +2 -2
  21. package/build-style/style-rtl.css +107 -45
  22. package/build-style/style.css +107 -45
  23. package/build-types/components/app/router.d.ts.map +1 -1
  24. package/build-types/components/app/use-route-title.d.ts +8 -0
  25. package/build-types/components/app/use-route-title.d.ts.map +1 -0
  26. package/build-types/components/root/index.d.ts.map +1 -1
  27. package/build-types/components/root/single-page.d.ts.map +1 -1
  28. package/build-types/store/types.d.ts +64 -7
  29. package/build-types/store/types.d.ts.map +1 -1
  30. package/package.json +22 -21
  31. package/src/components/app/router.tsx +39 -38
  32. package/src/components/app/use-route-title.ts +80 -0
  33. package/src/components/canvas/back-button.scss +2 -2
  34. package/src/components/navigation/navigation-item/style.scss +1 -1
  35. package/src/components/root/index.tsx +148 -31
  36. package/src/components/root/single-page.tsx +3 -0
  37. package/src/components/root/style.scss +122 -4
  38. package/src/components/site-hub/style.scss +2 -2
  39. package/src/components/site-icon/style.scss +1 -1
  40. package/src/components/site-icon-link/style.scss +2 -2
  41. package/src/store/types.ts +71 -7
  42. package/src/style.scss +1 -0
  43. package/tsconfig.json +1 -0
  44. package/tsconfig.tsbuildinfo +1 -1
@@ -1,4 +1,5 @@
1
1
  @use "@wordpress/base-styles/variables";
2
+ @use "@wordpress/base-styles/mixins";
2
3
 
3
4
  .boot-layout {
4
5
  height: 100%;
@@ -10,37 +11,154 @@
10
11
  background: var(--wpds-color-bg-surface-neutral-weak, #f0f0f0);
11
12
  }
12
13
 
14
+ .boot-layout__sidebar-backdrop {
15
+ position: fixed;
16
+ top: 0;
17
+ left: 0;
18
+ right: 0;
19
+ bottom: 0;
20
+ background-color: rgba(0, 0, 0, 0.5);
21
+ z-index: 100002;
22
+ cursor: pointer;
23
+ }
24
+
13
25
  .boot-layout__sidebar {
14
26
  height: 100%;
15
27
  flex-shrink: 0;
16
28
  width: 240px;
17
29
  position: relative;
18
30
  overflow: hidden;
31
+
32
+ &.is-mobile {
33
+ position: fixed;
34
+ top: 0;
35
+ bottom: 0;
36
+ left: 0;
37
+ width: 300px;
38
+ max-width: 85vw;
39
+ background: var(--wpds-color-bg-surface-neutral-weak, #f0f0f0);
40
+ z-index: 100003;
41
+ box-shadow: 2px 0 8px rgba(0, 0, 0, 0.2);
42
+ }
43
+ }
44
+
45
+ .boot-layout__mobile-sidebar-drawer {
46
+ position: fixed;
47
+ top: 0;
48
+ left: 0;
49
+ right: 0;
50
+ z-index: 3;
51
+ background: var(--wpds-color-bg-surface-neutral, #fff);
52
+ padding: variables.$grid-unit-20;
53
+ border-bottom: 1px solid var(--wpds-color-stroke-surface-neutral-weak, #ddd);
54
+ display: flex;
55
+ justify-content: flex-start;
56
+ align-items: center;
57
+ }
58
+
59
+ .boot-layout__canvas.has-mobile-drawer {
60
+ position: relative;
61
+ padding-top: 65px;
19
62
  }
20
63
 
21
64
  .boot-layout__surfaces {
22
65
  display: flex;
23
66
  flex-grow: 1;
24
- margin: variables.$grid-unit-10;
67
+ margin: 0;
25
68
  gap: variables.$grid-unit-10;
69
+
70
+ @include mixins.break-medium {
71
+ margin: variables.$grid-unit-10;
72
+
73
+ .boot-layout--single-page & {
74
+ margin-top: 0;
75
+ }
76
+ }
26
77
  }
27
78
 
28
79
  .boot-layout__stage,
29
- .boot-layout__inspector,
80
+ .boot-layout__inspector {
81
+ flex: 1;
82
+ overflow-y: auto;
83
+ background: var(--wpds-color-bg-surface-neutral, #fff);
84
+ color: var(--wpds-color-fg-content-neutral, #1e1e1e);
85
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
86
+ border: 1px solid var(--wpds-color-stroke-surface-neutral-weak, #ddd);
87
+ position: relative;
88
+
89
+ // Mobile-first: surfaces take full screen with fixed positioning
90
+ position: fixed;
91
+ top: 0;
92
+ left: 0;
93
+ right: 0;
94
+ bottom: 0;
95
+ width: 100vw;
96
+ height: 100vh;
97
+ border-radius: 0;
98
+ margin: 0;
99
+
100
+ // Desktop: restore original styles
101
+ @include mixins.break-medium {
102
+ position: static;
103
+ width: auto;
104
+ height: auto;
105
+ border-radius: 8px;
106
+ margin: 0;
107
+ }
108
+ }
109
+
110
+ .boot-layout__stage {
111
+ z-index: 2; // Highest surface priority on mobile
112
+
113
+ @include mixins.break-medium {
114
+ z-index: auto;
115
+ }
116
+ }
117
+
118
+ .boot-layout__inspector {
119
+ z-index: 3; // Medium surface priority on mobile
120
+
121
+ @include mixins.break-medium {
122
+ z-index: auto;
123
+ }
124
+ }
125
+
30
126
  .boot-layout__canvas {
31
127
  flex: 1;
32
128
  overflow-y: auto;
33
129
  background: var(--wpds-color-bg-surface-neutral, #fff);
34
130
  color: var(--wpds-color-fg-content-neutral, #1e1e1e);
35
- border-radius: 8px;
36
131
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
37
132
  border: 1px solid var(--wpds-color-stroke-surface-neutral-weak, #ddd);
38
133
  position: relative;
134
+
135
+ // Mobile-first: full screen with lowest priority
136
+ position: fixed;
137
+ top: 0;
138
+ left: 0;
139
+ right: 0;
140
+ bottom: 0;
141
+ width: 100vw;
142
+ height: 100vh;
143
+ z-index: 1; // Lowest surface priority
144
+ border-radius: 0;
145
+ margin: 0;
146
+
147
+ // Desktop: restore original styles
148
+ @include mixins.break-medium {
149
+ position: static;
150
+ width: auto;
151
+ height: auto;
152
+ border-radius: 8px;
153
+ z-index: auto;
154
+ }
39
155
  }
40
156
 
41
157
  .boot-layout.has-canvas .boot-layout__stage,
42
158
  .boot-layout__inspector {
43
- max-width: 400px;
159
+ @include mixins.break-medium {
160
+ max-width: 400px;
161
+ }
44
162
  }
45
163
 
46
164
  .boot-layout__canvas .interface-interface-skeleton {
@@ -47,8 +47,8 @@
47
47
 
48
48
  &:focus:not(:active) {
49
49
  outline:
50
- var(--wpds-border-width-focus, 2px) solid
50
+ var(--wpds-border-width-interactive-focus, 2px) solid
51
51
  var(--wpds-color-stroke-focus-brand, #0073aa);
52
- outline-offset: calc(-1 * var(--wpds-border-width-focus, 2px));
52
+ outline-offset: calc(-1 * var(--wpds-border-width-interactive-focus, 2px));
53
53
  }
54
54
  }
@@ -15,5 +15,5 @@
15
15
  height: variables.$grid-unit-40;
16
16
  object-fit: cover;
17
17
  aspect-ratio: 1 / 1;
18
- border-radius: var(--wpds-border-radius-medium, 4px);
18
+ border-radius: var(--wpds-border-radius-surface-md, 4px);
19
19
  }
@@ -17,8 +17,8 @@ $header-height: variables.$header-height;
17
17
 
18
18
  &:focus:not(:active) {
19
19
  outline:
20
- var(--wpds-border-width-focus, 2px) solid
20
+ var(--wpds-border-width-interactive-focus, 2px) solid
21
21
  var(--wpds-color-stroke-focus-brand, #0073aa);
22
- outline-offset: calc(-1 * var(--wpds-border-width-focus, 2px));
22
+ outline-offset: calc(-1 * var(--wpds-border-width-interactive-focus, 2px));
23
23
  }
24
24
  }
@@ -63,6 +63,75 @@ export interface CanvasData {
63
63
  editLink?: string;
64
64
  }
65
65
 
66
+ /**
67
+ * Route lifecycle configuration exported from route_module.
68
+ * The module should export a named `route` object with these optional functions.
69
+ */
70
+ export interface RouteConfig {
71
+ /**
72
+ * Pre-navigation hook for authentication, validation, or redirects.
73
+ * Called before the route is loaded.
74
+ */
75
+ beforeLoad?: ( context: RouteLoaderContext ) => void | Promise< void >;
76
+
77
+ /**
78
+ * Data preloading function.
79
+ * Called when the route is being loaded.
80
+ */
81
+ loader?: ( context: RouteLoaderContext ) => Promise< unknown >;
82
+
83
+ /**
84
+ * Function that returns canvas data for rendering.
85
+ * - Returns CanvasData to use default editor canvas
86
+ * - Returns null to use custom canvas component from content_module
87
+ * - Returns undefined to show no canvas
88
+ */
89
+ canvas?: (
90
+ context: RouteLoaderContext
91
+ ) => Promise< CanvasData | null | undefined >;
92
+
93
+ /**
94
+ * Function that determines whether to show the inspector panel.
95
+ * When not defined, defaults to true (always show inspector if component exists).
96
+ * When it returns false, the inspector is hidden even if an inspector component is exported.
97
+ *
98
+ * @example
99
+ * ```tsx
100
+ * export const route = {
101
+ * inspector: ({ search }) => {
102
+ * // Only show inspector when items are selected
103
+ * return search.selectedIds?.length > 0;
104
+ * },
105
+ * };
106
+ * ```
107
+ */
108
+ inspector?: ( context: RouteLoaderContext ) => boolean | Promise< boolean >;
109
+
110
+ /**
111
+ * Function that returns the document title for the route.
112
+ * The returned title will be formatted as: "{title} ‹ {siteTitle} — WordPress"
113
+ * and announced to screen readers for accessibility.
114
+ *
115
+ * @param context Route context with params and search
116
+ * @return The document title string or a Promise resolving to a string
117
+ *
118
+ * @example
119
+ * ```tsx
120
+ * export const route = {
121
+ * title: async ({ params }) => {
122
+ * const post = await resolveSelect(coreStore).getEntityRecord(
123
+ * 'postType',
124
+ * params.type,
125
+ * params.id
126
+ * );
127
+ * return post?.title?.rendered || 'Edit Post';
128
+ * },
129
+ * };
130
+ * ```
131
+ */
132
+ title?: ( context: RouteLoaderContext ) => string | Promise< string >;
133
+ }
134
+
66
135
  /**
67
136
  * Route configuration interface.
68
137
  * Routes specify content_module for surfaces and optionally route_module for lifecycle functions.
@@ -85,13 +154,8 @@ export interface Route {
85
154
 
86
155
  /**
87
156
  * Module path for route lifecycle functions.
88
- * The module should export a named export `route` containing:
89
- * - beforeLoad?: Pre-navigation hook (authentication, validation, redirects)
90
- * - loader?: Data preloading function
91
- * - canvas?: Function that returns canvas data for rendering
92
- * - Returns CanvasData to use default editor canvas
93
- * - Returns null to use custom canvas component from content_module
94
- * - Returns undefined to show no canvas
157
+ * The module should export a named `route` object implementing RouteConfig.
158
+ * @see RouteConfig for available lifecycle functions.
95
159
  */
96
160
  route_module?: string;
97
161
  }
package/src/style.scss CHANGED
@@ -11,6 +11,7 @@
11
11
  body:has(.boot-layout-container) {
12
12
  background: #1d2327; // Same as WP-Admin sidebar
13
13
  overflow: hidden;
14
+ @include wp-admin-reset( ".boot-layout-container" );
14
15
  }
15
16
 
16
17
  #wpcontent {
package/tsconfig.json CHANGED
@@ -5,6 +5,7 @@
5
5
  "checkJs": false
6
6
  },
7
7
  "references": [
8
+ { "path": "../a11y" },
8
9
  { "path": "../admin-ui" },
9
10
  { "path": "../components" },
10
11
  { "path": "../compose" },