@valentinkolb/cloud 0.4.0 → 0.5.1
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/package.json +18 -6
- package/scripts/preload.ts +78 -23
- package/src/_internal/define-app.ts +53 -46
- package/src/api/accounts-entities.ts +4 -0
- package/src/api/admin-core-settings.ts +98 -0
- package/src/api/announcements.ts +131 -0
- package/src/api/auth/schemas.ts +24 -0
- package/src/api/auth.ts +116 -13
- package/src/api/index.ts +7 -2
- package/src/api/me.ts +203 -14
- package/src/api/search/schemas.ts +1 -0
- package/src/api/search.ts +62 -8
- package/src/config/ssr.ts +2 -9
- package/src/contracts/announcements.test.ts +37 -0
- package/src/contracts/announcements.ts +121 -0
- package/src/contracts/app.ts +2 -0
- package/src/contracts/index.ts +3 -2
- package/src/contracts/registry.ts +2 -0
- package/src/contracts/shared.ts +108 -1
- package/src/desktop/index.ts +704 -0
- package/src/desktop/solid.tsx +938 -0
- package/src/server/api/index.ts +1 -1
- package/src/server/api/respond.ts +50 -10
- package/src/server/index.ts +44 -38
- package/src/server/middleware/auth.ts +98 -9
- package/src/server/middleware/index.ts +2 -1
- package/src/server/middleware/settings.ts +26 -0
- package/src/server/services/access.test.ts +197 -0
- package/src/server/services/access.ts +254 -6
- package/src/server/services/index.ts +14 -11
- package/src/server/services/pagination.ts +22 -0
- package/src/server/time.ts +45 -0
- package/src/services/account-lifecycle/index.ts +142 -18
- package/src/services/accounts/app.ts +658 -170
- package/src/services/accounts/authz.test.ts +77 -0
- package/src/services/accounts/authz.ts +22 -0
- package/src/services/accounts/entities.ts +84 -5
- package/src/services/accounts/groups.ts +30 -24
- package/src/services/accounts/model.test.ts +30 -0
- package/src/services/accounts/switching.test.ts +14 -0
- package/src/services/accounts/switching.ts +15 -6
- package/src/services/accounts/users.ts +75 -52
- package/src/services/announcements/index.test.ts +32 -0
- package/src/services/announcements/index.ts +224 -0
- package/src/services/audit/index.test.ts +84 -0
- package/src/services/audit/index.ts +431 -0
- package/src/services/auth-flows/index.ts +9 -2
- package/src/services/auth-flows/ipa.ts +47 -7
- package/src/services/auth-flows/magic-link.ts +92 -20
- package/src/services/auth-flows/password-reset.ts +284 -0
- package/src/services/auth-flows/proxy-return.test.ts +24 -0
- package/src/services/auth-flows/proxy-return.ts +49 -0
- package/src/services/gateway.ts +162 -0
- package/src/services/index.ts +44 -2
- package/src/services/ipa/effective-groups.test.ts +33 -0
- package/src/services/ipa/effective-groups.ts +70 -0
- package/src/services/ipa/profile.ts +45 -3
- package/src/services/ipa/search.ts +3 -5
- package/src/services/ipa/service-account.ts +15 -0
- package/src/services/ipa/sync-planning.test.ts +32 -0
- package/src/services/ipa/sync-planning.ts +22 -0
- package/src/services/ipa/sync.ts +110 -38
- package/src/services/notifications/index.ts +82 -11
- package/src/services/oauth-tokens.ts +104 -0
- package/src/services/postgres.ts +21 -6
- package/src/services/providers/local/auth.test.ts +22 -0
- package/src/services/providers/local/auth.ts +46 -3
- package/src/services/secrets.ts +10 -0
- package/src/services/service-account-credentials.test.ts +210 -0
- package/src/services/service-account-credentials.ts +715 -0
- package/src/services/service-accounts.ts +188 -0
- package/src/services/session/index.ts +7 -8
- package/src/services/settings/app.ts +4 -20
- package/src/services/settings/defaults.ts +79 -22
- package/src/services/settings/store.ts +47 -0
- package/src/services/weather/forecast.ts +40 -7
- package/src/services/webauthn.test.ts +36 -0
- package/src/services/webauthn.ts +384 -0
- package/src/shared/icons.ts +391 -100
- package/src/shared/index.ts +7 -0
- package/src/shared/markdown/extensions/code.ts +38 -1
- package/src/shared/markdown/extensions/images.ts +39 -3
- package/src/shared/markdown/extensions/info-blocks.ts +5 -5
- package/src/shared/markdown/extensions/mark.ts +48 -0
- package/src/shared/markdown/extensions/sub-sup.ts +60 -0
- package/src/shared/markdown/extensions/tables.ts +79 -58
- package/src/shared/markdown/formula.test.ts +1089 -0
- package/src/shared/markdown/formula.ts +1187 -0
- package/src/shared/markdown/index.ts +76 -2
- package/src/shared/mock-cover.ts +130 -0
- package/src/shared/redirect.test.ts +58 -0
- package/src/shared/redirect.ts +56 -0
- package/src/shared/theme.test.ts +24 -0
- package/src/shared/theme.ts +68 -0
- package/src/shared/time.ts +13 -0
- package/src/ssr/AdminLayout.tsx +7 -3
- package/src/ssr/AdminSidebar.tsx +115 -49
- package/src/ssr/AppLaunchpad.island.tsx +176 -0
- package/src/ssr/Footer.island.tsx +3 -8
- package/src/ssr/GlobalAnnouncements.island.tsx +141 -0
- package/src/ssr/GlobalSearchDialog.tsx +545 -117
- package/src/ssr/HotkeysHelpRail.island.tsx +3 -70
- package/src/ssr/Layout.tsx +74 -66
- package/src/ssr/LayoutBreadcrumbs.island.tsx +44 -0
- package/src/ssr/LayoutHelp.tsx +266 -0
- package/src/ssr/NavMenu.island.tsx +0 -39
- package/src/ssr/ThemeToggleRail.island.tsx +3 -3
- package/src/ssr/TimezoneCookie.island.tsx +23 -0
- package/src/ssr/islands/index.ts +13 -0
- package/src/styles/base-popover.css +5 -2
- package/src/styles/effects.css +87 -6
- package/src/styles/global.css +146 -9
- package/src/styles/input.css +3 -1
- package/src/styles/utilities-buttons.css +133 -27
- package/src/styles/utilities-code-display.css +67 -0
- package/src/styles/utilities-completion.css +223 -0
- package/src/styles/utilities-detail.css +73 -0
- package/src/styles/utilities-feedback.css +16 -15
- package/src/styles/utilities-layout.css +42 -2
- package/src/styles/utilities-markdown-editor.css +472 -0
- package/src/styles/utilities-navigation.css +63 -8
- package/src/styles/utilities-script.css +84 -0
- package/src/styles/utilities-table-tile.css +229 -0
- package/src/types/ambient.d.ts +9 -0
- package/src/ui/completion/behaviors.test.ts +95 -0
- package/src/ui/completion/behaviors.ts +205 -0
- package/src/ui/completion/engine.ts +368 -0
- package/src/ui/completion/index.ts +40 -0
- package/src/ui/completion/overlay.ts +92 -0
- package/src/ui/dialog-core.ts +173 -45
- package/src/ui/filter/FilterChip.tsx +42 -40
- package/src/ui/index.ts +11 -12
- package/src/ui/input/AutocompleteEditor.tsx +656 -0
- package/src/ui/input/CheckboxCard.tsx +91 -0
- package/src/ui/input/Combobox.tsx +375 -0
- package/src/ui/input/DatePicker.tsx +846 -0
- package/src/ui/input/DateTimeInput.tsx +29 -4
- package/src/ui/input/FileDropzone.tsx +116 -0
- package/src/ui/input/IconInput.tsx +116 -0
- package/src/ui/input/ImageInput.tsx +19 -2
- package/src/ui/input/MultiSelectInput.tsx +448 -0
- package/src/ui/input/NumberInput.tsx +417 -61
- package/src/ui/input/SegmentedControl.tsx +2 -2
- package/src/ui/input/Select.tsx +172 -10
- package/src/ui/input/Slider.tsx +3 -4
- package/src/ui/input/Switch.tsx +3 -2
- package/src/ui/input/TemplateEditor.tsx +212 -0
- package/src/ui/input/TextInput.tsx +144 -13
- package/src/ui/input/index.ts +53 -8
- package/src/ui/input/markdown/MarkdownEditor.tsx +774 -0
- package/src/ui/input/markdown/Toolbar.tsx +90 -0
- package/src/ui/input/markdown/actions.ts +233 -0
- package/src/ui/input/markdown/active-formats.ts +94 -0
- package/src/ui/input/markdown/behaviors.ts +193 -0
- package/src/ui/input/markdown/code-zone.ts +23 -0
- package/src/ui/input/markdown/highlight.ts +316 -0
- package/src/ui/layout.ts +22 -0
- package/src/ui/misc/AppOverview.tsx +105 -0
- package/src/ui/misc/AppWorkspace.tsx +607 -0
- package/src/ui/misc/Calendar.tsx +1291 -0
- package/src/ui/misc/Chart.tsx +162 -0
- package/src/ui/misc/CodeDisplay.tsx +54 -0
- package/src/ui/misc/ContextMenu.tsx +2 -2
- package/src/ui/misc/DataTable.tsx +269 -0
- package/src/ui/misc/DockWorkspace.tsx +425 -0
- package/src/ui/misc/Docs.tsx +153 -0
- package/src/ui/misc/Dropdown.tsx +2 -2
- package/src/ui/misc/EntitySearch.tsx +260 -129
- package/src/ui/misc/LinkCard.tsx +14 -2
- package/src/ui/misc/LogEntriesTable.tsx +34 -31
- package/src/ui/misc/Pagination.tsx +31 -12
- package/src/ui/misc/PanelDialog.tsx +109 -0
- package/src/ui/misc/Panes.tsx +873 -0
- package/src/ui/misc/PermissionEditor.tsx +358 -262
- package/src/ui/misc/Placeholder.tsx +40 -0
- package/src/ui/misc/ProgressBar.tsx +1 -1
- package/src/ui/misc/ResourceApiKeys.tsx +260 -0
- package/src/ui/misc/SettingsModal.tsx +150 -0
- package/src/ui/misc/StatCell.tsx +182 -40
- package/src/ui/misc/StatGrid.tsx +149 -0
- package/src/ui/misc/StructuredDataPreview.tsx +107 -0
- package/src/ui/misc/code-highlight.ts +213 -0
- package/src/ui/misc/index.ts +93 -12
- package/src/ui/prompts.tsx +362 -312
- package/src/ui/toast.ts +384 -0
- package/src/ui/widgets/Widget.tsx +12 -4
- package/src/ssr/MoreAppsDropdown.island.tsx +0 -61
- package/src/ui/ipa/GroupView.tsx +0 -36
- package/src/ui/ipa/LoginBtn.tsx +0 -16
- package/src/ui/ipa/UserView.tsx +0 -58
- package/src/ui/ipa/index.ts +0 -4
- package/src/ui/navigation.ts +0 -32
- package/src/ui/sidebar.tsx +0 -468
- /package/src/ui/{ipa → misc}/Avatar.tsx +0 -0
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
import type { Role } from "../contracts/shared";
|
|
2
2
|
import { Dropdown } from "../ui";
|
|
3
3
|
|
|
4
|
-
type MobileAppLink = {
|
|
5
|
-
href: string;
|
|
6
|
-
iconClass: string;
|
|
7
|
-
label: string;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
4
|
/**
|
|
11
5
|
* Minimal user projection for the nav menu — covers exactly what's rendered
|
|
12
6
|
* (initials, display name, uid, profile flag, admin role check). Avoids
|
|
@@ -22,11 +16,8 @@ export type NavMenuUser = {
|
|
|
22
16
|
|
|
23
17
|
type NavMenuProps = {
|
|
24
18
|
user?: NavMenuUser;
|
|
25
|
-
mobileApps: MobileAppLink[];
|
|
26
19
|
};
|
|
27
20
|
|
|
28
|
-
const hasRole = (roles: Role[], ...required: Role[]) => required.some((role) => roles.includes(role));
|
|
29
|
-
|
|
30
21
|
/** Navigation dropdown menu - always visible, adapts to auth state. */
|
|
31
22
|
export default function NavMenu(props: NavMenuProps) {
|
|
32
23
|
const getElements = () => [
|
|
@@ -61,36 +52,6 @@ export default function NavMenu(props: NavMenuProps) {
|
|
|
61
52
|
href: "/auth/login",
|
|
62
53
|
},
|
|
63
54
|
]),
|
|
64
|
-
// Section: Apps (mobile only — on desktop, tabs/rail handle this)
|
|
65
|
-
...(props.user
|
|
66
|
-
? [
|
|
67
|
-
{
|
|
68
|
-
element: (
|
|
69
|
-
<div class="md:hidden">
|
|
70
|
-
<div class="px-4 pt-3 pb-1 text-xs uppercase tracking-wider font-medium text-zinc-500">Apps</div>
|
|
71
|
-
{props.mobileApps.map((app) => (
|
|
72
|
-
<a
|
|
73
|
-
href={app.href}
|
|
74
|
-
class="flex w-full items-center gap-3 px-4 py-2 text-sm transition-colors hover:bg-white/30 dark:hover:bg-white/10 text-zinc-700 dark:text-zinc-300"
|
|
75
|
-
>
|
|
76
|
-
<i class={app.iconClass} />
|
|
77
|
-
<span>{app.label}</span>
|
|
78
|
-
</a>
|
|
79
|
-
))}
|
|
80
|
-
{hasRole(props.user.roles, "admin") && (
|
|
81
|
-
<a
|
|
82
|
-
href="/admin"
|
|
83
|
-
class="flex w-full items-center gap-3 px-4 py-2 text-sm transition-colors hover:bg-white/30 dark:hover:bg-white/10 text-zinc-700 dark:text-zinc-300"
|
|
84
|
-
>
|
|
85
|
-
<i class="ti ti-shield-cog" />
|
|
86
|
-
<span>Admin</span>
|
|
87
|
-
</a>
|
|
88
|
-
)}
|
|
89
|
-
</div>
|
|
90
|
-
),
|
|
91
|
-
},
|
|
92
|
-
]
|
|
93
|
-
: []),
|
|
94
55
|
];
|
|
95
56
|
|
|
96
57
|
return (
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { createSignal } from "solid-js";
|
|
2
|
-
import {
|
|
2
|
+
import { getCurrentThemePreference, setThemePreference, type CloudTheme } from "../shared/theme";
|
|
3
3
|
|
|
4
4
|
/** Theme toggle button for the desktop rail navigation. */
|
|
5
5
|
export default function ThemeToggleRail() {
|
|
6
|
-
const [mode, setMode] = createSignal<
|
|
6
|
+
const [mode, setMode] = createSignal<CloudTheme>(getCurrentThemePreference());
|
|
7
7
|
|
|
8
8
|
const toggleTheme = () => {
|
|
9
|
-
setMode(
|
|
9
|
+
setMode(setThemePreference(mode() === "dark" ? "light" : "dark"));
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
return (
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { cookies } from "@valentinkolb/stdlib/browser";
|
|
2
|
+
import { onMount } from "solid-js";
|
|
3
|
+
import { TIMEZONE_COOKIE } from "../shared/time";
|
|
4
|
+
|
|
5
|
+
export default function TimezoneCookie() {
|
|
6
|
+
onMount(() => {
|
|
7
|
+
const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
8
|
+
const current = cookies.readCookie(TIMEZONE_COOKIE);
|
|
9
|
+
if (timeZone && current !== timeZone) {
|
|
10
|
+
cookies.writeCookie(TIMEZONE_COOKIE, timeZone);
|
|
11
|
+
try {
|
|
12
|
+
if (sessionStorage.getItem("cloud.timezone.reload") !== timeZone) {
|
|
13
|
+
sessionStorage.setItem("cloud.timezone.reload", timeZone);
|
|
14
|
+
window.location.reload();
|
|
15
|
+
}
|
|
16
|
+
} catch {
|
|
17
|
+
// Cookie persistence still succeeds; the next navigation will render with the browser timezone.
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
return null;
|
|
23
|
+
}
|
package/src/ssr/islands/index.ts
CHANGED
|
@@ -1 +1,14 @@
|
|
|
1
1
|
export { default as SearchBar } from "./SearchBar.island";
|
|
2
|
+
import { LayoutHelp } from "../LayoutHelp";
|
|
3
|
+
import { AppLaunchpadButton, AppLaunchpadProvider } from "../AppLaunchpad.island";
|
|
4
|
+
|
|
5
|
+
export { AppLaunchpadButton, AppLaunchpadProvider, openAppLaunchpad, setAppLaunchpadContext } from "../AppLaunchpad.island";
|
|
6
|
+
export type { AppLaunchpadApp, AppLaunchpadLegalLink } from "../AppLaunchpad.island";
|
|
7
|
+
export { LayoutHelp, openLayoutHelpDialog } from "../LayoutHelp";
|
|
8
|
+
export type { LayoutHelpProps, LayoutHelpTab } from "../LayoutHelp";
|
|
9
|
+
|
|
10
|
+
export const Layout = {
|
|
11
|
+
Help: LayoutHelp,
|
|
12
|
+
AppLaunchpadButton,
|
|
13
|
+
AppLaunchpadProvider,
|
|
14
|
+
};
|
|
@@ -4,8 +4,11 @@ solid-island {
|
|
|
4
4
|
display: contents;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
/* Popover positioning
|
|
8
|
-
|
|
7
|
+
/* Popover positioning. Strip the UA-default white box for popovers
|
|
8
|
+
that don't opt into one of our paper-ish surfaces (`.paper`,
|
|
9
|
+
`.popup`) — those are typically tooltips / soft-hint popovers that
|
|
10
|
+
provide their own chrome. */
|
|
11
|
+
[popover]:not(.paper):not(.popup) {
|
|
9
12
|
background: transparent;
|
|
10
13
|
border: none;
|
|
11
14
|
}
|
package/src/styles/effects.css
CHANGED
|
@@ -45,12 +45,7 @@
|
|
|
45
45
|
content: "";
|
|
46
46
|
position: absolute;
|
|
47
47
|
inset: -50%;
|
|
48
|
-
background: linear-gradient(
|
|
49
|
-
115deg,
|
|
50
|
-
transparent 0%,
|
|
51
|
-
rgba(255, 255, 255, 0.25) 50%,
|
|
52
|
-
transparent 100%
|
|
53
|
-
);
|
|
48
|
+
background: linear-gradient(115deg, transparent 0%, rgba(255, 255, 255, 0.25) 50%, transparent 100%);
|
|
54
49
|
animation: shimmer 5s ease-in-out infinite;
|
|
55
50
|
}
|
|
56
51
|
}
|
|
@@ -63,3 +58,89 @@
|
|
|
63
58
|
transform: translateX(100%);
|
|
64
59
|
}
|
|
65
60
|
}
|
|
61
|
+
|
|
62
|
+
/* Dashboard launchpad panel. Scoped through :has() so the calmer backdrop only
|
|
63
|
+
applies to the dashboard app picker, not every bare dialog. */
|
|
64
|
+
dialog:has(.launchpad-panel)::backdrop {
|
|
65
|
+
background: rgb(0 0 0 / 0.45);
|
|
66
|
+
backdrop-filter: blur(8px);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.dark dialog:has(.launchpad-panel)::backdrop {
|
|
70
|
+
background: rgb(0 0 0 / 0.35);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.launchpad-panel {
|
|
74
|
+
background: rgb(255 255 255 / 0.96);
|
|
75
|
+
border: 1px solid rgb(228 228 231 / 0.82);
|
|
76
|
+
border-radius: 1.5rem;
|
|
77
|
+
box-shadow:
|
|
78
|
+
inset 0 1px 0 0 rgb(255 255 255 / 0.9),
|
|
79
|
+
0 28px 68px -42px rgb(24 24 27 / 0.48);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.dark .launchpad-panel {
|
|
83
|
+
background: linear-gradient(180deg, rgb(24 24 27 / 0.98), rgb(15 15 17 / 0.98));
|
|
84
|
+
border-color: rgb(255 255 255 / 0.13);
|
|
85
|
+
box-shadow:
|
|
86
|
+
inset 0 1px 0 0 rgb(255 255 255 / 0.08),
|
|
87
|
+
0 28px 68px -36px rgb(0 0 0 / 0.82);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/* Dashboard launchpad app icon. One app colour drives the glyph and graded rim;
|
|
91
|
+
the face stays clean so the tile feels crisp instead of plastic. */
|
|
92
|
+
.launchpad-panel .app-icon {
|
|
93
|
+
--icon-face: #ffffff;
|
|
94
|
+
--rim-top: color-mix(in oklab, var(--app-icon-color), white 34%);
|
|
95
|
+
--rim-bottom: color-mix(in oklab, var(--app-icon-color), black 12%);
|
|
96
|
+
--rim-top-hover: color-mix(in oklab, var(--app-icon-color), white 2%);
|
|
97
|
+
--rim-bottom-hover: color-mix(in oklab, var(--app-icon-color), black 30%);
|
|
98
|
+
--glyph: var(--app-icon-color);
|
|
99
|
+
--glyph-hover: var(--app-icon-color);
|
|
100
|
+
--drop: none;
|
|
101
|
+
|
|
102
|
+
background:
|
|
103
|
+
linear-gradient(var(--icon-face), var(--icon-face)) padding-box,
|
|
104
|
+
linear-gradient(180deg, var(--rim-top), var(--rim-bottom)) border-box;
|
|
105
|
+
border: 2.5px solid transparent;
|
|
106
|
+
box-shadow: var(--drop);
|
|
107
|
+
color: var(--glyph);
|
|
108
|
+
transition:
|
|
109
|
+
background 0.18s ease,
|
|
110
|
+
box-shadow 0.18s ease,
|
|
111
|
+
color 0.18s ease;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
@supports (color: oklch(from red l c h)) {
|
|
115
|
+
.launchpad-panel .app-icon {
|
|
116
|
+
--glyph: oklch(from var(--app-icon-color) min(l, 0.5) c h);
|
|
117
|
+
--glyph-hover: oklch(from var(--app-icon-color) min(l, 0.4) c h);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.dark .launchpad-panel .app-icon {
|
|
122
|
+
--icon-face: #202026;
|
|
123
|
+
--rim-top: color-mix(in oklab, var(--app-icon-color), white 30%);
|
|
124
|
+
--rim-bottom: color-mix(in oklab, var(--app-icon-color), black 24%);
|
|
125
|
+
--rim-top-hover: color-mix(in oklab, var(--app-icon-color), white 54%);
|
|
126
|
+
--rim-bottom-hover: color-mix(in oklab, var(--app-icon-color), white 6%);
|
|
127
|
+
--glyph: var(--app-icon-color);
|
|
128
|
+
--glyph-hover: color-mix(in oklab, var(--app-icon-color), white 32%);
|
|
129
|
+
--drop: 0 10px 20px -12px rgb(0 0 0 / 0.7);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
@supports (color: oklch(from red l c h)) {
|
|
133
|
+
.dark .launchpad-panel .app-icon {
|
|
134
|
+
--glyph: oklch(from var(--app-icon-color) max(l, 0.82) c h);
|
|
135
|
+
--glyph-hover: oklch(from var(--app-icon-color) max(l, 0.96) c h);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/* Hover changes only the icon tile, never the whole icon+label item. */
|
|
140
|
+
.launchpad-panel .group:hover > .app-icon,
|
|
141
|
+
.launchpad-panel .app-icon:hover {
|
|
142
|
+
background:
|
|
143
|
+
linear-gradient(var(--icon-face), var(--icon-face)) padding-box,
|
|
144
|
+
linear-gradient(180deg, var(--rim-top-hover), var(--rim-bottom-hover)) border-box;
|
|
145
|
+
color: var(--glyph-hover);
|
|
146
|
+
}
|
package/src/styles/global.css
CHANGED
|
@@ -10,12 +10,36 @@
|
|
|
10
10
|
@custom-variant light (html:not(.dark) &);
|
|
11
11
|
|
|
12
12
|
@import "@tabler/icons-webfont/dist/tabler-icons.css";
|
|
13
|
-
|
|
13
|
+
|
|
14
|
+
/* IBM Plex family — Sans for body, Mono for code, Condensed for badges/tags.
|
|
15
|
+
Per-weight imports keep the network payload predictable; we deliberately
|
|
16
|
+
skip the lighter weights (100–300) and italic-condensed since the design
|
|
17
|
+
system never uses them. */
|
|
18
|
+
@import "@fontsource/ibm-plex-sans/400.css";
|
|
19
|
+
@import "@fontsource/ibm-plex-sans/400-italic.css";
|
|
20
|
+
@import "@fontsource/ibm-plex-sans/500.css";
|
|
21
|
+
@import "@fontsource/ibm-plex-sans/600.css";
|
|
22
|
+
@import "@fontsource/ibm-plex-sans/700.css";
|
|
23
|
+
@import "@fontsource/ibm-plex-mono/400.css";
|
|
24
|
+
@import "@fontsource/ibm-plex-mono/400-italic.css";
|
|
25
|
+
@import "@fontsource/ibm-plex-mono/500.css";
|
|
26
|
+
@import "@fontsource/ibm-plex-mono/600.css";
|
|
27
|
+
@import "@fontsource/ibm-plex-sans-condensed/400.css";
|
|
28
|
+
@import "@fontsource/ibm-plex-sans-condensed/500.css";
|
|
29
|
+
@import "@fontsource/ibm-plex-sans-condensed/600.css";
|
|
30
|
+
@import "@fontsource/ibm-plex-sans-condensed/700.css";
|
|
31
|
+
|
|
14
32
|
@import "./tokens.css";
|
|
15
33
|
@import "./utilities-buttons.css";
|
|
16
34
|
@import "./utilities-layout.css";
|
|
17
35
|
@import "./utilities-navigation.css";
|
|
18
36
|
@import "./utilities-feedback.css";
|
|
37
|
+
@import "./utilities-detail.css";
|
|
38
|
+
@import "./utilities-table-tile.css";
|
|
39
|
+
@import "./utilities-script.css";
|
|
40
|
+
@import "./utilities-markdown-editor.css";
|
|
41
|
+
@import "./utilities-completion.css";
|
|
42
|
+
@import "./utilities-code-display.css";
|
|
19
43
|
@import "./base-popover.css";
|
|
20
44
|
@import "./effects.css";
|
|
21
45
|
@import "./input.css";
|
|
@@ -24,11 +48,34 @@
|
|
|
24
48
|
--color-dark: rgb(9 9 11);
|
|
25
49
|
--color-selection-bg: rgb(147 197 253 / 0.45);
|
|
26
50
|
--color-selection-fg: rgb(15 23 42);
|
|
51
|
+
|
|
52
|
+
/* Type system — IBM Plex family.
|
|
53
|
+
- Sans: default body / UI text (readable, neutral, slight personality)
|
|
54
|
+
- Mono: code, IDs, technical values (matches sans proportions)
|
|
55
|
+
- Condensed: badges, tags, dense labels where Sans is too wide
|
|
56
|
+
|
|
57
|
+
Tailwind 4 derives `font-sans` / `font-mono` / `font-condensed`
|
|
58
|
+
utilities from these tokens. CSS consumers can also reference them
|
|
59
|
+
via `var(--font-sans)` etc. (e.g. CodeMirror theme overrides). */
|
|
60
|
+
--font-sans: "IBM Plex Sans", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
61
|
+
--font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
62
|
+
--font-condensed: "IBM Plex Sans Condensed", "IBM Plex Sans", system-ui, sans-serif;
|
|
27
63
|
}
|
|
28
64
|
|
|
29
65
|
:root {
|
|
30
|
-
|
|
31
|
-
|
|
66
|
+
color-scheme: light;
|
|
67
|
+
/* Depth language (visual redesign). Inset bevel for in-flow surfaces (clip-safe),
|
|
68
|
+
recess for input wells, press for :active, float for PORTALED overlays only.
|
|
69
|
+
`--theme-shadow-elevated` flows the bevel through the token that `paper` and
|
|
70
|
+
the Layout header already consume, so they stay consistent. */
|
|
71
|
+
--theme-bevel-top: inset 0 1px 0 0 rgb(255 255 255 / 0.85);
|
|
72
|
+
--theme-bevel-bottom: inset 0 -1px 1px 0 rgb(0 0 0 / 0.05);
|
|
73
|
+
--theme-recess: inset 0 1px 2px rgb(0 0 0 / 0.08);
|
|
74
|
+
--theme-recess-sm: inset 0 1px 1px rgb(0 0 0 / 0.08);
|
|
75
|
+
--theme-press: inset 0 2px 4px rgb(0 0 0 / 0.19), inset 0 1px 1px rgb(0 0 0 / 0.1);
|
|
76
|
+
--theme-shadow-float: 0 12px 32px -10px rgb(0 0 0 / 0.22), 0 4px 10px -4px rgb(0 0 0 / 0.1);
|
|
77
|
+
--theme-shadow-elevated: var(--theme-bevel-top), var(--theme-bevel-bottom);
|
|
78
|
+
--theme-shadow-hover: var(--theme-bevel-top), var(--theme-bevel-bottom), 0 6px 16px -6px rgb(0 0 0 / 0.14);
|
|
32
79
|
--theme-input-py: 0.375rem;
|
|
33
80
|
--theme-input-px: 0.5rem;
|
|
34
81
|
--theme-list-active-border: none;
|
|
@@ -43,11 +90,12 @@
|
|
|
43
90
|
--theme-rail-item-active-border-r: none;
|
|
44
91
|
--theme-rail-item-inactive-border-r: none;
|
|
45
92
|
--theme-divider: 1px solid rgb(228 228 231);
|
|
93
|
+
--theme-focus-ring: inset 0 0 0 2px color-mix(in srgb, var(--color-blue-500) 45%, transparent);
|
|
46
94
|
}
|
|
47
95
|
|
|
48
96
|
* {
|
|
49
97
|
font-variant-ligatures: contextual;
|
|
50
|
-
font-family:
|
|
98
|
+
font-family: var(--font-sans);
|
|
51
99
|
scrollbar-width: thin;
|
|
52
100
|
scrollbar-color: rgb(161 161 170 / 0.4) transparent;
|
|
53
101
|
}
|
|
@@ -56,6 +104,84 @@
|
|
|
56
104
|
scrollbar-color: rgb(82 82 91 / 0.5) transparent;
|
|
57
105
|
}
|
|
58
106
|
|
|
107
|
+
.dark {
|
|
108
|
+
--theme-focus-ring: inset 0 0 0 2px color-mix(in srgb, var(--color-blue-400) 55%, transparent);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/* stdlib charts: make the SVG fill its wrapping element.
|
|
112
|
+
stdlib emits `<svg viewBox="0 0 W H">` without `width`/`height`
|
|
113
|
+
attributes, which would otherwise fall back to the browser's
|
|
114
|
+
replaced-element default (300×150) and either overflow tiny
|
|
115
|
+
containers or sit dwarfed inside wider ones. `display: block`
|
|
116
|
+
stops the inline-baseline gap; `width/height: 100%` lets the
|
|
117
|
+
container's CSS box drive the SVG size, and the `<Chart>`
|
|
118
|
+
wrapper passes the measured pixel dimensions back to stdlib so
|
|
119
|
+
the viewBox matches — no aspect distortion, no letterboxing. */
|
|
120
|
+
.stdlib-chart {
|
|
121
|
+
display: block;
|
|
122
|
+
width: 100%;
|
|
123
|
+
height: 100%;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
:root .stdlib-chart {
|
|
127
|
+
--stdlib-chart-c1: #14b8a6;
|
|
128
|
+
--stdlib-chart-c2: #f97316;
|
|
129
|
+
--stdlib-chart-c3: #8b5cf6;
|
|
130
|
+
--stdlib-chart-c4: #ec4899;
|
|
131
|
+
--stdlib-chart-c5: #22c55e;
|
|
132
|
+
--stdlib-chart-c6: #eab308;
|
|
133
|
+
--stdlib-chart-c7: #06b6d4;
|
|
134
|
+
--stdlib-chart-c8: #ef4444;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/* stdlib charts — dark-mode overrides.
|
|
138
|
+
|
|
139
|
+
stdlib's embedded <style> hardcodes a light-mode `color: #1f2937`
|
|
140
|
+
on .stdlib-chart and `stroke: white` on slice/point/outlier
|
|
141
|
+
separators. The hardcoded color leaves axis labels / tick text
|
|
142
|
+
unreadable on a dark background, and white slice strokes look
|
|
143
|
+
harsh against zinc-950. We override BOTH from outside the SVG
|
|
144
|
+
with higher specificity (parent `.dark` selector beats the
|
|
145
|
+
embedded one-class rule).
|
|
146
|
+
|
|
147
|
+
Why specificity matters: stdlib's <style> lives INSIDE the SVG,
|
|
148
|
+
so its rules are part of the document. Both rule sets have one
|
|
149
|
+
class selector each (`.stdlib-chart`), and the embedded one is
|
|
150
|
+
parsed AFTER global.css — without raising specificity here, the
|
|
151
|
+
embedded rule would win and dark mode would stay broken. The
|
|
152
|
+
`.dark` parent on `<html>` (set by the platform's theme toggle)
|
|
153
|
+
bumps these rules to two classes, beating stdlib's one-class
|
|
154
|
+
embedded defaults cleanly. */
|
|
155
|
+
.dark .stdlib-chart {
|
|
156
|
+
color: rgb(228 228 231); /* zinc-200 — readable on zinc-950 */
|
|
157
|
+
}
|
|
158
|
+
.dark .stdlib-chart .stdlib-chart-slice,
|
|
159
|
+
.dark .stdlib-chart .stdlib-chart-point,
|
|
160
|
+
.dark .stdlib-chart .stdlib-chart-box-outlier {
|
|
161
|
+
/* zinc-950 to match the dark page background, so slice / point
|
|
162
|
+
separators read as "gaps between segments" rather than visible
|
|
163
|
+
white lines against a dark surface. */
|
|
164
|
+
stroke: rgb(9 9 11);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/* stdlib charts — scientific data-viz refinement.
|
|
168
|
+
|
|
169
|
+
stdlib already renders the structure (gridlines, axes, ticks, flat
|
|
170
|
+
fills); the only thing missing for a precise "measurement" look is
|
|
171
|
+
the typography. Numeric axis ticks + bar values read as monospaced,
|
|
172
|
+
tabular figures so columns of numbers line up the way they do in a
|
|
173
|
+
plotting tool. Two-class selectors (`.stdlib-chart .stdlib-chart-…`)
|
|
174
|
+
beat stdlib's one-class embedded <style> the same way the dark-mode
|
|
175
|
+
overrides above do. font-family is otherwise unset by stdlib, so the
|
|
176
|
+
chart would inherit the app sans — we pin the numeric labels to the
|
|
177
|
+
platform mono stack (IBM Plex Mono via @fontsource). */
|
|
178
|
+
.stdlib-chart .stdlib-chart-tick-label,
|
|
179
|
+
.stdlib-chart .stdlib-chart-bar-value,
|
|
180
|
+
.stdlib-chart .stdlib-chart-axis-label {
|
|
181
|
+
font-family: var(--font-mono);
|
|
182
|
+
font-variant-numeric: tabular-nums;
|
|
183
|
+
}
|
|
184
|
+
|
|
59
185
|
*::-webkit-scrollbar {
|
|
60
186
|
width: 0.5rem;
|
|
61
187
|
height: 0.5rem;
|
|
@@ -89,20 +215,31 @@
|
|
|
89
215
|
background: transparent;
|
|
90
216
|
}
|
|
91
217
|
|
|
218
|
+
.multi-select-pill-strip {
|
|
219
|
+
scrollbar-width: thin;
|
|
220
|
+
}
|
|
221
|
+
|
|
92
222
|
body {
|
|
93
223
|
/* Explicit values — avoids @apply layer ordering issues with multiple CSS files */
|
|
94
224
|
background-color: rgb(250 250 250); /* zinc-50 */
|
|
95
|
-
color: rgb(24 24 27);
|
|
225
|
+
color: rgb(24 24 27); /* zinc-900 */
|
|
96
226
|
}
|
|
97
227
|
|
|
98
228
|
.dark body {
|
|
99
|
-
background-color: rgb(9 9 11);
|
|
100
|
-
color: rgb(244 244 245);
|
|
229
|
+
background-color: rgb(9 9 11); /* zinc-950 */
|
|
230
|
+
color: rgb(244 244 245); /* zinc-100 */
|
|
101
231
|
}
|
|
102
232
|
|
|
103
233
|
.dark {
|
|
104
|
-
|
|
105
|
-
--theme-
|
|
234
|
+
color-scheme: dark;
|
|
235
|
+
--theme-bevel-top: inset 0 1px 0 0 rgb(255 255 255 / 0.07);
|
|
236
|
+
--theme-bevel-bottom: inset 0 -1px 1px 0 rgb(0 0 0 / 0.4);
|
|
237
|
+
--theme-recess: inset 0 1px 2px rgb(0 0 0 / 0.45);
|
|
238
|
+
--theme-recess-sm: inset 0 1px 1px rgb(0 0 0 / 0.4);
|
|
239
|
+
--theme-press: inset 0 2px 4px rgb(0 0 0 / 0.5), inset 0 1px 1px rgb(0 0 0 / 0.3);
|
|
240
|
+
--theme-shadow-float: 0 14px 36px -10px rgb(0 0 0 / 0.6), 0 4px 12px -4px rgb(0 0 0 / 0.4);
|
|
241
|
+
--theme-shadow-elevated: var(--theme-bevel-top), var(--theme-bevel-bottom);
|
|
242
|
+
--theme-shadow-hover: var(--theme-bevel-top), var(--theme-bevel-bottom), 0 6px 18px -6px rgb(0 0 0 / 0.5);
|
|
106
243
|
--theme-list-active-bg: rgb(39 39 42);
|
|
107
244
|
--theme-list-hover-bg: rgb(30 30 33);
|
|
108
245
|
--theme-tab-active-bg: rgb(39 39 42);
|
package/src/styles/input.css
CHANGED
|
@@ -17,6 +17,7 @@ button[disabled],
|
|
|
17
17
|
/* Global Checkbox Styling */
|
|
18
18
|
input[type="checkbox"] {
|
|
19
19
|
@apply appearance-none w-4 h-4 bg-white dark:bg-black border border-zinc-300 dark:border-zinc-700 cursor-pointer transition-all duration-200 inline-flex items-center justify-center m-0 align-middle rounded;
|
|
20
|
+
box-shadow: var(--theme-recess-sm);
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
input[type="checkbox"]::before {
|
|
@@ -27,6 +28,7 @@ input[type="checkbox"]::before {
|
|
|
27
28
|
|
|
28
29
|
input[type="checkbox"]:checked {
|
|
29
30
|
@apply bg-blue-500 border-blue-500;
|
|
31
|
+
box-shadow: inset 0 1px 0 0 rgb(255 255 255 / 0.35);
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
input[type="checkbox"]:checked::before {
|
|
@@ -42,7 +44,7 @@ input[type="checkbox"]:focus {
|
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
input[type="checkbox"]:focus-visible {
|
|
45
|
-
@apply
|
|
47
|
+
@apply focus-ui;
|
|
46
48
|
}
|
|
47
49
|
|
|
48
50
|
input[type="checkbox"]:disabled {
|