@lessly/ui 1.5.0 → 2.0.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.
- package/README.md +35 -17
- package/dist/chunk-F5RMHSPS.js +433 -0
- package/dist/index.d.ts +34 -104
- package/dist/index.js +1300 -1896
- package/dist/router.d.ts +101 -0
- package/dist/router.js +254 -0
- package/dist/styles-federated.css +112 -7
- package/dist/styles.css +106 -1
- package/dist/tailwind-preset.js +23 -1
- package/package.json +11 -3
package/dist/router.d.ts
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { LucideIcon } from 'lucide-react';
|
|
3
|
+
|
|
4
|
+
type ExtensionLinkUiMode = 'federation' | 'standalone';
|
|
5
|
+
interface ExtensionLinkProps extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> {
|
|
6
|
+
/**
|
|
7
|
+
* 'federation' → the extension runs inside the workspace shell and navigates
|
|
8
|
+
* client-side via react-router's <Link>. 'standalone' → the extension is
|
|
9
|
+
* served full-page, so a plain <a href> triggers a normal document load.
|
|
10
|
+
*/
|
|
11
|
+
uiMode: ExtensionLinkUiMode;
|
|
12
|
+
/** Target route/href. */
|
|
13
|
+
to: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Federation-aware navigation link. Federation extensions are mounted in-shell
|
|
17
|
+
* and navigate client-side (react-router <Link>); standalone extensions load
|
|
18
|
+
* full-page (<a href>). Anchor props are forwarded to both variants — in
|
|
19
|
+
* particular onMouseEnter/onFocus, which hosts use to preload the target route.
|
|
20
|
+
*
|
|
21
|
+
* The federation branch renders a react-router <Link>, so it must be used
|
|
22
|
+
* within a Router context (the workspace shell / MemoryRouter in tests).
|
|
23
|
+
*/
|
|
24
|
+
declare function ExtensionLink({ uiMode, to, className, children, ...anchorProps }: ExtensionLinkProps): React.JSX.Element;
|
|
25
|
+
declare namespace ExtensionLink {
|
|
26
|
+
var displayName: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface NavItem {
|
|
30
|
+
label: string;
|
|
31
|
+
href: string;
|
|
32
|
+
icon?: LucideIcon;
|
|
33
|
+
exact?: boolean;
|
|
34
|
+
}
|
|
35
|
+
type NavLinkComponent = React.ComponentType<{
|
|
36
|
+
to: string;
|
|
37
|
+
className?: string;
|
|
38
|
+
children?: React.ReactNode;
|
|
39
|
+
} & Record<string, unknown>>;
|
|
40
|
+
interface SidebarNavLinkProps {
|
|
41
|
+
item: NavItem;
|
|
42
|
+
collapsed?: boolean;
|
|
43
|
+
active?: boolean;
|
|
44
|
+
basePath?: string;
|
|
45
|
+
LinkComponent?: NavLinkComponent;
|
|
46
|
+
className?: string;
|
|
47
|
+
}
|
|
48
|
+
declare function SidebarNavLink({ item, collapsed, active, basePath, LinkComponent, className, }: SidebarNavLinkProps): React.JSX.Element;
|
|
49
|
+
interface SidebarNavProps {
|
|
50
|
+
items: NavItem[];
|
|
51
|
+
collapsed?: boolean;
|
|
52
|
+
basePath?: string;
|
|
53
|
+
LinkComponent?: NavLinkComponent;
|
|
54
|
+
isItemActive?: (item: NavItem, pathname: string) => boolean;
|
|
55
|
+
className?: string;
|
|
56
|
+
}
|
|
57
|
+
declare function SidebarNav({ items, collapsed, basePath, LinkComponent, isItemActive, className, }: SidebarNavProps): React.JSX.Element;
|
|
58
|
+
|
|
59
|
+
interface AppSidebarProps {
|
|
60
|
+
items: NavItem[];
|
|
61
|
+
/** Expanded-slot mark/wordmark, rendered when `header` is absent. Also the collapsed-rail
|
|
62
|
+
* fallback when `logoCollapsed` isn't given, on a rail that isn't `collapsible` — see
|
|
63
|
+
* `logoCollapsed`. */
|
|
64
|
+
logo?: React.ReactNode;
|
|
65
|
+
/** Collapsed-rail identity — a small mark, for a rail that cannot be expanded from inside it.
|
|
66
|
+
* A `collapsible` rail shows the pin here instead and never reads this: the 52px rail holds
|
|
67
|
+
* one box, and the way back to expanded is what it holds. */
|
|
68
|
+
logoCollapsed?: React.ReactNode;
|
|
69
|
+
/** Identity slot above the rail — e.g. an <OrgProductSwitcher/> (#266). Falls back to `logo`.
|
|
70
|
+
* Expanded-only: rendering it in the 52px collapsed rail would overflow, so the collapsed
|
|
71
|
+
* branch never reads it. What stands in depends on `collapsible` — the pin when it is set,
|
|
72
|
+
* `logoCollapsed ?? logo` when it is not. */
|
|
73
|
+
header?: React.ReactNode;
|
|
74
|
+
/** Account slot below the rail — e.g. a <UserMenu/>. Its divider renders only with it. */
|
|
75
|
+
footer?: React.ReactNode;
|
|
76
|
+
/** Render the built-in collapse pin. Off by default: the shipped rail has none.
|
|
77
|
+
* `collapsed` is still honoured without it, for consumers driving collapse themselves. */
|
|
78
|
+
collapsible?: boolean;
|
|
79
|
+
collapsed?: boolean;
|
|
80
|
+
defaultCollapsed?: boolean;
|
|
81
|
+
onCollapsedChange?: (collapsed: boolean) => void;
|
|
82
|
+
basePath?: string;
|
|
83
|
+
LinkComponent?: NavLinkComponent;
|
|
84
|
+
isItemActive?: (item: NavItem, pathname: string) => boolean;
|
|
85
|
+
className?: string;
|
|
86
|
+
}
|
|
87
|
+
declare function AppSidebar({ items, logo, logoCollapsed, header, footer, collapsible, collapsed: controlled, defaultCollapsed, onCollapsedChange, basePath, LinkComponent, isItemActive, className, }: AppSidebarProps): React.JSX.Element;
|
|
88
|
+
|
|
89
|
+
interface AppShellProps {
|
|
90
|
+
/** The sidebar, typically an <AppSidebar/>. Rendered in the desktop rail and,
|
|
91
|
+
* on mobile, inside a Sheet (force-expanded via cloneElement collapsed=false). */
|
|
92
|
+
sidebar: React.ReactNode;
|
|
93
|
+
topBar?: React.ReactNode;
|
|
94
|
+
children?: React.ReactNode;
|
|
95
|
+
className?: string;
|
|
96
|
+
}
|
|
97
|
+
declare function AppShell({ sidebar, topBar, children, className }: AppShellProps): React.JSX.Element;
|
|
98
|
+
/** Alias of AppShell — reads better in app router files. */
|
|
99
|
+
declare const AuthenticatedLayout: typeof AppShell;
|
|
100
|
+
|
|
101
|
+
export { AppShell, type AppShellProps, AppSidebar, type AppSidebarProps, AuthenticatedLayout, ExtensionLink, type ExtensionLinkProps, type ExtensionLinkUiMode, type NavItem, type NavLinkComponent, SidebarNav, SidebarNavLink, type SidebarNavLinkProps, type SidebarNavProps };
|
package/dist/router.js
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Button,
|
|
3
|
+
NavRow,
|
|
4
|
+
Sheet,
|
|
5
|
+
SheetContent,
|
|
6
|
+
SheetDescription,
|
|
7
|
+
SheetTitle,
|
|
8
|
+
SheetTrigger,
|
|
9
|
+
Tooltip,
|
|
10
|
+
TooltipContent,
|
|
11
|
+
TooltipProvider,
|
|
12
|
+
TooltipTrigger,
|
|
13
|
+
cn,
|
|
14
|
+
useIsMobile,
|
|
15
|
+
useSidebar
|
|
16
|
+
} from "./chunk-F5RMHSPS.js";
|
|
17
|
+
|
|
18
|
+
// src/components/extension-link.tsx
|
|
19
|
+
import { Link } from "react-router";
|
|
20
|
+
import { jsx } from "react/jsx-runtime";
|
|
21
|
+
function ExtensionLink({ uiMode, to, className, children, ...anchorProps }) {
|
|
22
|
+
if (uiMode === "federation") {
|
|
23
|
+
return /* @__PURE__ */ jsx(Link, { to, className, ...anchorProps, children });
|
|
24
|
+
}
|
|
25
|
+
return /* @__PURE__ */ jsx("a", { href: to, className, ...anchorProps, children });
|
|
26
|
+
}
|
|
27
|
+
ExtensionLink.displayName = "ExtensionLink";
|
|
28
|
+
|
|
29
|
+
// src/components/sidebar-nav.tsx
|
|
30
|
+
import { Link as Link2, useLocation } from "react-router";
|
|
31
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
32
|
+
function isActivePath(pathname, full, exact) {
|
|
33
|
+
if (exact) return pathname === full;
|
|
34
|
+
return pathname === full || pathname.startsWith(`${full}/`);
|
|
35
|
+
}
|
|
36
|
+
function SidebarNavLink({
|
|
37
|
+
item,
|
|
38
|
+
collapsed = false,
|
|
39
|
+
active = false,
|
|
40
|
+
basePath = "",
|
|
41
|
+
LinkComponent,
|
|
42
|
+
className
|
|
43
|
+
}) {
|
|
44
|
+
const Comp = LinkComponent ?? Link2;
|
|
45
|
+
const to = `${basePath}${item.href}`;
|
|
46
|
+
const Icon = item.icon;
|
|
47
|
+
const link = /* @__PURE__ */ jsx2(
|
|
48
|
+
NavRow,
|
|
49
|
+
{
|
|
50
|
+
variant: "rail",
|
|
51
|
+
active,
|
|
52
|
+
label: item.label,
|
|
53
|
+
hideLabel: collapsed,
|
|
54
|
+
icon: Icon ? /* @__PURE__ */ jsx2(Icon, { "aria-hidden": "true" }) : void 0,
|
|
55
|
+
className: cn(collapsed && "size-9 justify-center px-0 py-0", className),
|
|
56
|
+
asChild: true,
|
|
57
|
+
children: /* @__PURE__ */ jsx2(Comp, { to, "aria-current": active ? "page" : void 0 })
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
if (!collapsed) return link;
|
|
61
|
+
return /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
62
|
+
/* @__PURE__ */ jsx2(TooltipTrigger, { asChild: true, children: link }),
|
|
63
|
+
/* @__PURE__ */ jsx2(TooltipContent, { side: "right", children: item.label })
|
|
64
|
+
] });
|
|
65
|
+
}
|
|
66
|
+
function SidebarNav({
|
|
67
|
+
items,
|
|
68
|
+
collapsed = false,
|
|
69
|
+
basePath = "",
|
|
70
|
+
LinkComponent,
|
|
71
|
+
isItemActive,
|
|
72
|
+
className
|
|
73
|
+
}) {
|
|
74
|
+
const { pathname } = useLocation();
|
|
75
|
+
const nav = /* @__PURE__ */ jsx2(
|
|
76
|
+
"nav",
|
|
77
|
+
{
|
|
78
|
+
className: cn(
|
|
79
|
+
"flex flex-col gap-2",
|
|
80
|
+
collapsed && "items-center",
|
|
81
|
+
className
|
|
82
|
+
),
|
|
83
|
+
children: items.map((item) => {
|
|
84
|
+
const full = `${basePath}${item.href}`;
|
|
85
|
+
const active = isItemActive ? isItemActive(item, pathname) : isActivePath(pathname, full, item.exact);
|
|
86
|
+
return /* @__PURE__ */ jsx2(
|
|
87
|
+
SidebarNavLink,
|
|
88
|
+
{
|
|
89
|
+
item,
|
|
90
|
+
active,
|
|
91
|
+
collapsed,
|
|
92
|
+
basePath,
|
|
93
|
+
LinkComponent
|
|
94
|
+
},
|
|
95
|
+
item.href
|
|
96
|
+
);
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
return collapsed ? /* @__PURE__ */ jsx2(TooltipProvider, { children: nav }) : nav;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// src/components/app-sidebar.tsx
|
|
104
|
+
import { PanelLeft } from "lucide-react";
|
|
105
|
+
import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
106
|
+
function Divider({ collapsed, testId, className }) {
|
|
107
|
+
return /* @__PURE__ */ jsx3(
|
|
108
|
+
"div",
|
|
109
|
+
{
|
|
110
|
+
"data-testid": testId,
|
|
111
|
+
className: cn(
|
|
112
|
+
"h-px shrink-0 bg-border-subtle",
|
|
113
|
+
collapsed ? "ml-[6px] w-[40px]" : "ml-[14px] w-[220px]",
|
|
114
|
+
className
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
function AppSidebar({
|
|
120
|
+
items,
|
|
121
|
+
logo,
|
|
122
|
+
logoCollapsed,
|
|
123
|
+
header,
|
|
124
|
+
footer,
|
|
125
|
+
collapsible = false,
|
|
126
|
+
collapsed: controlled,
|
|
127
|
+
defaultCollapsed,
|
|
128
|
+
onCollapsedChange,
|
|
129
|
+
basePath,
|
|
130
|
+
LinkComponent,
|
|
131
|
+
isItemActive,
|
|
132
|
+
className
|
|
133
|
+
}) {
|
|
134
|
+
const { collapsed, toggle } = useSidebar({
|
|
135
|
+
collapsed: controlled,
|
|
136
|
+
defaultCollapsed,
|
|
137
|
+
onCollapsedChange
|
|
138
|
+
});
|
|
139
|
+
const pin = collapsible ? /* @__PURE__ */ jsx3(
|
|
140
|
+
"button",
|
|
141
|
+
{
|
|
142
|
+
type: "button",
|
|
143
|
+
onClick: toggle,
|
|
144
|
+
"aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar",
|
|
145
|
+
"aria-expanded": !collapsed,
|
|
146
|
+
className: "flex size-6 shrink-0 items-center justify-center rounded-md text-text-secondary transition-colors hover:bg-[var(--hov-bg)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus",
|
|
147
|
+
children: /* @__PURE__ */ jsx3(PanelLeft, { className: "size-4", "aria-hidden": "true" })
|
|
148
|
+
}
|
|
149
|
+
) : null;
|
|
150
|
+
return /* @__PURE__ */ jsxs2(
|
|
151
|
+
"aside",
|
|
152
|
+
{
|
|
153
|
+
"data-collapsed": collapsed,
|
|
154
|
+
className: cn(
|
|
155
|
+
"flex h-full shrink-0 flex-col overflow-hidden transition-[width] duration-200 ease-in-out",
|
|
156
|
+
collapsed ? "w-[52px]" : "w-[248px]",
|
|
157
|
+
className
|
|
158
|
+
),
|
|
159
|
+
children: [
|
|
160
|
+
/* @__PURE__ */ jsx3("div", { className: cn("flex h-14 items-center gap-2", collapsed ? "justify-center px-1" : "px-3"), children: collapsed ? collapsible ? (
|
|
161
|
+
/* The 52px rail holds one 32px box, and the way back to expanded is what it holds.
|
|
162
|
+
The logo has the expanded band and the top bar; the pin has nowhere else, and a
|
|
163
|
+
pin hidden behind the mark is no pin at all on a device that cannot hover. */
|
|
164
|
+
/* @__PURE__ */ jsx3(
|
|
165
|
+
"button",
|
|
166
|
+
{
|
|
167
|
+
type: "button",
|
|
168
|
+
onClick: toggle,
|
|
169
|
+
"aria-label": "Expand sidebar",
|
|
170
|
+
"aria-expanded": false,
|
|
171
|
+
className: "flex size-8 shrink-0 items-center justify-center rounded-md text-text-secondary transition-colors hover:bg-[var(--hov-bg)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus",
|
|
172
|
+
children: /* @__PURE__ */ jsx3(PanelLeft, { className: "size-4", "aria-hidden": "true" })
|
|
173
|
+
}
|
|
174
|
+
)
|
|
175
|
+
) : logoCollapsed ?? logo : /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
176
|
+
header ?? logo,
|
|
177
|
+
pin
|
|
178
|
+
] }) }),
|
|
179
|
+
/* @__PURE__ */ jsx3(Divider, { collapsed, testId: "sidebar-divider-header" }),
|
|
180
|
+
/* @__PURE__ */ jsx3(
|
|
181
|
+
"div",
|
|
182
|
+
{
|
|
183
|
+
"data-testid": "sidebar-scroll",
|
|
184
|
+
className: cn(
|
|
185
|
+
"min-h-0 flex-1 overflow-y-auto overflow-x-hidden pt-3 pb-2",
|
|
186
|
+
collapsed ? "px-1" : "px-3"
|
|
187
|
+
),
|
|
188
|
+
children: /* @__PURE__ */ jsx3(SidebarNav, { items, collapsed, basePath, LinkComponent, isItemActive })
|
|
189
|
+
}
|
|
190
|
+
),
|
|
191
|
+
footer && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
192
|
+
/* @__PURE__ */ jsx3(Divider, { collapsed, testId: "sidebar-divider-account" }),
|
|
193
|
+
/* @__PURE__ */ jsx3("div", { className: cn("py-2", collapsed ? "px-1" : "px-3"), children: footer })
|
|
194
|
+
] })
|
|
195
|
+
]
|
|
196
|
+
}
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// src/components/app-shell.tsx
|
|
201
|
+
import * as React from "react";
|
|
202
|
+
import { Menu } from "lucide-react";
|
|
203
|
+
import { useLocation as useLocation2 } from "react-router";
|
|
204
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
205
|
+
function expandedSidebar(sidebar) {
|
|
206
|
+
return React.isValidElement(sidebar) ? React.cloneElement(sidebar, { collapsed: false }) : sidebar;
|
|
207
|
+
}
|
|
208
|
+
function AppShell({ sidebar, topBar, children, className }) {
|
|
209
|
+
const { pathname } = useLocation2();
|
|
210
|
+
const [mobileOpen, setMobileOpen] = React.useState(false);
|
|
211
|
+
React.useEffect(() => {
|
|
212
|
+
setMobileOpen(false);
|
|
213
|
+
}, [pathname]);
|
|
214
|
+
const isMobile = useIsMobile();
|
|
215
|
+
if (isMobile) {
|
|
216
|
+
return /* @__PURE__ */ jsx4(TooltipProvider, { children: /* @__PURE__ */ jsxs3("div", { className: cn("flex min-h-screen flex-col bg-bg-surface", className), children: [
|
|
217
|
+
/* @__PURE__ */ jsxs3(
|
|
218
|
+
"header",
|
|
219
|
+
{
|
|
220
|
+
"data-slot": "app-shell-mobile-header",
|
|
221
|
+
className: "flex shrink-0 items-center justify-between border-b border-border-subtle bg-bg-surface px-4 py-3",
|
|
222
|
+
children: [
|
|
223
|
+
/* @__PURE__ */ jsxs3(Sheet, { open: mobileOpen, onOpenChange: setMobileOpen, children: [
|
|
224
|
+
/* @__PURE__ */ jsx4(SheetTrigger, { asChild: true, children: /* @__PURE__ */ jsx4(Button, { variant: "ghost", size: "icon", className: "size-8 text-text-secondary", "aria-label": "Open navigation", children: /* @__PURE__ */ jsx4(Menu, { className: "size-5" }) }) }),
|
|
225
|
+
/* @__PURE__ */ jsxs3(SheetContent, { side: "left", className: "w-[248px] bg-bg-surface p-0", children: [
|
|
226
|
+
/* @__PURE__ */ jsx4(SheetTitle, { className: "sr-only", children: "Navigation" }),
|
|
227
|
+
/* @__PURE__ */ jsx4(SheetDescription, { className: "sr-only", children: "Application navigation menu" }),
|
|
228
|
+
expandedSidebar(sidebar)
|
|
229
|
+
] })
|
|
230
|
+
] }),
|
|
231
|
+
/* @__PURE__ */ jsx4("div", { className: "flex items-center gap-2", children: topBar })
|
|
232
|
+
]
|
|
233
|
+
}
|
|
234
|
+
),
|
|
235
|
+
/* @__PURE__ */ jsx4("main", { className: "flex-1 overflow-auto px-4", children })
|
|
236
|
+
] }) });
|
|
237
|
+
}
|
|
238
|
+
return /* @__PURE__ */ jsx4(TooltipProvider, { children: /* @__PURE__ */ jsxs3("div", { className: cn("flex min-h-screen gap-3 bg-bg-surface p-4", className), children: [
|
|
239
|
+
/* @__PURE__ */ jsx4("div", { className: "sticky top-4 h-[calc(100vh-32px)] shrink-0", children: sidebar }),
|
|
240
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex min-w-0 flex-1 flex-col overflow-hidden", children: [
|
|
241
|
+
topBar && /* @__PURE__ */ jsx4("div", { "data-slot": "app-shell-topbar", className: "flex h-14 shrink-0 items-center gap-2 px-6", children: topBar }),
|
|
242
|
+
/* @__PURE__ */ jsx4("main", { className: "flex-1 overflow-y-auto px-6", children })
|
|
243
|
+
] })
|
|
244
|
+
] }) });
|
|
245
|
+
}
|
|
246
|
+
var AuthenticatedLayout = AppShell;
|
|
247
|
+
export {
|
|
248
|
+
AppShell,
|
|
249
|
+
AppSidebar,
|
|
250
|
+
AuthenticatedLayout,
|
|
251
|
+
ExtensionLink,
|
|
252
|
+
SidebarNav,
|
|
253
|
+
SidebarNavLink
|
|
254
|
+
};
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* on a parent element (usually <html> or <body>).
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
:root {
|
|
15
|
+
:where(:root) {
|
|
16
16
|
--bg-primary: #191b24;
|
|
17
17
|
--bg-secondary: #12141b;
|
|
18
18
|
--bg-surface: #1f222d;
|
|
@@ -276,7 +276,7 @@
|
|
|
276
276
|
--inverted-foreground: var(--bg-brand);
|
|
277
277
|
}
|
|
278
278
|
|
|
279
|
-
.light {
|
|
279
|
+
:where(.light) {
|
|
280
280
|
--bg-primary: #f6f7f7;
|
|
281
281
|
--bg-secondary: #eeeff0;
|
|
282
282
|
--bg-surface: #f2f3f4;
|
|
@@ -385,7 +385,7 @@
|
|
|
385
385
|
|
|
386
386
|
/* Reduced motion — collapse every motion variable to instant/linear (see reducedMotionBlock in build.js). */
|
|
387
387
|
@media (prefers-reduced-motion: reduce) {
|
|
388
|
-
:root {
|
|
388
|
+
:where(:root) {
|
|
389
389
|
--motion-duration-instant: 0ms;
|
|
390
390
|
--motion-duration-fast: 0ms;
|
|
391
391
|
--motion-duration-normal: 0ms;
|
|
@@ -413,7 +413,7 @@
|
|
|
413
413
|
/* === Deprecated aliases — remove in the next major ===
|
|
414
414
|
Old vendored `--color-*` names mapped onto the @lessly/tokens variables above.
|
|
415
415
|
Generated by scripts/build-styles.mjs — do not edit. */
|
|
416
|
-
:root {
|
|
416
|
+
:where(:root) {
|
|
417
417
|
--color-bg-primary: var(--bg-primary);
|
|
418
418
|
--color-bg-secondary: var(--bg-secondary);
|
|
419
419
|
--color-bg-surface: var(--bg-surface);
|
|
@@ -465,7 +465,7 @@
|
|
|
465
465
|
--color-border-danger: var(--border-danger);
|
|
466
466
|
}
|
|
467
467
|
|
|
468
|
-
.light {
|
|
468
|
+
:where(.light) {
|
|
469
469
|
--color-bg-primary: var(--bg-primary);
|
|
470
470
|
--color-bg-secondary: var(--bg-secondary);
|
|
471
471
|
--color-bg-surface: var(--bg-surface);
|
|
@@ -530,7 +530,18 @@
|
|
|
530
530
|
:where(:root) {
|
|
531
531
|
--spacing: 0.25rem;
|
|
532
532
|
}
|
|
533
|
-
:root {
|
|
533
|
+
:where(:root) {
|
|
534
|
+
/* === Translucent tints the kit paints (#701) === */
|
|
535
|
+
/* A semantic token is a whole colour with no `<alpha-value>` placeholder, so `bg-bg-secondary/50`
|
|
536
|
+
compiles to nothing on Tailwind 3 while Tailwind 4 answers it with color-mix. These are the
|
|
537
|
+
three alphas the kit writes, as variables the preset maps a colour name onto so both majors
|
|
538
|
+
and both consumption paths resolve them. Like --hov-bg below, the inner var() resolves at the
|
|
539
|
+
element that paints, so `.light` needs no override. Delete each the release @lessly/tokens
|
|
540
|
+
publishes its semantic colours with an `<alpha-value>` placeholder. */
|
|
541
|
+
--bg-secondary-a50: color-mix(in oklab, var(--bg-secondary) 50%, transparent);
|
|
542
|
+
--bg-secondary-a80: color-mix(in oklab, var(--bg-secondary) 80%, transparent);
|
|
543
|
+
--bg-danger-a90: color-mix(in oklab, var(--bg-danger) 90%, transparent);
|
|
544
|
+
|
|
534
545
|
/* === Nav / menu surfaces (0.3.0 sidebar) === */
|
|
535
546
|
/* The floating surface sits on the package's overlay pair: --menu-bg on
|
|
536
547
|
--bg-overlay, --menu-shadow on --shadow-overlay. theme.css re-resolves both
|
|
@@ -553,7 +564,7 @@
|
|
|
553
564
|
--auth-btn-shadow: none;
|
|
554
565
|
}
|
|
555
566
|
|
|
556
|
-
.light {
|
|
567
|
+
:where(.light) {
|
|
557
568
|
/* Light keeps opaque hover plates: a translucent text-mix would vanish on a
|
|
558
569
|
white menu. Pinned 0.3.0-prototype literals — the package has no hover-surface
|
|
559
570
|
roles yet, so these can't move onto tokens the way --menu-bg did. */
|
|
@@ -593,6 +604,15 @@
|
|
|
593
604
|
transition-timing-function: var(--motion-easing-standard);
|
|
594
605
|
}
|
|
595
606
|
|
|
607
|
+
/* === Layout === */
|
|
608
|
+
/* Backs the <PageColumn> primitive: the reading column, capped and centred in the well. A real class
|
|
609
|
+
rather than a Tailwind arbitrary utility, which the content scanner can drop for a newly-used
|
|
610
|
+
class. Horizontal padding is deliberately absent — AppShell owns the inset. */
|
|
611
|
+
.page-column {
|
|
612
|
+
max-width: 780px;
|
|
613
|
+
margin-inline: auto;
|
|
614
|
+
}
|
|
615
|
+
|
|
596
616
|
/* === Animation layer (tw-animate-css, compiled) — see scripts/build-styles.mjs === */
|
|
597
617
|
/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */
|
|
598
618
|
@layer properties;
|
|
@@ -935,3 +955,88 @@
|
|
|
935
955
|
}
|
|
936
956
|
}
|
|
937
957
|
}
|
|
958
|
+
|
|
959
|
+
/* === Tailwind v4 theme bridge — generated by scripts/build-styles.mjs === */
|
|
960
|
+
/* Colour utilities exist in v4 only for names in the `@theme` namespace; the deprecated
|
|
961
|
+
--color-* aliases above are :root properties, which is not the same thing. `inline` so a
|
|
962
|
+
utility substitutes the token at the element it paints rather than freezing it on :root,
|
|
963
|
+
which is what keeps a `.light` scope inside the page working. Permanent, and inert on
|
|
964
|
+
Tailwind 3. */
|
|
965
|
+
@theme inline {
|
|
966
|
+
--color-bg-brand: var(--bg-brand);
|
|
967
|
+
--color-bg-brand-bright: var(--bg-brand-bright);
|
|
968
|
+
--color-bg-brand-bright-hover: var(--bg-brand-bright-hover);
|
|
969
|
+
--color-bg-brand-hover: var(--bg-brand-hover);
|
|
970
|
+
--color-bg-brand-subtle: var(--bg-brand-subtle);
|
|
971
|
+
--color-bg-danger: var(--bg-danger);
|
|
972
|
+
--color-bg-danger-a90: var(--bg-danger-a90);
|
|
973
|
+
--color-bg-danger-subtle: var(--bg-danger-subtle);
|
|
974
|
+
--color-bg-elevated: var(--bg-elevated);
|
|
975
|
+
--color-bg-overlay: var(--bg-overlay);
|
|
976
|
+
--color-bg-primary: var(--bg-primary);
|
|
977
|
+
--color-bg-rose-subtle: var(--bg-rose-subtle);
|
|
978
|
+
--color-bg-secondary: var(--bg-secondary);
|
|
979
|
+
--color-bg-secondary-a50: var(--bg-secondary-a50);
|
|
980
|
+
--color-bg-secondary-a80: var(--bg-secondary-a80);
|
|
981
|
+
--color-bg-selected: var(--bg-selected);
|
|
982
|
+
--color-bg-success: var(--bg-success);
|
|
983
|
+
--color-bg-success-bright: var(--bg-success-bright);
|
|
984
|
+
--color-bg-success-subtle: var(--bg-success-subtle);
|
|
985
|
+
--color-bg-sunken: var(--bg-sunken);
|
|
986
|
+
--color-bg-surface: var(--bg-surface);
|
|
987
|
+
--color-bg-teal-subtle: var(--bg-teal-subtle);
|
|
988
|
+
--color-bg-violet-subtle: var(--bg-violet-subtle);
|
|
989
|
+
--color-bg-warning: var(--bg-warning);
|
|
990
|
+
--color-bg-warning-subtle: var(--bg-warning-subtle);
|
|
991
|
+
--color-border-brand: var(--border-brand);
|
|
992
|
+
--color-border-danger: var(--border-danger);
|
|
993
|
+
--color-border-default: var(--border-default);
|
|
994
|
+
--color-border-focus: var(--border-focus);
|
|
995
|
+
--color-border-selected: var(--border-selected);
|
|
996
|
+
--color-border-strong: var(--border-strong);
|
|
997
|
+
--color-border-subtle: var(--border-subtle);
|
|
998
|
+
--color-border-success: var(--border-success);
|
|
999
|
+
--color-border-warning: var(--border-warning);
|
|
1000
|
+
--color-field-bg: var(--field-bg);
|
|
1001
|
+
--color-field-bg-focus: var(--field-bg-focus);
|
|
1002
|
+
--color-field-bg-hover: var(--field-bg-hover);
|
|
1003
|
+
--color-field-bg-valid: var(--field-bg-valid);
|
|
1004
|
+
--color-field-border: var(--field-border);
|
|
1005
|
+
--color-field-border-error: var(--field-border-error);
|
|
1006
|
+
--color-field-border-filled: var(--field-border-filled);
|
|
1007
|
+
--color-field-border-focus: var(--field-border-focus);
|
|
1008
|
+
--color-field-border-hover: var(--field-border-hover);
|
|
1009
|
+
--color-field-border-success: var(--field-border-success);
|
|
1010
|
+
--color-field-ring-error: var(--field-ring-error);
|
|
1011
|
+
--color-field-ring-focus: var(--field-ring-focus);
|
|
1012
|
+
--color-field-ring-success: var(--field-ring-success);
|
|
1013
|
+
--color-icon-brand: var(--icon-brand);
|
|
1014
|
+
--color-icon-danger: var(--icon-danger);
|
|
1015
|
+
--color-icon-disabled: var(--icon-disabled);
|
|
1016
|
+
--color-icon-primary: var(--icon-primary);
|
|
1017
|
+
--color-icon-secondary: var(--icon-secondary);
|
|
1018
|
+
--color-icon-success: var(--icon-success);
|
|
1019
|
+
--color-icon-warning: var(--icon-warning);
|
|
1020
|
+
--color-overlay-backdrop: var(--overlay-backdrop);
|
|
1021
|
+
--color-overlay-modal-bg: var(--overlay-modal-bg);
|
|
1022
|
+
--color-overlay-scrim: var(--overlay-scrim);
|
|
1023
|
+
--color-text-brand: var(--text-brand);
|
|
1024
|
+
--color-text-danger: var(--text-danger);
|
|
1025
|
+
--color-text-disabled: var(--text-disabled);
|
|
1026
|
+
--color-text-inverse: var(--text-inverse);
|
|
1027
|
+
--color-text-link: var(--text-link);
|
|
1028
|
+
--color-text-link-hover: var(--text-link-hover);
|
|
1029
|
+
--color-text-on-brand: var(--text-on-brand);
|
|
1030
|
+
--color-text-on-danger: var(--text-on-danger);
|
|
1031
|
+
--color-text-on-success: var(--text-on-success);
|
|
1032
|
+
--color-text-on-success-bright: var(--text-on-success-bright);
|
|
1033
|
+
--color-text-on-warning: var(--text-on-warning);
|
|
1034
|
+
--color-text-primary: var(--text-primary);
|
|
1035
|
+
--color-text-rose: var(--text-rose);
|
|
1036
|
+
--color-text-secondary: var(--text-secondary);
|
|
1037
|
+
--color-text-success: var(--text-success);
|
|
1038
|
+
--color-text-teal: var(--text-teal);
|
|
1039
|
+
--color-text-tertiary: var(--text-tertiary);
|
|
1040
|
+
--color-text-violet: var(--text-violet);
|
|
1041
|
+
--color-text-warning: var(--text-warning);
|
|
1042
|
+
}
|
package/dist/styles.css
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* === @lessly/ui styles — generated by scripts/build-styles.mjs === */
|
|
2
2
|
/* @lessly/tokens theme (composite .text-<style> classes stripped) + deprecated
|
|
3
|
-
--color-* aliases + ui pieces + animation layer */
|
|
3
|
+
--color-* aliases + ui pieces + animation layer + v4 @theme bridge */
|
|
4
4
|
|
|
5
5
|
/*
|
|
6
6
|
* Auto-generated by tokens/build.js — do not edit manually.
|
|
@@ -572,6 +572,17 @@
|
|
|
572
572
|
--spacing: 0.25rem;
|
|
573
573
|
}
|
|
574
574
|
:root {
|
|
575
|
+
/* === Translucent tints the kit paints (#701) === */
|
|
576
|
+
/* A semantic token is a whole colour with no `<alpha-value>` placeholder, so `bg-bg-secondary/50`
|
|
577
|
+
compiles to nothing on Tailwind 3 while Tailwind 4 answers it with color-mix. These are the
|
|
578
|
+
three alphas the kit writes, as variables the preset maps a colour name onto so both majors
|
|
579
|
+
and both consumption paths resolve them. Like --hov-bg below, the inner var() resolves at the
|
|
580
|
+
element that paints, so `.light` needs no override. Delete each the release @lessly/tokens
|
|
581
|
+
publishes its semantic colours with an `<alpha-value>` placeholder. */
|
|
582
|
+
--bg-secondary-a50: color-mix(in oklab, var(--bg-secondary) 50%, transparent);
|
|
583
|
+
--bg-secondary-a80: color-mix(in oklab, var(--bg-secondary) 80%, transparent);
|
|
584
|
+
--bg-danger-a90: color-mix(in oklab, var(--bg-danger) 90%, transparent);
|
|
585
|
+
|
|
575
586
|
/* === Nav / menu surfaces (0.3.0 sidebar) === */
|
|
576
587
|
/* The floating surface sits on the package's overlay pair: --menu-bg on
|
|
577
588
|
--bg-overlay, --menu-shadow on --shadow-overlay. theme.css re-resolves both
|
|
@@ -640,6 +651,15 @@
|
|
|
640
651
|
transition-timing-function: var(--motion-easing-standard);
|
|
641
652
|
}
|
|
642
653
|
|
|
654
|
+
/* === Layout === */
|
|
655
|
+
/* Backs the <PageColumn> primitive: the reading column, capped and centred in the well. A real class
|
|
656
|
+
rather than a Tailwind arbitrary utility, which the content scanner can drop for a newly-used
|
|
657
|
+
class. Horizontal padding is deliberately absent — AppShell owns the inset. */
|
|
658
|
+
.page-column {
|
|
659
|
+
max-width: 780px;
|
|
660
|
+
margin-inline: auto;
|
|
661
|
+
}
|
|
662
|
+
|
|
643
663
|
/* === Animation layer (tw-animate-css, compiled) — see scripts/build-styles.mjs === */
|
|
644
664
|
/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */
|
|
645
665
|
@layer properties;
|
|
@@ -982,3 +1002,88 @@
|
|
|
982
1002
|
}
|
|
983
1003
|
}
|
|
984
1004
|
}
|
|
1005
|
+
|
|
1006
|
+
/* === Tailwind v4 theme bridge — generated by scripts/build-styles.mjs === */
|
|
1007
|
+
/* Colour utilities exist in v4 only for names in the `@theme` namespace; the deprecated
|
|
1008
|
+
--color-* aliases above are :root properties, which is not the same thing. `inline` so a
|
|
1009
|
+
utility substitutes the token at the element it paints rather than freezing it on :root,
|
|
1010
|
+
which is what keeps a `.light` scope inside the page working. Permanent, and inert on
|
|
1011
|
+
Tailwind 3. */
|
|
1012
|
+
@theme inline {
|
|
1013
|
+
--color-bg-brand: var(--bg-brand);
|
|
1014
|
+
--color-bg-brand-bright: var(--bg-brand-bright);
|
|
1015
|
+
--color-bg-brand-bright-hover: var(--bg-brand-bright-hover);
|
|
1016
|
+
--color-bg-brand-hover: var(--bg-brand-hover);
|
|
1017
|
+
--color-bg-brand-subtle: var(--bg-brand-subtle);
|
|
1018
|
+
--color-bg-danger: var(--bg-danger);
|
|
1019
|
+
--color-bg-danger-a90: var(--bg-danger-a90);
|
|
1020
|
+
--color-bg-danger-subtle: var(--bg-danger-subtle);
|
|
1021
|
+
--color-bg-elevated: var(--bg-elevated);
|
|
1022
|
+
--color-bg-overlay: var(--bg-overlay);
|
|
1023
|
+
--color-bg-primary: var(--bg-primary);
|
|
1024
|
+
--color-bg-rose-subtle: var(--bg-rose-subtle);
|
|
1025
|
+
--color-bg-secondary: var(--bg-secondary);
|
|
1026
|
+
--color-bg-secondary-a50: var(--bg-secondary-a50);
|
|
1027
|
+
--color-bg-secondary-a80: var(--bg-secondary-a80);
|
|
1028
|
+
--color-bg-selected: var(--bg-selected);
|
|
1029
|
+
--color-bg-success: var(--bg-success);
|
|
1030
|
+
--color-bg-success-bright: var(--bg-success-bright);
|
|
1031
|
+
--color-bg-success-subtle: var(--bg-success-subtle);
|
|
1032
|
+
--color-bg-sunken: var(--bg-sunken);
|
|
1033
|
+
--color-bg-surface: var(--bg-surface);
|
|
1034
|
+
--color-bg-teal-subtle: var(--bg-teal-subtle);
|
|
1035
|
+
--color-bg-violet-subtle: var(--bg-violet-subtle);
|
|
1036
|
+
--color-bg-warning: var(--bg-warning);
|
|
1037
|
+
--color-bg-warning-subtle: var(--bg-warning-subtle);
|
|
1038
|
+
--color-border-brand: var(--border-brand);
|
|
1039
|
+
--color-border-danger: var(--border-danger);
|
|
1040
|
+
--color-border-default: var(--border-default);
|
|
1041
|
+
--color-border-focus: var(--border-focus);
|
|
1042
|
+
--color-border-selected: var(--border-selected);
|
|
1043
|
+
--color-border-strong: var(--border-strong);
|
|
1044
|
+
--color-border-subtle: var(--border-subtle);
|
|
1045
|
+
--color-border-success: var(--border-success);
|
|
1046
|
+
--color-border-warning: var(--border-warning);
|
|
1047
|
+
--color-field-bg: var(--field-bg);
|
|
1048
|
+
--color-field-bg-focus: var(--field-bg-focus);
|
|
1049
|
+
--color-field-bg-hover: var(--field-bg-hover);
|
|
1050
|
+
--color-field-bg-valid: var(--field-bg-valid);
|
|
1051
|
+
--color-field-border: var(--field-border);
|
|
1052
|
+
--color-field-border-error: var(--field-border-error);
|
|
1053
|
+
--color-field-border-filled: var(--field-border-filled);
|
|
1054
|
+
--color-field-border-focus: var(--field-border-focus);
|
|
1055
|
+
--color-field-border-hover: var(--field-border-hover);
|
|
1056
|
+
--color-field-border-success: var(--field-border-success);
|
|
1057
|
+
--color-field-ring-error: var(--field-ring-error);
|
|
1058
|
+
--color-field-ring-focus: var(--field-ring-focus);
|
|
1059
|
+
--color-field-ring-success: var(--field-ring-success);
|
|
1060
|
+
--color-icon-brand: var(--icon-brand);
|
|
1061
|
+
--color-icon-danger: var(--icon-danger);
|
|
1062
|
+
--color-icon-disabled: var(--icon-disabled);
|
|
1063
|
+
--color-icon-primary: var(--icon-primary);
|
|
1064
|
+
--color-icon-secondary: var(--icon-secondary);
|
|
1065
|
+
--color-icon-success: var(--icon-success);
|
|
1066
|
+
--color-icon-warning: var(--icon-warning);
|
|
1067
|
+
--color-overlay-backdrop: var(--overlay-backdrop);
|
|
1068
|
+
--color-overlay-modal-bg: var(--overlay-modal-bg);
|
|
1069
|
+
--color-overlay-scrim: var(--overlay-scrim);
|
|
1070
|
+
--color-text-brand: var(--text-brand);
|
|
1071
|
+
--color-text-danger: var(--text-danger);
|
|
1072
|
+
--color-text-disabled: var(--text-disabled);
|
|
1073
|
+
--color-text-inverse: var(--text-inverse);
|
|
1074
|
+
--color-text-link: var(--text-link);
|
|
1075
|
+
--color-text-link-hover: var(--text-link-hover);
|
|
1076
|
+
--color-text-on-brand: var(--text-on-brand);
|
|
1077
|
+
--color-text-on-danger: var(--text-on-danger);
|
|
1078
|
+
--color-text-on-success: var(--text-on-success);
|
|
1079
|
+
--color-text-on-success-bright: var(--text-on-success-bright);
|
|
1080
|
+
--color-text-on-warning: var(--text-on-warning);
|
|
1081
|
+
--color-text-primary: var(--text-primary);
|
|
1082
|
+
--color-text-rose: var(--text-rose);
|
|
1083
|
+
--color-text-secondary: var(--text-secondary);
|
|
1084
|
+
--color-text-success: var(--text-success);
|
|
1085
|
+
--color-text-teal: var(--text-teal);
|
|
1086
|
+
--color-text-tertiary: var(--text-tertiary);
|
|
1087
|
+
--color-text-violet: var(--text-violet);
|
|
1088
|
+
--color-text-warning: var(--text-warning);
|
|
1089
|
+
}
|