@toyonix/web-kit 0.1.2 → 0.1.3

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.
@@ -111,32 +111,80 @@
111
111
  outline: var(--tx-border-width) solid var(--tx-border);
112
112
  }
113
113
 
114
- /* Narrow screens: app links get their own row under the logo, scrolling sideways if needed. */
114
+ /*
115
+ * Narrow screens: stay on one row. The header gets more compact, and if the app links still
116
+ * don't fit, they scroll sideways (AppShell scrolls the current app into view).
117
+ */
115
118
  @media (max-width: 640px) {
116
119
  .tx-header__inner {
117
- flex-wrap: wrap;
118
- row-gap: 4px;
119
- padding-top: 10px;
120
- padding-bottom: 8px;
121
- min-height: 0;
120
+ gap: 10px;
121
+ min-height: 56px;
122
122
  }
123
123
 
124
- .tx-header__inner .tx-icon-btn {
125
- margin-left: auto;
124
+ .tx-logo {
125
+ flex: none;
126
+ gap: 8px;
127
+ font-size: 20px;
128
+ }
129
+
130
+ .tx-logo__mark {
131
+ width: 26px;
132
+ height: 26px;
133
+ font-size: 13px;
126
134
  }
127
135
 
128
136
  .tx-nav {
129
- order: 3;
137
+ flex: 0 1 auto;
130
138
  flex-wrap: nowrap;
131
- width: 100%;
132
- margin-left: 0;
133
- padding: 4px 3px 6px;
139
+ min-width: 0;
140
+ padding: 3px; /* room for the current app's outline */
134
141
  overflow-x: auto;
135
142
  scrollbar-width: none;
136
143
  }
137
144
 
145
+ .tx-nav::-webkit-scrollbar {
146
+ display: none;
147
+ }
148
+
149
+ /* Fade only the edges that have more links beyond them (set by AppShell), hinting at the scroll. */
150
+ .tx-nav[data-more-left],
151
+ .tx-nav[data-more-right] {
152
+ --tx-nav-fade-left: 0px;
153
+ --tx-nav-fade-right: 0px;
154
+ -webkit-mask-image: linear-gradient(
155
+ to right,
156
+ transparent,
157
+ #000 var(--tx-nav-fade-left),
158
+ #000 calc(100% - var(--tx-nav-fade-right)),
159
+ transparent
160
+ );
161
+ mask-image: linear-gradient(
162
+ to right,
163
+ transparent,
164
+ #000 var(--tx-nav-fade-left),
165
+ #000 calc(100% - var(--tx-nav-fade-right)),
166
+ transparent
167
+ );
168
+ }
169
+
170
+ .tx-nav[data-more-left] {
171
+ --tx-nav-fade-left: 22px;
172
+ }
173
+
174
+ .tx-nav[data-more-right] {
175
+ --tx-nav-fade-right: 22px;
176
+ }
177
+
138
178
  .tx-nav a {
139
179
  flex: none;
180
+ padding: 6px 9px;
181
+ font-size: 14px;
182
+ }
183
+
184
+ .tx-header__inner .tx-icon-btn {
185
+ flex: none;
186
+ width: 36px;
187
+ height: 36px;
140
188
  }
141
189
  }
142
190
 
@@ -3,6 +3,7 @@ import { appHref, getAppId } from "../env.js";
3
3
  import { navApps } from "../registry/index.js";
4
4
  import { ThemeToggle } from "./ThemeToggle.js";
5
5
  import { useRegistry } from "./use-registry.js";
6
+ import { useEffect, useRef } from "react";
6
7
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
8
  //#region src/react/AppShell.tsx
8
9
  /**
@@ -12,6 +13,29 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
12
13
  function AppShell({ children, registry, appTitle, nav, footer }) {
13
14
  const appId = getAppId();
14
15
  const apps = navApps(useRegistry(registry));
16
+ const navRef = useRef(null);
17
+ const appCount = apps.length;
18
+ useEffect(() => {
19
+ const nav = navRef.current;
20
+ if (!nav) return;
21
+ const markEdges = () => {
22
+ const max = nav.scrollWidth - nav.clientWidth;
23
+ nav.toggleAttribute("data-more-left", max > 1 && nav.scrollLeft > 1);
24
+ nav.toggleAttribute("data-more-right", max > 1 && nav.scrollLeft < max - 1);
25
+ };
26
+ const update = () => {
27
+ const current = nav.querySelector("[aria-current]");
28
+ if (current && nav.scrollWidth > nav.clientWidth + 1) nav.scrollLeft = current.offsetLeft - (nav.clientWidth - current.offsetWidth) / 2;
29
+ markEdges();
30
+ };
31
+ update();
32
+ nav.addEventListener("scroll", markEdges, { passive: true });
33
+ window.addEventListener("resize", update);
34
+ return () => {
35
+ nav.removeEventListener("scroll", markEdges);
36
+ window.removeEventListener("resize", update);
37
+ };
38
+ }, [appCount]);
15
39
  if (appId !== "root" && !apps.some((app) => app.id === appId)) apps.push({
16
40
  id: appId,
17
41
  title: appTitle ?? appId,
@@ -42,6 +66,7 @@ function AppShell({ children, registry, appTitle, nav, footer }) {
42
66
  }), /* @__PURE__ */ jsx("span", { children: "toyonix" })]
43
67
  }),
44
68
  /* @__PURE__ */ jsxs("nav", {
69
+ ref: navRef,
45
70
  className: "tx-nav",
46
71
  "aria-label": "toyonix apps",
47
72
  children: [/* @__PURE__ */ jsx("a", {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toyonix/web-kit",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Shared design system, components, and tooling for every toyonix static site.",
5
5
  "license": "MIT",
6
6
  "author": "ToYoNiX",