@myst-theme/site 0.3.2 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myst-theme/site",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "main": "./src/index.ts",
5
5
  "types": "./src/index.ts",
6
6
  "files": [
@@ -16,20 +16,20 @@
16
16
  "dependencies": {
17
17
  "@headlessui/react": "^1.7.15",
18
18
  "@heroicons/react": "^2.0.18",
19
- "@myst-theme/diagrams": "^0.3.2",
20
- "@myst-theme/frontmatter": "^0.3.2",
21
- "@myst-theme/jupyter": "^0.3.2",
22
- "@myst-theme/providers": "^0.3.2",
19
+ "@myst-theme/diagrams": "^0.3.3",
20
+ "@myst-theme/frontmatter": "^0.3.3",
21
+ "@myst-theme/jupyter": "^0.3.3",
22
+ "@myst-theme/providers": "^0.3.3",
23
23
  "classnames": "^2.3.2",
24
24
  "lodash.throttle": "^4.1.1",
25
25
  "myst-common": "^1.0.1",
26
26
  "myst-config": "^1.0.0",
27
- "myst-demo": "^0.3.2",
28
- "myst-to-react": "^0.3.2",
27
+ "myst-demo": "^0.3.3",
28
+ "myst-to-react": "^0.3.3",
29
29
  "nbtx": "^0.2.3",
30
30
  "node-cache": "^5.1.2",
31
31
  "node-fetch": "^2.6.11",
32
- "thebe-react": "^0.2.3",
32
+ "thebe-react": "^0.2.5",
33
33
  "unist-util-select": "^4.0.1"
34
34
  },
35
35
  "peerDependencies": {
@@ -16,14 +16,14 @@ export function Bibliography() {
16
16
  {filtered.length > HIDE_OVER_N_REFERENCES && (
17
17
  <button
18
18
  onClick={() => setHidden(!hidden)}
19
- className="float-right text-xs p-1 px-2 border rounded hover:border-blue-500 dark:hover:border-blue-400"
19
+ className="float-right p-1 px-2 text-xs border rounded hover:border-blue-500 dark:hover:border-blue-400"
20
20
  >
21
21
  {hidden ? 'Show All' : 'Collapse'}
22
22
  </button>
23
23
  )}
24
24
  <header className="text-lg font-semibold text-stone-900 dark:text-white">References</header>
25
25
  </div>
26
- <div className="text-xs mb-8 pl-3 text-stone-500 dark:text-stone-300">
26
+ <div className="pl-3 mb-8 text-xs text-stone-500 dark:text-stone-300">
27
27
  <ol>
28
28
  {refs.map((label) => {
29
29
  const { html } = data[label];
@@ -37,7 +37,7 @@ export function Bibliography() {
37
37
  );
38
38
  })}
39
39
  {filtered.length > HIDE_OVER_N_REFERENCES && (
40
- <li className="list-none text-center">
40
+ <li className="text-center list-none">
41
41
  <button
42
42
  onClick={() => setHidden(!hidden)}
43
43
  className="p-2 border rounded hover:border-blue-500 dark:hover:border-blue-400"
@@ -23,7 +23,7 @@ export function Run({
23
23
  ) => Promise<(IThebeCellExecuteReturn | null)[]>;
24
24
  }) {
25
25
  return (
26
- <div className="flex relative text-sm">
26
+ <div className="relative flex text-sm">
27
27
  <button
28
28
  className={classNames(
29
29
  'cursor-pointer text-gray-700 active:text-green-700 hover:opacity-100',
@@ -35,7 +35,7 @@ export function Run({
35
35
  disabled={disabled || !ready || executing}
36
36
  onClick={() => execute()}
37
37
  >
38
- <PlayCircleIcon className="h-6 w-6 inline-block align-top" title="run all cells" />
38
+ <PlayCircleIcon className="inline-block w-6 h-6 align-top" title="run all cells" />
39
39
  </button>
40
40
  {executing && (
41
41
  <span className="absolute top-0 left-0 z-10 w-[22px] h-[22px] opacity-100">
@@ -59,11 +59,11 @@ export function Clear({
59
59
  }) {
60
60
  return (
61
61
  <button
62
- className="flex cursor-pointer text-gray-700 active:text-green-700 opacity-60 hover:opacity-100"
62
+ className="flex text-gray-700 cursor-pointer active:text-green-700 opacity-60 hover:opacity-100"
63
63
  disabled={disabled || !ready || executing}
64
64
  onClick={() => clear()}
65
65
  >
66
- <MinusCircleIcon className="h-6 w-6 inline-block align-top" title="clear all outputs" />
66
+ <MinusCircleIcon className="inline-block w-6 h-6 align-top" title="clear all outputs" />
67
67
  </button>
68
68
  );
69
69
  }
@@ -98,7 +98,7 @@ export function NotebookRunAll() {
98
98
 
99
99
  return (
100
100
  <div className="flex">
101
- <div className="group flex relative space-x-1">
101
+ <div className="relative flex group space-x-1">
102
102
  <Run
103
103
  ready={ready}
104
104
  executing={executing}
@@ -108,20 +108,20 @@ export function NotebookRunAll() {
108
108
  }}
109
109
  />
110
110
  <button
111
- className="flex items-center cursor-pointer text-gray-700 active:text-green-700 opacity-60 hover:opacity-100"
111
+ className="flex items-center text-gray-700 cursor-pointer active:text-green-700 opacity-60 hover:opacity-100"
112
112
  disabled={!ready || executing}
113
113
  onClick={() => restart()}
114
114
  >
115
- <ArrowPathIcon className="h-6 w-6" title="restart kernel" />
115
+ <ArrowPathIcon className="w-6 h-6" title="restart kernel" />
116
116
  </button>
117
117
  <Clear ready={ready} executing={executing} clear={clear} />
118
118
  <button
119
- className="flex items-center cursor-pointer text-gray-700 active:text-green-700 opacity-60 hover:opacity-100"
119
+ className="flex items-center text-gray-700 cursor-pointer active:text-green-700 opacity-60 hover:opacity-100"
120
120
  disabled={!ready}
121
121
  onClick={clickLaunchInJupyter}
122
122
  >
123
123
  <ArrowTopRightOnSquareIcon
124
- className="h-6 w-6 inline-block align-top"
124
+ className="inline-block w-6 h-6 align-top"
125
125
  title="launch in juptyer"
126
126
  />
127
127
  </button>
@@ -26,7 +26,7 @@ type Props = {
26
26
  * scrollIntoView is used to ensure that when a user clicks on an item, it will smoothly scroll.
27
27
  */
28
28
  const Headings = ({ headings, activeId, highlight, selector }: Props) => (
29
- <ul className="text-slate-400 text-sm leading-6">
29
+ <ul className="text-sm text-slate-400 leading-6">
30
30
  {headings.map((heading) => (
31
31
  <li
32
32
  key={heading.id}
@@ -213,7 +213,7 @@ export const DocumentOutline = ({
213
213
  maxHeight: `calc(100vh - ${(top ?? 0) + 20}px)`,
214
214
  }}
215
215
  >
216
- <div className="text-slate-900 mb-4 text-sm leading-6 dark:text-slate-100 uppercase">
216
+ <div className="mb-4 text-sm uppercase text-slate-900 leading-6 dark:text-slate-100">
217
217
  In this article
218
218
  </div>
219
219
  <Headings headings={headings} activeId={activeId} highlight={highlight} selector={selector} />
@@ -3,6 +3,8 @@ import PowerIcon from '@heroicons/react/24/outline/PowerIcon';
3
3
  import { useHasNotebookProvider } from '@myst-theme/jupyter';
4
4
  import { useNavigation } from '@remix-run/react';
5
5
  import { useEffect, useState } from 'react';
6
+ import { Spinner } from './Spinner';
7
+ import classNames from 'classnames';
6
8
 
7
9
  export function EnableCompute({
8
10
  canCompute,
@@ -10,14 +12,7 @@ export function EnableCompute({
10
12
  }: React.PropsWithChildren<{ canCompute: boolean }>) {
11
13
  const { load, loading, core } = useThebeLoader();
12
14
  const { connect, connecting, ready: serverReady, error: serverError } = useThebeServer();
13
- const {
14
- start,
15
- starting,
16
- shutdown,
17
- session,
18
- ready: sessionReady,
19
- error: sessionError,
20
- } = useThebeSession();
15
+ const { start, starting, shutdown, ready: sessionReady, error: sessionError } = useThebeSession();
21
16
  const hasNotebookProvider = useHasNotebookProvider();
22
17
  const navigation = useNavigation();
23
18
  const [enabling, setEnabling] = useState(false);
@@ -36,16 +31,14 @@ export function EnableCompute({
36
31
  }, [enabling, core, serverReady, sessionReady]);
37
32
 
38
33
  if (!canCompute || !hasNotebookProvider) return null;
39
- let classes = 'flex text-center mr-1 cursor-pointer rounded-full';
40
- const idleClasses = 'text-blue-700 hover:opacity-100 opacity-60';
41
- const busyClasses = 'bg-yellow-700 text-yellow-700 opacity-100 font-semibold';
42
- const readyClasses = 'bg-green-700 text-green-700 opacity-100 font-semibold';
43
- const errorClasses = 'bg-red-700 text-red-700 opacity-100';
44
-
45
- if (busy) classes += busyClasses;
46
- else if (serverReady && sessionReady) classes += readyClasses;
47
- else if (serverError || sessionError) classes += errorClasses;
48
- else classes += idleClasses;
34
+ let title = 'Connect to a compute server';
35
+ const error = !!sessionError || !!serverError;
36
+ if (error) {
37
+ title = 'Error connecting to compute server';
38
+ }
39
+ if (busy) {
40
+ title = 'Connecting...';
41
+ }
49
42
 
50
43
  useEffect(() => {
51
44
  if (navigation.state === 'loading') {
@@ -54,10 +47,25 @@ export function EnableCompute({
54
47
  }, [shutdown, navigation]);
55
48
 
56
49
  return (
57
- <div className="flex mx-1 items-center mb-2">
58
- <button className={classes} onClick={() => setEnabling(true)} disabled={enabling || enabled}>
59
- <PowerIcon className="h-6 w-6 mx-1 inline-block align-top" title="enable compute" />
60
- </button>
50
+ <div className="relative flex items-center mx-1 mb-2">
51
+ {!enabled && (
52
+ <button
53
+ className={classNames(
54
+ 'flex text-center mr-1 cursor-pointer rounded-full disabled:opacity-10 text-gray-700',
55
+ { 'text-red-600 opacity-100': error },
56
+ )}
57
+ onClick={() => setEnabling(true)}
58
+ disabled={connecting || starting}
59
+ title={title}
60
+ >
61
+ <PowerIcon className="inline-block w-6 h-6 mx-1 align-top" />
62
+ </button>
63
+ )}
64
+ {(connecting || starting) && !error && (
65
+ <span className="absolute top-0 left-1 z-10 w-[22px] h-[22px] opacity-100" title={title}>
66
+ <Spinner size={24} />
67
+ </span>
68
+ )}
61
69
  {enabled && <>{children}</>}
62
70
  </div>
63
71
  );
@@ -16,19 +16,19 @@ const FooterLink = ({
16
16
  return (
17
17
  <Link
18
18
  prefetch="intent"
19
- className="group flex-1 p-4 block border font-normal hover:border-blue-600 dark:hover:border-blue-400 no-underline hover:text-blue-600 dark:hover:text-blue-400 text-gray-600 dark:text-gray-100 border-gray-200 dark:border-gray-500 rounded shadow-sm hover:shadow-lg dark:shadow-neutral-700"
19
+ className="flex-1 block p-4 font-normal text-gray-600 no-underline border border-gray-200 rounded group hover:border-blue-600 dark:hover:border-blue-400 hover:text-blue-600 dark:hover:text-blue-400 dark:text-gray-100 dark:border-gray-500 shadow-sm hover:shadow-lg dark:shadow-neutral-700"
20
20
  to={withBaseurl(url, baseurl)}
21
21
  >
22
- <div className="flex align-middle h-full">
22
+ <div className="flex h-full align-middle">
23
23
  {right && (
24
- <ArrowLeftIcon className="w-6 h-6 self-center transition-transform group-hover:-translate-x-1 shrink-0" />
24
+ <ArrowLeftIcon className="self-center w-6 h-6 transition-transform group-hover:-translate-x-1 shrink-0" />
25
25
  )}
26
26
  <div className={classNames('flex-grow', { 'text-right': right })}>
27
27
  <div className="text-xs text-gray-500 dark:text-gray-400">{group || ' '}</div>
28
28
  {short_title || title}
29
29
  </div>
30
30
  {!right && (
31
- <ArrowRightIcon className="w-6 h-6 self-center transition-transform group-hover:translate-x-1 shrink-0" />
31
+ <ArrowRightIcon className="self-center w-6 h-6 transition-transform group-hover:translate-x-1 shrink-0" />
32
32
  )}
33
33
  </div>
34
34
  </Link>
@@ -38,7 +38,7 @@ const FooterLink = ({
38
38
  export function FooterLinksBlock({ links }: { links?: FooterLinks }) {
39
39
  if (!links) return null;
40
40
  return (
41
- <div className="flex space-x-4 pt-10 mb-10">
41
+ <div className="flex pt-10 mb-10 space-x-4">
42
42
  {links.navigation?.prev && <FooterLink {...links.navigation?.prev} right />}
43
43
  {links.navigation?.next && <FooterLink {...links.navigation?.next} />}
44
44
  </div>
@@ -92,7 +92,7 @@ const Headings = ({ folder, headings, sections }: Props) => {
92
92
  {heading.short_title || heading.title}
93
93
  </HeadingLink>
94
94
  ) : (
95
- <h5 className="mb-3 lg:mt-8 font-semibold break-words dark:text-white">
95
+ <h5 className="mb-3 font-semibold break-words lg:mt-8 dark:text-white">
96
96
  {heading.short_title || heading.title}
97
97
  </h5>
98
98
  )}
@@ -3,7 +3,7 @@ import MoonIcon from '@heroicons/react/24/solid/MoonIcon';
3
3
  import SunIcon from '@heroicons/react/24/outline/SunIcon';
4
4
  import classNames from 'classnames';
5
5
 
6
- export function ThemeButton({ className = 'mx-3 h-8 w-8' }: { className?: string }) {
6
+ export function ThemeButton({ className = 'w-8 h-8 mx-3' }: { className?: string }) {
7
7
  const { isDark, nextTheme } = useTheme();
8
8
  return (
9
9
  <button
@@ -57,7 +57,7 @@ function ExternalOrInternalLink({
57
57
  function NavItem({ item }: { item: SiteNavItem }) {
58
58
  if (!('children' in item)) {
59
59
  return (
60
- <div className="relative grow-0 inline-block mx-2">
60
+ <div className="relative inline-block mx-2 grow-0">
61
61
  <ExternalOrInternalLink
62
62
  nav
63
63
  to={item.url ?? ''}
@@ -76,9 +76,9 @@ function NavItem({ item }: { item: SiteNavItem }) {
76
76
  );
77
77
  }
78
78
  return (
79
- <Menu as="div" className="relative grow-0 inline-block mx-2">
79
+ <Menu as="div" className="relative inline-block mx-2 grow-0">
80
80
  <div className="inline-block">
81
- <Menu.Button className="inline-flex items-center justify-center w-full mx-2 py-1 text-md font-medium text-stone-900 dark:text-white rounded-md focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75">
81
+ <Menu.Button className="inline-flex items-center justify-center w-full py-1 mx-2 font-medium rounded-md text-md text-stone-900 dark:text-white focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75">
82
82
  <span>{item.title}</span>
83
83
  <ChevronDownIcon className="w-5 h-5 ml-2 -mr-1 text-violet-200 hover:text-violet-100" />
84
84
  </Menu.Button>
@@ -92,7 +92,7 @@ function NavItem({ item }: { item: SiteNavItem }) {
92
92
  leaveFrom="transform opacity-100 scale-100"
93
93
  leaveTo="transform opacity-0 scale-95"
94
94
  >
95
- <Menu.Items className="origin-top-left absolute left-4 mt-2 w-48 rounded-sm shadow-lg py-1 bg-white ring-1 ring-black ring-opacity-5 focus:outline-none">
95
+ <Menu.Items className="absolute w-48 py-1 mt-2 origin-top-left bg-white rounded-sm shadow-lg left-4 ring-1 ring-black ring-opacity-5 focus:outline-none">
96
96
  {item.children?.map((action) => (
97
97
  <Menu.Item key={action.url}>
98
98
  {/* This is really ugly, BUT, the action needs to be defined HERE or the click away doesn't work for some reason */}
@@ -131,7 +131,7 @@ function NavItem({ item }: { item: SiteNavItem }) {
131
131
  function NavItems({ nav }: { nav?: SiteManifest['nav'] }) {
132
132
  if (!nav) return null;
133
133
  return (
134
- <div className="text-md flex-grow hidden lg:block">
134
+ <div className="flex-grow hidden text-md lg:block">
135
135
  {nav.map((item) => {
136
136
  return <NavItem key={'url' in item ? item.url : item.title} item={item} />;
137
137
  })}
@@ -144,10 +144,10 @@ function ActionMenu({ actions }: { actions?: SiteManifest['actions'] }) {
144
144
  return (
145
145
  <Menu as="div" className="relative">
146
146
  <div>
147
- <Menu.Button className="bg-transparent flex text-sm rounded-full focus:outline-none">
147
+ <Menu.Button className="flex text-sm bg-transparent rounded-full focus:outline-none">
148
148
  <span className="sr-only">Open Menu</span>
149
149
  <div className="flex items-center text-stone-200 hover:text-white">
150
- <EllipsisVerticalIcon className="h-8 w-8 p-1" />
150
+ <EllipsisVerticalIcon className="w-8 h-8 p-1" />
151
151
  </div>
152
152
  </Menu.Button>
153
153
  </div>
@@ -160,7 +160,7 @@ function ActionMenu({ actions }: { actions?: SiteManifest['actions'] }) {
160
160
  leaveFrom="transform opacity-100 scale-100"
161
161
  leaveTo="transform opacity-0 scale-95"
162
162
  >
163
- <Menu.Items className="origin-top-right absolute right-0 mt-2 w-48 rounded-sm shadow-lg py-1 bg-white ring-1 ring-black ring-opacity-5 focus:outline-none">
163
+ <Menu.Items className="absolute right-0 w-48 py-1 mt-2 origin-top-right bg-white rounded-sm shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
164
164
  {actions?.map((action) => (
165
165
  <Menu.Item key={action.url}>
166
166
  {({ active }) => (
@@ -182,19 +182,46 @@ function ActionMenu({ actions }: { actions?: SiteManifest['actions'] }) {
182
182
  );
183
183
  }
184
184
 
185
- function HomeLink({ logo, logoText, name }: { logo?: string; logoText?: string; name?: string }) {
185
+ function HomeLink({
186
+ logo,
187
+ logoDark,
188
+ logoText,
189
+ name,
190
+ }: {
191
+ logo?: string;
192
+ logoDark?: string;
193
+ logoText?: string;
194
+ name?: string;
195
+ }) {
186
196
  const Link = useLinkProvider();
187
197
  const baseurl = useBaseurl();
188
198
  const nothingSet = !logo && !logoText;
189
199
  return (
190
200
  <Link
191
- className="flex items-center dark:text-white w-fit ml-3 md:ml-5 xl:ml-7"
201
+ className="flex items-center ml-3 dark:text-white w-fit md:ml-5 xl:ml-7"
192
202
  to={withBaseurl('/', baseurl)}
193
203
  prefetch="intent"
194
204
  >
195
205
  {logo && (
196
- <div className="dark:bg-white dark:rounded p-1 mr-3">
197
- <img src={logo} className="h-9" alt={logoText || name} height="2.25rem"></img>
206
+ <div
207
+ className={classNames('p-1 mr-3', {
208
+ 'dark:bg-white dark:rounded': !logoDark,
209
+ })}
210
+ >
211
+ <img
212
+ src={logo}
213
+ className={classNames('h-9', { 'dark:hidden': !!logoDark })}
214
+ alt={logoText || name}
215
+ height="2.25rem"
216
+ ></img>
217
+ {logoDark && (
218
+ <img
219
+ src={logoDark}
220
+ className="hidden h-9 dark:block"
221
+ alt={logoText || name}
222
+ height="2.25rem"
223
+ ></img>
224
+ )}
198
225
  </div>
199
226
  )}
200
227
  <span
@@ -211,7 +238,8 @@ function HomeLink({ logo, logoText, name }: { logo?: string; logoText?: string;
211
238
  export function TopNav() {
212
239
  const [open, setOpen] = useNavOpen();
213
240
  const config = useSiteManifest();
214
- const { logo, logo_text, logoText, actions, title, nav } = config ?? ({} as SiteManifest);
241
+ const { logo, logo_dark, logo_text, logoText, actions, title, nav } =
242
+ config ?? ({} as SiteManifest);
215
243
  return (
216
244
  <div className="bg-white/80 backdrop-blur dark:bg-stone-900/80 shadow dark:shadow-stone-700 p-3 md:px-8 fixed w-screen top-0 z-30 h-[60px]">
217
245
  <nav className="flex items-center justify-between flex-wrap max-w-[1440px] mx-auto">
@@ -223,15 +251,20 @@ export function TopNav() {
223
251
  setOpen(!open);
224
252
  }}
225
253
  >
226
- <MenuIcon className="h-8 w-8 p-1" />
254
+ <MenuIcon className="w-8 h-8 p-1" />
227
255
  <span className="sr-only">Open Menu</span>
228
256
  </button>
229
257
  </div>
230
- <HomeLink name={title} logo={logo} logoText={logo_text || logoText} />
258
+ <HomeLink
259
+ name={title}
260
+ logo={logo}
261
+ logoDark={logo_dark}
262
+ logoText={logo_text || logoText}
263
+ />
231
264
  </div>
232
- <div className="flex-grow flex items-center w-auto">
265
+ <div className="flex items-center flex-grow w-auto">
233
266
  <NavItems nav={nav} />
234
- <div className="block flex-grow"></div>
267
+ <div className="flex-grow block"></div>
235
268
  <ThemeButton />
236
269
  <div className="block sm:hidden">
237
270
  <ActionMenu actions={actions} />
@@ -240,7 +273,7 @@ export function TopNav() {
240
273
  {actions?.map((action, index) => (
241
274
  <ExternalOrInternalLink
242
275
  key={action.url || index}
243
- className="inline-block text-md px-4 py-2 mx-1 leading-none border rounded border-stone-700 dark:border-white text-stone-700 dark:text-white hover:text-stone-500 dark:hover:text-neutral-800 hover:bg-neutral-100 mt-0"
276
+ className="inline-block px-4 py-2 mx-1 mt-0 leading-none border rounded text-md border-stone-700 dark:border-white text-stone-700 dark:text-white hover:text-stone-500 dark:hover:text-neutral-800 hover:bg-neutral-100"
244
277
  to={action.url}
245
278
  >
246
279
  {action.title}
@@ -96,7 +96,9 @@ export function updateSiteManifestStaticLinksInplace(
96
96
  if (!action.static) return;
97
97
  action.url = updateUrl(action.url);
98
98
  });
99
+ // TODO: this needs to be based on the template.yml in the future
99
100
  if (data.logo) data.logo = updateUrl(data.logo);
101
+ if (data.logo_dark) data.logo_dark = updateUrl(data.logo_dark);
100
102
  // Update the thumbnails to point at the CDN
101
103
  data.projects?.forEach((project) => {
102
104
  project.pages
@@ -10,7 +10,12 @@ import type { GenericParent } from 'myst-common';
10
10
  import { SourceFileKind } from 'myst-common';
11
11
  import { EnableCompute } from '../components/EnableCompute';
12
12
  import { NotebookRunAll } from '../components/ComputeControls';
13
- import { NotebookProvider, BinderBadge, useComputeOptions } from '@myst-theme/jupyter';
13
+ import {
14
+ NotebookProvider,
15
+ BinderBadge,
16
+ useComputeOptions,
17
+ ConnectionStatusTray,
18
+ } from '@myst-theme/jupyter';
14
19
 
15
20
  export const ArticlePage = React.memo(function ({ article }: { article: PageLoader }) {
16
21
  const computeOptions = useComputeOptions();
@@ -39,6 +44,7 @@ export const ArticlePage = React.memo(function ({ article }: { article: PageLoad
39
44
  )}
40
45
  </div>
41
46
  <ContentBlocks pageKind={article.kind} mdast={article.mdast as GenericParent} />
47
+ <ConnectionStatusTray />
42
48
  <Bibliography />
43
49
  {!hide_footer_links && <FooterLinksBlock links={article.footer} />}
44
50
  </NotebookProvider>
@@ -63,7 +63,7 @@ export function Document({
63
63
  <body className="m-0 transition-colors duration-500 bg-white dark:bg-stone-900">
64
64
  <ThemeProvider theme={theme} renderers={renderers} {...links}>
65
65
  <BaseUrlProvider baseurl={baseurl}>
66
- <ThebeBundleLoaderProvider loadThebeLite>
66
+ <ThebeBundleLoaderProvider loadThebeLite publicPath={baseurl}>
67
67
  <SiteProvider config={config}>
68
68
  <ConfiguredThebeServerProvider>{children}</ConfiguredThebeServerProvider>
69
69
  </SiteProvider>