@osdk/react-components 0.19.0-main-b5d7e7b9644f6f9d2b3771c6fafca28cd20a3cbb → 0.19.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/CHANGELOG.md +3 -11
- package/build/browser/object-table/EditableCell.module.css +2 -2
- package/build/browser/public/experimental/theme.js +19 -0
- package/build/browser/public/experimental/theme.js.map +1 -0
- package/build/browser/public/experimental.js +1 -0
- package/build/browser/public/experimental.js.map +1 -1
- package/build/browser/styles.css +10 -99
- package/build/browser/theme/OsdkThemeContext.js +19 -0
- package/build/browser/theme/OsdkThemeContext.js.map +1 -0
- package/build/browser/theme/OsdkThemeProvider.js +74 -0
- package/build/browser/theme/OsdkThemeProvider.js.map +1 -0
- package/build/browser/theme/types.js +2 -0
- package/build/browser/theme/types.js.map +1 -0
- package/build/browser/theme/useOsdkTheme.js +40 -0
- package/build/browser/theme/useOsdkTheme.js.map +1 -0
- package/build/browser/theme/useSystemTheme.js +45 -0
- package/build/browser/theme/useSystemTheme.js.map +1 -0
- package/build/browser/tokens/base-tokens/dark.css +8 -99
- package/build/browser/util/UserAgent.js +1 -1
- package/build/browser/util/UserAgent.js.map +1 -1
- package/build/cjs/chunk-2YA74OKB.cjs +86 -0
- package/build/cjs/chunk-2YA74OKB.cjs.map +1 -0
- package/build/cjs/{chunk-74XNR3YF.cjs → chunk-3OUALM3K.cjs} +4 -4
- package/build/cjs/{chunk-74XNR3YF.cjs.map → chunk-3OUALM3K.cjs.map} +1 -1
- package/build/cjs/chunk-3Y4W37E3.cjs +11 -0
- package/build/cjs/{chunk-G2AYUCKB.cjs.map → chunk-3Y4W37E3.cjs.map} +1 -1
- package/build/cjs/chunk-62DGPKOC.cjs +11 -0
- package/build/cjs/{chunk-6Z2CEPQP.cjs.map → chunk-62DGPKOC.cjs.map} +1 -1
- package/build/cjs/{chunk-BIPWKG5Q.cjs → chunk-6XRF4IAL.cjs} +4 -4
- package/build/cjs/{chunk-BIPWKG5Q.cjs.map → chunk-6XRF4IAL.cjs.map} +1 -1
- package/build/cjs/chunk-774FGQHO.cjs +11 -0
- package/build/cjs/{chunk-O5LBEGUH.cjs.map → chunk-774FGQHO.cjs.map} +1 -1
- package/build/cjs/{chunk-BBSLIWGB.cjs → chunk-BXCHISUQ.cjs} +3 -3
- package/build/cjs/chunk-BXCHISUQ.cjs.map +1 -0
- package/build/cjs/{chunk-B26H5TLV.cjs → chunk-DKPG7O4B.cjs} +4 -4
- package/build/cjs/{chunk-B26H5TLV.cjs.map → chunk-DKPG7O4B.cjs.map} +1 -1
- package/build/cjs/{chunk-5ZI6OPSJ.cjs → chunk-FIAYYZHY.cjs} +5 -5
- package/build/cjs/{chunk-5ZI6OPSJ.cjs.map → chunk-FIAYYZHY.cjs.map} +1 -1
- package/build/cjs/{chunk-NFFAHI3U.cjs → chunk-L6QDNMMG.cjs} +4 -4
- package/build/cjs/chunk-L6QDNMMG.cjs.map +1 -0
- package/build/cjs/{chunk-GABRYORZ.cjs → chunk-P7R4RWMU.cjs} +4 -4
- package/build/cjs/{chunk-GABRYORZ.cjs.map → chunk-P7R4RWMU.cjs.map} +1 -1
- package/build/cjs/{chunk-NXXHABK7.cjs → chunk-QOI2FQSL.cjs} +4 -4
- package/build/cjs/{chunk-NXXHABK7.cjs.map → chunk-QOI2FQSL.cjs.map} +1 -1
- package/build/cjs/chunk-S25XCKOA.cjs +11 -0
- package/build/cjs/{chunk-C6IVBY3E.cjs.map → chunk-S25XCKOA.cjs.map} +1 -1
- package/build/cjs/chunk-SLHKSOQC.cjs +11 -0
- package/build/cjs/{chunk-5NPRZBFO.cjs.map → chunk-SLHKSOQC.cjs.map} +1 -1
- package/build/cjs/public/experimental/action-form.cjs +4 -4
- package/build/cjs/public/experimental/document-viewer.cjs +5 -5
- package/build/cjs/public/experimental/email-viewer.cjs +3 -3
- package/build/cjs/public/experimental/excel-viewer.cjs +3 -3
- package/build/cjs/public/experimental/filter-list.cjs +13 -13
- package/build/cjs/public/experimental/image-viewer.cjs +3 -3
- package/build/cjs/public/experimental/markdown-renderer.cjs +3 -3
- package/build/cjs/public/experimental/object-table.cjs +8 -8
- package/build/cjs/public/experimental/object-table.css +2 -2
- package/build/cjs/public/experimental/object-table.css.map +1 -1
- package/build/cjs/public/experimental/pdf-viewer.cjs +7 -7
- package/build/cjs/public/experimental/theme.cjs +17 -0
- package/build/cjs/public/experimental/theme.cjs.map +1 -0
- package/build/cjs/public/experimental/theme.d.cts +88 -0
- package/build/cjs/public/experimental/tiff-renderer.cjs +3 -3
- package/build/cjs/public/experimental/video-viewer.cjs +3 -3
- package/build/cjs/public/experimental/xml-viewer.cjs +3 -3
- package/build/cjs/public/experimental.cjs +63 -54
- package/build/cjs/public/experimental.css +2 -2
- package/build/cjs/public/experimental.css.map +1 -1
- package/build/cjs/public/experimental.d.cts +1 -0
- package/build/esm/object-table/EditableCell.module.css +2 -2
- package/build/esm/public/experimental/theme.js +19 -0
- package/build/esm/public/experimental/theme.js.map +1 -0
- package/build/esm/public/experimental.js +1 -0
- package/build/esm/public/experimental.js.map +1 -1
- package/build/esm/theme/OsdkThemeContext.js +19 -0
- package/build/esm/theme/OsdkThemeContext.js.map +1 -0
- package/build/esm/theme/OsdkThemeProvider.js +74 -0
- package/build/esm/theme/OsdkThemeProvider.js.map +1 -0
- package/build/esm/theme/types.js +2 -0
- package/build/esm/theme/types.js.map +1 -0
- package/build/esm/theme/useOsdkTheme.js +40 -0
- package/build/esm/theme/useOsdkTheme.js.map +1 -0
- package/build/esm/theme/useSystemTheme.js +45 -0
- package/build/esm/theme/useSystemTheme.js.map +1 -0
- package/build/esm/tokens/base-tokens/dark.css +8 -99
- package/build/esm/util/UserAgent.js +1 -1
- package/build/esm/util/UserAgent.js.map +1 -1
- package/build/types/public/experimental/theme.d.ts +3 -0
- package/build/types/public/experimental/theme.d.ts.map +1 -0
- package/build/types/public/experimental.d.ts +1 -0
- package/build/types/public/experimental.d.ts.map +1 -1
- package/build/types/theme/OsdkThemeContext.d.ts +3 -0
- package/build/types/theme/OsdkThemeContext.d.ts.map +1 -0
- package/build/types/theme/OsdkThemeProvider.d.ts +45 -0
- package/build/types/theme/OsdkThemeProvider.d.ts.map +1 -0
- package/build/types/theme/types.d.ts +25 -0
- package/build/types/theme/types.d.ts.map +1 -0
- package/build/types/theme/useOsdkTheme.d.ts +16 -0
- package/build/types/theme/useOsdkTheme.d.ts.map +1 -0
- package/build/types/theme/useSystemTheme.d.ts +7 -0
- package/build/types/theme/useSystemTheme.d.ts.map +1 -0
- package/docs/CSSVariables.md +4 -16
- package/docs/OsdkThemeProvider.md +239 -0
- package/docs/Prerequisites.md +23 -0
- package/package.json +17 -8
- package/build/cjs/chunk-5NPRZBFO.cjs +0 -11
- package/build/cjs/chunk-6Z2CEPQP.cjs +0 -11
- package/build/cjs/chunk-BBSLIWGB.cjs.map +0 -1
- package/build/cjs/chunk-C6IVBY3E.cjs +0 -11
- package/build/cjs/chunk-G2AYUCKB.cjs +0 -11
- package/build/cjs/chunk-NFFAHI3U.cjs.map +0 -1
- package/build/cjs/chunk-O5LBEGUH.cjs +0 -11
package/docs/CSSVariables.md
CHANGED
|
@@ -1508,17 +1508,13 @@ For more comprehensive theming, override the Blueprint tokens that the OSDK toke
|
|
|
1508
1508
|
|
|
1509
1509
|
## Dark Mode
|
|
1510
1510
|
|
|
1511
|
-
`@osdk/react-components` ships built-in dark-theme overrides
|
|
1511
|
+
`@osdk/react-components` ships built-in dark-theme overrides that activate when `[data-bp-color-scheme="dark"]` is set on an ancestor element (typically `<html>`) — matching Blueprint's own convention so the OSDK + Blueprint tokens flip together. The supported way to set the attribute is `<OsdkThemeProvider>` from `@osdk/react-components/experimental/theme`; see [OsdkThemeProvider](./OsdkThemeProvider.md) for the full reference, including `defaultTheme="system"` (the default, follows `prefers-color-scheme`), runtime toggles via `useOsdkTheme`, and controlled mode for integrating with an external theme store.
|
|
1512
1512
|
|
|
1513
|
-
|
|
1514
|
-
2. **`[data-bp-color-scheme="dark"]` or `.bp6-dark`** — matches the Blueprint convention. Set this attribute / class on any ancestor (often `<html>`) to force dark explicitly. Useful when the OS preference doesn't reflect what the host wants, or when previewing dark mode in isolation.
|
|
1515
|
-
3. **`[data-theme="dark"]`** — matches the Tailwind/Primer/Storybook toolbar convention. Lets Storybook (and other hosts that already use this attribute) opt into dark without duplicating overrides.
|
|
1516
|
-
|
|
1517
|
-
The attribute paths win over the media query when both apply, giving hosts an explicit override. Under `[data-bp-color-scheme="dark"]` / `.bp6-dark`, Blueprint flips `--bp-*` itself, so `dark.css` only re-maps `--osdk-*` tokens. The other two selectors also flip the relevant `--bp-*` tokens because Blueprint doesn't fire there.
|
|
1513
|
+
Under `[data-bp-color-scheme="dark"]` Blueprint flips its own `--bp-*` tokens, so `dark.css` only re-maps the subset of `--osdk-*` tokens that have no `--bp-*` counterpart or that intentionally diverge from Blueprint's value.
|
|
1518
1514
|
|
|
1519
1515
|
### Adding your own dark overrides
|
|
1520
1516
|
|
|
1521
|
-
To customize dark-mode tokens beyond the defaults, declare your overrides in a higher layer using the same
|
|
1517
|
+
To customize dark-mode tokens beyond the defaults, declare your overrides in a higher layer using the same selector:
|
|
1522
1518
|
|
|
1523
1519
|
```css
|
|
1524
1520
|
@layer osdk.styles, user.theme;
|
|
@@ -1526,15 +1522,7 @@ To customize dark-mode tokens beyond the defaults, declare your overrides in a h
|
|
|
1526
1522
|
@import "@osdk/react-components/styles.css" layer(osdk.styles);
|
|
1527
1523
|
|
|
1528
1524
|
@layer user.theme {
|
|
1529
|
-
|
|
1530
|
-
:root {
|
|
1531
|
-
--osdk-background-primary: #0a0a0a;
|
|
1532
|
-
--osdk-table-row-bg-alternate: #161616;
|
|
1533
|
-
}
|
|
1534
|
-
}
|
|
1535
|
-
|
|
1536
|
-
[data-bp-color-scheme="dark"],
|
|
1537
|
-
.bp6-dark {
|
|
1525
|
+
[data-bp-color-scheme="dark"] {
|
|
1538
1526
|
--osdk-background-primary: #0a0a0a;
|
|
1539
1527
|
--osdk-table-row-bg-alternate: #161616;
|
|
1540
1528
|
}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# OsdkThemeProvider
|
|
2
|
+
|
|
3
|
+
Provides OSDK theme state to descendants and writes a `data-bp-color-scheme` attribute onto the document so the OSDK + Blueprint design tokens activate the right theme. Components inside the provider re-render automatically when the resolved theme changes.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
Before using `OsdkThemeProvider`, complete the library setup described in [Prerequisites](./Prerequisites.md), in particular the CSS layer imports - the provider only flips an attribute; the OSDK token CSS does the rest.
|
|
8
|
+
|
|
9
|
+
## Table of Contents
|
|
10
|
+
|
|
11
|
+
- [Import](#import)
|
|
12
|
+
- [Quick start](#quick-start)
|
|
13
|
+
- [Props reference](#props-reference)
|
|
14
|
+
- [`useOsdkTheme` hook](#useosdktheme-hook)
|
|
15
|
+
- [Examples](#examples)
|
|
16
|
+
- [Default: follow the OS preference](#default-follow-the-os-preference)
|
|
17
|
+
- [Force light or dark with `defaultTheme`](#force-light-or-dark-with-defaulttheme)
|
|
18
|
+
- [Build a `ThemeToggle`](#build-a-themetoggle)
|
|
19
|
+
- [Drive the theme from an external store (controlled mode)](#drive-the-theme-from-an-external-store-controlled-mode)
|
|
20
|
+
- [Scope theming to a subtree](#scope-theming-to-a-subtree)
|
|
21
|
+
- [Branching on the resolved theme in JS](#branching-on-the-resolved-theme-in-js)
|
|
22
|
+
|
|
23
|
+
## Import
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
import {
|
|
27
|
+
type OsdkThemeMode,
|
|
28
|
+
OsdkThemeProvider,
|
|
29
|
+
type ResolvedOsdkTheme,
|
|
30
|
+
useOsdkTheme,
|
|
31
|
+
} from "@osdk/react-components/experimental/theme";
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quick start
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
import { OsdkThemeProvider } from "@osdk/react-components/experimental/theme";
|
|
38
|
+
|
|
39
|
+
function App() {
|
|
40
|
+
return (
|
|
41
|
+
<OsdkProvider client={client}>
|
|
42
|
+
<OsdkThemeProvider>
|
|
43
|
+
{/* your app */}
|
|
44
|
+
</OsdkThemeProvider>
|
|
45
|
+
</OsdkProvider>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
With no props the provider follows `prefers-color-scheme` and re-renders when the OS preference changes. To override the OS at runtime, descendants call `setTheme` from [`useOsdkTheme`](#useosdktheme-hook).
|
|
51
|
+
|
|
52
|
+
> **Always render the provider somewhere above OSDK components.** OSDK components stay in light mode without it — the CSS only flips when `data-bp-color-scheme="dark"` is on an ancestor, and the provider is the supported way to manage that attribute. If an external store already owns your theme value, use [controlled mode](#drive-the-theme-from-an-external-store-controlled-mode) instead of skipping the provider — that way descendants can still call `useOsdkTheme`.
|
|
53
|
+
|
|
54
|
+
## Props reference
|
|
55
|
+
|
|
56
|
+
| Prop | Type | Default | Description |
|
|
57
|
+
| ---------------- | --------------------------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
58
|
+
| `theme` | `"light" \| "dark" \| "system"` _(optional)_ | — | Controlled theme. When provided, the provider does not maintain its own state — the parent must respond to `onThemeChanged` (or update its own external store) and re-render with the new value. See [Drive the theme from an external store](#drive-the-theme-from-an-external-store-controlled-mode). |
|
|
59
|
+
| `defaultTheme` | `"light" \| "dark" \| "system"` | `"system"` | Initial theme when uncontrolled. Ignored when `theme` is provided. The provider owns the state from then on; descendants change it at runtime via `useOsdkTheme().setTheme`. |
|
|
60
|
+
| `onThemeChanged` | `(theme: OsdkThemeMode) => void` _(optional)_ | — | Fires whenever a descendant calls `setTheme`. Use this to layer side effects (persistence, analytics) on top of the default state update, or to drive an external store in controlled mode. |
|
|
61
|
+
| `target` | `HTMLElement \| null` _(optional)_ | `document.documentElement` | Element to write `data-bp-color-scheme` onto. Defaults to `<html>` so Blueprint portals (popovers, dialogs, tooltips) — which render outside the React tree — also receive the theme. See [Scope theming to a subtree](#scope-theming-to-a-subtree). |
|
|
62
|
+
| `children` | `React.ReactNode` | — | Subtree that should resolve the theme via `useOsdkTheme`. |
|
|
63
|
+
|
|
64
|
+
### `defaultTheme` modes
|
|
65
|
+
|
|
66
|
+
| Mode | Behavior |
|
|
67
|
+
| ---------- | --------------------------------------------------------------------------------------- |
|
|
68
|
+
| `"system"` | Follows the OS `prefers-color-scheme` setting and re-renders when it changes (default). |
|
|
69
|
+
| `"light"` | Starts in light mode regardless of the OS preference. |
|
|
70
|
+
| `"dark"` | Starts in dark mode regardless of the OS preference. |
|
|
71
|
+
|
|
72
|
+
`"system"` is the only mode where the resolved theme can change without anyone calling `setTheme` — it reacts to the OS preference flipping while your app is open.
|
|
73
|
+
|
|
74
|
+
## `useOsdkTheme` hook
|
|
75
|
+
|
|
76
|
+
```tsx
|
|
77
|
+
const { theme, resolvedTheme, setTheme } = useOsdkTheme();
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
| Field | Type | Description |
|
|
81
|
+
| --------------- | ------------------------------- | --------------------------------------------------------------------------------------------------------- |
|
|
82
|
+
| `theme` | `"light" \| "dark" \| "system"` | The requested mode, including `"system"`. |
|
|
83
|
+
| `resolvedTheme` | `"light" \| "dark"` | The concrete theme actually applied to the DOM. When `theme === "system"`, tracks `prefers-color-scheme`. |
|
|
84
|
+
| `setTheme` | `(next: OsdkThemeMode) => void` | Switch the requested mode at runtime. |
|
|
85
|
+
|
|
86
|
+
Must be called from a descendant of `<OsdkThemeProvider>`; throws otherwise.
|
|
87
|
+
|
|
88
|
+
## Examples
|
|
89
|
+
|
|
90
|
+
### Default: follow the OS preference
|
|
91
|
+
|
|
92
|
+
The simplest setup — no props needed. The provider starts in `"system"` mode, listens to `prefers-color-scheme`, and flips automatically when the user toggles their OS appearance.
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
import { OsdkThemeProvider } from "@osdk/react-components/experimental/theme";
|
|
96
|
+
|
|
97
|
+
export function Root() {
|
|
98
|
+
return (
|
|
99
|
+
<OsdkProvider client={client}>
|
|
100
|
+
<OsdkThemeProvider>
|
|
101
|
+
<App />
|
|
102
|
+
</OsdkThemeProvider>
|
|
103
|
+
</OsdkProvider>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
To verify this in development, open Chrome DevTools → `⌘⇧P` → "Show Rendering" → set "Emulate CSS media feature prefers-color-scheme" to `light` or `dark`.
|
|
109
|
+
|
|
110
|
+
### Force light or dark with `defaultTheme`
|
|
111
|
+
|
|
112
|
+
Pin the initial mode if your app intentionally ships in light or dark regardless of the OS:
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
<OsdkThemeProvider defaultTheme="dark">
|
|
116
|
+
<App />
|
|
117
|
+
</OsdkThemeProvider>;
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Users can still switch at runtime via `useOsdkTheme().setTheme`; `defaultTheme` only seeds the initial value.
|
|
121
|
+
|
|
122
|
+
### Build a `ThemeToggle`
|
|
123
|
+
|
|
124
|
+
A typical settings-bar control that lets the user pick light/dark/system:
|
|
125
|
+
|
|
126
|
+
```tsx
|
|
127
|
+
import {
|
|
128
|
+
type OsdkThemeMode,
|
|
129
|
+
useOsdkTheme,
|
|
130
|
+
} from "@osdk/react-components/experimental/theme";
|
|
131
|
+
|
|
132
|
+
const MODES: readonly OsdkThemeMode[] = ["light", "dark", "system"];
|
|
133
|
+
|
|
134
|
+
export function ThemeToggle() {
|
|
135
|
+
const { theme, resolvedTheme, setTheme } = useOsdkTheme();
|
|
136
|
+
return (
|
|
137
|
+
<div role="group" aria-label="Theme">
|
|
138
|
+
{MODES.map((mode) => (
|
|
139
|
+
<button
|
|
140
|
+
key={mode}
|
|
141
|
+
type="button"
|
|
142
|
+
onClick={() => setTheme(mode)}
|
|
143
|
+
aria-pressed={theme === mode}
|
|
144
|
+
>
|
|
145
|
+
{mode}
|
|
146
|
+
</button>
|
|
147
|
+
))}
|
|
148
|
+
{theme === "system" && (
|
|
149
|
+
<span aria-live="polite">(resolved: {resolvedTheme})</span>
|
|
150
|
+
)}
|
|
151
|
+
</div>
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Render it anywhere inside the provider:
|
|
157
|
+
|
|
158
|
+
```tsx
|
|
159
|
+
<OsdkThemeProvider>
|
|
160
|
+
<Header>
|
|
161
|
+
<ThemeToggle />
|
|
162
|
+
</Header>
|
|
163
|
+
<main>{/* ... */}</main>
|
|
164
|
+
</OsdkThemeProvider>;
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Drive the theme from an external store (controlled mode)
|
|
168
|
+
|
|
169
|
+
If the theme value already lives outside the OSDK tree (e.g. in a parent design-system provider), pass it in via the `theme` prop. The provider stops owning state; you re-render it with the new value when the store changes, and the provider rewrites `data-bp-color-scheme` accordingly.
|
|
170
|
+
|
|
171
|
+
```tsx
|
|
172
|
+
import {
|
|
173
|
+
type OsdkThemeMode,
|
|
174
|
+
OsdkThemeProvider,
|
|
175
|
+
} from "@osdk/react-components/experimental/theme";
|
|
176
|
+
import { useAppTheme } from "../store/theme.js"; // your own store hook
|
|
177
|
+
|
|
178
|
+
export function AppRoot() {
|
|
179
|
+
// `theme` is owned by the app's store, not by the provider.
|
|
180
|
+
const theme = useAppTheme();
|
|
181
|
+
return (
|
|
182
|
+
<OsdkProvider client={client}>
|
|
183
|
+
<OsdkThemeProvider theme={theme}>
|
|
184
|
+
<App />
|
|
185
|
+
</OsdkThemeProvider>
|
|
186
|
+
</OsdkProvider>
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
If descendants call `setTheme` from `useOsdkTheme()`, controlled mode does **not** update the provider's state — it fires `onThemeChanged` so you can route the change back into your store.
|
|
192
|
+
|
|
193
|
+
```tsx
|
|
194
|
+
<OsdkThemeProvider
|
|
195
|
+
theme={theme}
|
|
196
|
+
onThemeChanged={(next) => dispatch(setTheme(next))}
|
|
197
|
+
>
|
|
198
|
+
<App />
|
|
199
|
+
</OsdkThemeProvider>;
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Use controlled mode whenever an external source of truth exists. Use uncontrolled (just `defaultTheme`) when the provider can own the state itself.
|
|
203
|
+
|
|
204
|
+
### Scope theming to a subtree
|
|
205
|
+
|
|
206
|
+
By default the provider writes `data-bp-color-scheme` onto `<html>` so portaled overlays (popovers, dialogs, tooltips) inherit the theme. To theme only a slice of the page — for example, embedding an OSDK dashboard inside a host app that already manages its own theme — pass a `target`:
|
|
207
|
+
|
|
208
|
+
```tsx
|
|
209
|
+
import { useRef } from "react";
|
|
210
|
+
|
|
211
|
+
export function DashboardEmbed() {
|
|
212
|
+
const scopeRef = useRef<HTMLDivElement>(null);
|
|
213
|
+
return (
|
|
214
|
+
<div ref={scopeRef}>
|
|
215
|
+
<OsdkThemeProvider target={scopeRef.current} defaultTheme="dark">
|
|
216
|
+
<Dashboard />
|
|
217
|
+
</OsdkThemeProvider>
|
|
218
|
+
</div>
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Trade-off: portals from `@base-ui/react` / Blueprint render in a portal container that is **not** a descendant of `scopeRef`, so dropdowns and tooltips opened from inside the scoped subtree will follow the document-level theme, not the scoped one. Use the default (`<html>`) target unless you specifically need per-region theming.
|
|
224
|
+
|
|
225
|
+
## Branching on the resolved theme in JS
|
|
226
|
+
|
|
227
|
+
If you need to swap an asset or change a non-CSS value based on theme, read `resolvedTheme` — not `theme` — so the `"system"` mode resolves to a concrete `"light"` or `"dark"` for you:
|
|
228
|
+
|
|
229
|
+
```tsx
|
|
230
|
+
function LogoMark() {
|
|
231
|
+
const { resolvedTheme } = useOsdkTheme();
|
|
232
|
+
return (
|
|
233
|
+
<img
|
|
234
|
+
src={resolvedTheme === "dark" ? "/logo-dark.svg" : "/logo-light.svg"}
|
|
235
|
+
alt="Logo"
|
|
236
|
+
/>
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
```
|
package/docs/Prerequisites.md
CHANGED
|
@@ -124,6 +124,29 @@ All components resolve their visual properties through CSS custom properties. Th
|
|
|
124
124
|
|
|
125
125
|
Per-component references list the `--osdk-*` variables each component exposes — see, for example, [ObjectTable › Theming](./ObjectTable.md#theming). The full catalog of variables lives in [CSSVariables.md](./CSSVariables.md).
|
|
126
126
|
|
|
127
|
+
### Light and dark mode
|
|
128
|
+
|
|
129
|
+
OSDK components ship a built-in dark theme. Wrap your app in `<OsdkThemeProvider>` to activate it and to let users override the OS preference at runtime:
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
import { OsdkThemeProvider } from "@osdk/react-components/experimental/theme";
|
|
133
|
+
|
|
134
|
+
function App() {
|
|
135
|
+
return (
|
|
136
|
+
<OsdkProvider client={client}>
|
|
137
|
+
<OsdkThemeProvider>
|
|
138
|
+
{/* defaults to "system" */}
|
|
139
|
+
{/* your app */}
|
|
140
|
+
</OsdkThemeProvider>
|
|
141
|
+
</OsdkProvider>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
By default the provider follows `prefers-color-scheme` and writes the resolved value to `data-bp-color-scheme` on `<html>` — matching [Blueprint's convention](https://blueprintjs.com/docs/#core/colors) so the theme also applies to portaled overlays (popovers, dialogs, tooltips).
|
|
147
|
+
|
|
148
|
+
See [OsdkThemeProvider](./OsdkThemeProvider.md) for the full reference, including the `defaultTheme` modes, the `useOsdkTheme` hook, persisting the user's choice, and integrating with an external theme store via controlled mode.
|
|
149
|
+
|
|
127
150
|
### Accessibility
|
|
128
151
|
|
|
129
152
|
When overriding theme tokens, keep the result accessible:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@osdk/react-components",
|
|
3
|
-
"version": "0.19.0
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -124,6 +124,15 @@
|
|
|
124
124
|
"require": "./build/cjs/public/experimental/pdf-viewer.cjs",
|
|
125
125
|
"default": "./build/browser/public/experimental/pdf-viewer.js"
|
|
126
126
|
},
|
|
127
|
+
"./experimental/theme": {
|
|
128
|
+
"browser": "./build/browser/public/experimental/theme.js",
|
|
129
|
+
"import": {
|
|
130
|
+
"types": "./build/types/public/experimental/theme.d.ts",
|
|
131
|
+
"default": "./build/esm/public/experimental/theme.js"
|
|
132
|
+
},
|
|
133
|
+
"require": "./build/cjs/public/experimental/theme.cjs",
|
|
134
|
+
"default": "./build/browser/public/experimental/theme.js"
|
|
135
|
+
},
|
|
127
136
|
"./experimental/tiff-renderer": {
|
|
128
137
|
"browser": "./build/browser/public/experimental/tiff-renderer.js",
|
|
129
138
|
"import": {
|
|
@@ -184,9 +193,9 @@
|
|
|
184
193
|
"xlsx": "^0.18.5"
|
|
185
194
|
},
|
|
186
195
|
"peerDependencies": {
|
|
187
|
-
"@osdk/api": "
|
|
188
|
-
"@osdk/client": "
|
|
189
|
-
"@osdk/react": "
|
|
196
|
+
"@osdk/api": "^2.8.0",
|
|
197
|
+
"@osdk/client": "^2.8.0",
|
|
198
|
+
"@osdk/react": "^2.8.0",
|
|
190
199
|
"@types/react": "^17 || ^18 || ^19",
|
|
191
200
|
"classnames": "^2.0.0",
|
|
192
201
|
"react": "^17 || ^18 || ^19",
|
|
@@ -211,11 +220,11 @@
|
|
|
211
220
|
"react-dom": "^18.3.1",
|
|
212
221
|
"typescript": "~5.5.4",
|
|
213
222
|
"@osdk/aip-core": "0.4.0",
|
|
214
|
-
"@osdk/
|
|
215
|
-
"@osdk/
|
|
223
|
+
"@osdk/api": "2.23.0",
|
|
224
|
+
"@osdk/client": "2.23.0",
|
|
216
225
|
"@osdk/monorepo.api-extractor": "~0.7.0",
|
|
217
226
|
"@osdk/monorepo.tsconfig": "~0.7.0",
|
|
218
|
-
"@osdk/react": "2.23.0
|
|
227
|
+
"@osdk/react": "2.23.0"
|
|
219
228
|
},
|
|
220
229
|
"publishConfig": {
|
|
221
230
|
"access": "public"
|
|
@@ -240,7 +249,7 @@
|
|
|
240
249
|
],
|
|
241
250
|
"type": "module",
|
|
242
251
|
"scripts": {
|
|
243
|
-
"check-attw": "attw --pack . --exclude-entrypoints ./styles.css ./experimental/action-form ./experimental/aip-agent-chat ./experimental/document-viewer ./experimental/email-viewer ./experimental/excel-viewer ./experimental/filter-list ./experimental/image-viewer ./experimental/markdown-renderer ./experimental/object-table ./experimental/pdf-viewer ./experimental/tiff-renderer ./experimental/video-viewer ./experimental/xml-viewer",
|
|
252
|
+
"check-attw": "attw --pack . --exclude-entrypoints ./styles.css ./experimental/action-form ./experimental/aip-agent-chat ./experimental/document-viewer ./experimental/email-viewer ./experimental/excel-viewer ./experimental/filter-list ./experimental/image-viewer ./experimental/markdown-renderer ./experimental/object-table ./experimental/pdf-viewer ./experimental/theme ./experimental/tiff-renderer ./experimental/video-viewer ./experimental/xml-viewer",
|
|
244
253
|
"check-spelling": "cspell --quiet .",
|
|
245
254
|
"clean": "rm -rf lib dist types build tsconfig.tsbuildinfo",
|
|
246
255
|
"fix-lint": "eslint . --fix && dprint fmt",
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var chunkKHMOMROL_cjs = require('./chunk-KHMOMROL.cjs');
|
|
4
|
-
var chunkBBSLIWGB_cjs = require('./chunk-BBSLIWGB.cjs');
|
|
5
|
-
|
|
6
|
-
// src/public/experimental/video-viewer.ts
|
|
7
|
-
var VideoViewer2 = chunkBBSLIWGB_cjs.withOsdkMetrics(chunkKHMOMROL_cjs.VideoViewer, "VideoViewer");
|
|
8
|
-
|
|
9
|
-
exports.VideoViewer = VideoViewer2;
|
|
10
|
-
//# sourceMappingURL=chunk-5NPRZBFO.cjs.map
|
|
11
|
-
//# sourceMappingURL=chunk-5NPRZBFO.cjs.map
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var chunkVOROB7KJ_cjs = require('./chunk-VOROB7KJ.cjs');
|
|
4
|
-
var chunkBBSLIWGB_cjs = require('./chunk-BBSLIWGB.cjs');
|
|
5
|
-
|
|
6
|
-
// src/public/experimental/image-viewer.ts
|
|
7
|
-
var ImageViewer2 = chunkBBSLIWGB_cjs.withOsdkMetrics(chunkVOROB7KJ_cjs.ImageViewer, "ImageViewer");
|
|
8
|
-
|
|
9
|
-
exports.ImageViewer = ImageViewer2;
|
|
10
|
-
//# sourceMappingURL=chunk-6Z2CEPQP.cjs.map
|
|
11
|
-
//# sourceMappingURL=chunk-6Z2CEPQP.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/util/UserAgent.ts","../../src/util/withOsdkMetrics.ts"],"names":["useRegisterUserAgent","React"],"mappings":";;;;;;;;;;;;AAgBA,IAAM,kBAAA,GAAqB,yBAAyB,sDAA2B,CAAA,CAAA;AACxE,SAAS,mBAAmB,aAAA,EAAe;AAChD,EAAA,OAAO,CAAA,EAAG,kBAAkB,CAAA,CAAA,EAAI,aAAa,CAAA,CAAA;AAC/C;;;ACKO,SAAS,eAAA,CAAgB,WAAW,IAAA,EAAM;AAC/C,EAAA,MAAM,UAAU,CAAA,KAAA,KAAS;AACvB,IAAAA,0BAAA,CAAqB,kBAAA,CAAmB,IAAI,CAAC,CAAA;AAC7C,IAAA,uBAAoBC,sBAAA,CAAM,aAAA,CAAc,SAAA,EAAW,KAAK,CAAA;AAAA,EAC1D,CAAA;AACA,EAAA,OAAA,CAAQ,WAAA,GAAc,mBAAmB,IAAI,CAAA,CAAA,CAAA;AAC7C,EAAA,OAAO,OAAA;AACT","file":"chunk-BBSLIWGB.cjs","sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst PACKAGE_USER_AGENT = `osdk-react-components/${process.env.PACKAGE_VERSION}`;\nexport function componentUserAgent(componentName) {\n return `${PACKAGE_USER_AGENT}/${componentName}`;\n}","/*\n * Copyright 2026 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useRegisterUserAgent } from \"@osdk/react\";\nimport React from \"react\";\nimport { componentUserAgent } from \"./UserAgent.js\";\n\n// `any` is required: FunctionComponent defaults to FunctionComponent<{}> which\n// rejects components with required props. A generic P parameter doesn't help\n// because TS can't infer both P and C simultaneously from a single argument.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function withOsdkMetrics(Component, name) {\n const Wrapped = props => {\n useRegisterUserAgent(componentUserAgent(name));\n return /*#__PURE__*/React.createElement(Component, props);\n };\n Wrapped.displayName = `withOsdkMetrics(${name})`;\n return Wrapped;\n}"]}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var chunkPKJFOG2Z_cjs = require('./chunk-PKJFOG2Z.cjs');
|
|
4
|
-
var chunkBBSLIWGB_cjs = require('./chunk-BBSLIWGB.cjs');
|
|
5
|
-
|
|
6
|
-
// src/public/experimental/email-viewer.ts
|
|
7
|
-
var EmailViewer2 = chunkBBSLIWGB_cjs.withOsdkMetrics(chunkPKJFOG2Z_cjs.EmailViewer, "EmailViewer");
|
|
8
|
-
|
|
9
|
-
exports.EmailViewer = EmailViewer2;
|
|
10
|
-
//# sourceMappingURL=chunk-C6IVBY3E.cjs.map
|
|
11
|
-
//# sourceMappingURL=chunk-C6IVBY3E.cjs.map
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var chunkOUJQJQ7N_cjs = require('./chunk-OUJQJQ7N.cjs');
|
|
4
|
-
var chunkBBSLIWGB_cjs = require('./chunk-BBSLIWGB.cjs');
|
|
5
|
-
|
|
6
|
-
// src/public/experimental/xml-viewer.ts
|
|
7
|
-
var XmlViewer2 = chunkBBSLIWGB_cjs.withOsdkMetrics(chunkOUJQJQ7N_cjs.XmlViewer, "XmlViewer");
|
|
8
|
-
|
|
9
|
-
exports.XmlViewer = XmlViewer2;
|
|
10
|
-
//# sourceMappingURL=chunk-G2AYUCKB.cjs.map
|
|
11
|
-
//# sourceMappingURL=chunk-G2AYUCKB.cjs.map
|