@myst-theme/site 0.5.2 → 0.5.4

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.5.2",
3
+ "version": "0.5.4",
4
4
  "main": "./src/index.ts",
5
5
  "types": "./src/index.ts",
6
6
  "files": [
@@ -16,18 +16,18 @@
16
16
  "dependencies": {
17
17
  "@headlessui/react": "^1.7.15",
18
18
  "@heroicons/react": "^2.0.18",
19
- "@myst-theme/diagrams": "^0.5.2",
20
- "@myst-theme/frontmatter": "^0.5.2",
21
- "@myst-theme/jupyter": "^0.5.2",
22
- "@myst-theme/common": "^0.5.2",
23
- "@myst-theme/providers": "^0.5.2",
19
+ "@myst-theme/diagrams": "^0.5.4",
20
+ "@myst-theme/frontmatter": "^0.5.4",
21
+ "@myst-theme/jupyter": "^0.5.4",
22
+ "@myst-theme/common": "^0.5.4",
23
+ "@myst-theme/providers": "^0.5.4",
24
24
  "classnames": "^2.3.2",
25
25
  "lodash.throttle": "^4.1.1",
26
26
  "myst-common": "^1.1.1",
27
27
  "myst-spec-ext": "^1.1.1",
28
28
  "myst-config": "^1.1.1",
29
- "myst-demo": "^0.5.2",
30
- "myst-to-react": "^0.5.2",
29
+ "myst-demo": "^0.5.4",
30
+ "myst-to-react": "^0.5.4",
31
31
  "nbtx": "^0.2.3",
32
32
  "node-cache": "^5.1.2",
33
33
  "node-fetch": "^2.6.11",
@@ -220,7 +220,7 @@ export function useOutlineHeight<T extends HTMLElement = HTMLElement>(
220
220
 
221
221
  export const DocumentOutline = ({
222
222
  outlineRef,
223
- top,
223
+ top = 0,
224
224
  className,
225
225
  selector = SELECTOR,
226
226
  children,
@@ -246,8 +246,8 @@ export const DocumentOutline = ({
246
246
  className,
247
247
  )}
248
248
  style={{
249
- top: top ?? 0,
250
- maxHeight: `calc(100vh - ${(top ?? 0) + 20}px)`,
249
+ top: top,
250
+ maxHeight: `calc(100vh - ${top + 20}px)`,
251
251
  }}
252
252
  >
253
253
  <div className="mb-4 text-sm leading-6 uppercase text-slate-900 dark:text-slate-100">
@@ -280,12 +280,16 @@ export function SupportingDocuments() {
280
280
  to={withBaseurl(`/${p.slug}#main`, baseurl)}
281
281
  prefetch="intent"
282
282
  className={({ isActive }) =>
283
- classNames('no-underline flex self-center', {
283
+ classNames('no-underline flex self-center hover:text-blue-700', {
284
284
  'text-blue-600': isActive,
285
285
  })
286
286
  }
287
287
  >
288
- <DocumentChartBarIcon className="inline h-5 pr-2 shrink-0" />
288
+ <DocumentChartBarIcon
289
+ width="1.25rem"
290
+ height="1.25rem"
291
+ className="inline mr-2 shrink-0"
292
+ />
289
293
  <span>{p.short_title || p.title}</span>
290
294
  </NavLink>
291
295
  </li>
@@ -21,14 +21,22 @@ const FooterLink = ({
21
21
  >
22
22
  <div className="flex h-full align-middle">
23
23
  {right && (
24
- <ArrowLeftIcon className="self-center w-6 h-6 transition-transform group-hover:-translate-x-1 shrink-0" />
24
+ <ArrowLeftIcon
25
+ width="1.5rem"
26
+ height="1.5rem"
27
+ className="self-center transition-transform group-hover:-translate-x-1 shrink-0"
28
+ />
25
29
  )}
26
30
  <div className={classNames('flex-grow', { 'text-right': right })}>
27
31
  <div className="text-xs text-gray-500 dark:text-gray-400">{group || ' '}</div>
28
32
  {short_title || title}
29
33
  </div>
30
34
  {!right && (
31
- <ArrowRightIcon className="self-center w-6 h-6 transition-transform group-hover:translate-x-1 shrink-0" />
35
+ <ArrowRightIcon
36
+ width="1.5rem"
37
+ height="1.5rem"
38
+ className="self-center transition-transform group-hover:translate-x-1 shrink-0"
39
+ />
32
40
  )}
33
41
  </div>
34
42
  </Link>
@@ -8,67 +8,99 @@ import {
8
8
  import { useGridSystemProvider } from '@myst-theme/providers';
9
9
  import classNames from 'classnames';
10
10
  import type { PageFrontmatter } from 'myst-frontmatter';
11
+ import { ThemeButton } from './Navigation';
11
12
 
12
13
  export function ArticleHeader({
13
14
  frontmatter,
14
15
  children,
16
+ toggleTheme,
15
17
  className,
16
18
  }: {
17
19
  frontmatter: PageFrontmatter;
18
20
  children?: React.ReactNode;
21
+ toggleTheme?: boolean;
19
22
  className?: string;
20
23
  }) {
21
24
  const grid = useGridSystemProvider();
22
25
  const { subject, venue, biblio, ...rest } = frontmatter ?? {};
26
+ const positionBackground = {
27
+ 'col-page-right': grid === 'article-left-grid',
28
+ 'col-page': grid === 'article-grid',
29
+ };
30
+ const positionFrontmatter = {
31
+ 'col-body': grid === 'article-left-grid',
32
+ 'col-page-left': grid === 'article-grid',
33
+ };
23
34
  return (
24
- <header
25
- className={classNames(
26
- 'w-full relative pt-[2rem] col-screen article',
27
- grid,
28
- 'subgrid-gap',
29
- {
30
- 'bg-no-repeat bg-cover bg-top': frontmatter?.banner,
31
- 'pb-[4rem]': frontmatter?.banner,
32
- },
33
- className,
34
- )}
35
- style={{
36
- backgroundImage: frontmatter?.banner ? `url(${frontmatter?.banner})` : undefined,
37
- }}
38
- >
35
+ <header className="relative col-screen">
39
36
  {frontmatter?.banner && (
40
- <div className="absolute border-white shadow-2xl bg-white/80 dark:bg-black/80 backdrop-blur top-[2rem] h-[calc(100%-4rem)] w-full col-screen md:col-screen-inset pointer-events-none"></div>
37
+ // This is the banner contained in a full-bleed div
38
+ <div
39
+ className={classNames(
40
+ 'absolute',
41
+ grid,
42
+ 'subgrid-gap col-screen bg-no-repeat bg-cover bg-top w-full h-full -z-10 pointer-events-none',
43
+ )}
44
+ style={{
45
+ backgroundImage: `url(${frontmatter?.banner})`,
46
+ }}
47
+ >
48
+ <div
49
+ className={classNames(
50
+ 'absolute border-white shadow-2xl bg-white/80 dark:bg-black/80 backdrop-blur',
51
+ 'w-full',
52
+ 'top-[2rem] h-[calc(100%-4rem)] md:top-[4rem] md:h-[calc(100%-8rem)]',
53
+ positionBackground,
54
+ )}
55
+ />
56
+ </div>
41
57
  )}
42
58
  <div
43
- className={classNames('flex w-full align-middle z-10 py-2 mb-[1rem] text-sm', {
44
- 'col-screen md:col-screen-inset px-4': frontmatter?.banner,
45
- 'col-page-right': !frontmatter?.banner,
46
- 'bg-white/80 dark:bg-black/80': frontmatter?.banner,
47
- })}
59
+ className={classNames(
60
+ 'w-full relative col-screen article',
61
+ grid,
62
+ 'subgrid-gap',
63
+ {
64
+ 'my-[2rem] pb-[2rem] md:my-[4rem]': frontmatter?.banner,
65
+ 'my-[2rem]': !frontmatter?.banner,
66
+ },
67
+ className,
68
+ )}
48
69
  >
49
- {subject && (
50
- <div
51
- className={classNames('flex-none pr-2 smallcaps', {
52
- 'border-r mr-2': venue,
53
- })}
54
- >
55
- {subject}
70
+ <div
71
+ className={classNames('flex w-full align-middle py-2 mb-[1rem] text-sm', {
72
+ 'px-4 w-full': frontmatter?.banner,
73
+ 'bg-white/80 dark:bg-black/80': frontmatter?.banner,
74
+ ...positionBackground,
75
+ })}
76
+ >
77
+ {subject && (
78
+ <div
79
+ className={classNames('flex-none pr-2 smallcaps', {
80
+ 'border-r mr-2': venue,
81
+ })}
82
+ >
83
+ {subject}
84
+ </div>
85
+ )}
86
+ <Journal venue={venue} biblio={biblio} />
87
+ <div className="flex-grow"></div>
88
+ <div className="hidden sm:block">
89
+ <LicenseBadges license={frontmatter?.license} />
90
+ <OpenAccessBadge open_access={frontmatter?.open_access} />
91
+ <GitHubLink github={frontmatter?.github} />
56
92
  </div>
57
- )}
58
- <Journal venue={venue} biblio={biblio} />
59
- <div className="flex-grow"></div>
60
- <LicenseBadges license={frontmatter?.license} />
61
- <OpenAccessBadge open_access={frontmatter?.open_access} />
62
- <GitHubLink github={frontmatter?.github} />
93
+ {toggleTheme && <ThemeButton className="inline-block w-5 h-5 mt-0.5 ml-1" />}
94
+ </div>
95
+ <FrontmatterBlock
96
+ frontmatter={rest}
97
+ authorStyle="list"
98
+ className={classNames({ 'pt-4 px-6': frontmatter?.banner, ...positionFrontmatter })}
99
+ hideBadges
100
+ hideExports
101
+ />
102
+ {children}
63
103
  </div>
64
- <FrontmatterBlock
65
- frontmatter={rest}
66
- authorStyle="list"
67
- className={classNames('z-10', { 'pt-4': frontmatter?.banner })}
68
- hideBadges
69
- hideExports
70
- />
71
- {children}
72
104
  </header>
73
105
  );
74
106
  }
@@ -1,22 +1,21 @@
1
- import { useNavOpen } from '@myst-theme/providers';
1
+ import { useNavOpen, useThemeTop } from '@myst-theme/providers';
2
2
  import { TableOfContents } from './TableOfContents';
3
3
 
4
4
  export function Navigation({
5
5
  children,
6
6
  projectSlug,
7
- top,
8
7
  tocRef,
9
8
  hide_toc,
10
9
  footer,
11
10
  }: {
12
11
  children?: React.ReactNode;
13
12
  projectSlug?: string;
14
- top?: number;
15
13
  tocRef?: React.RefObject<HTMLDivElement>;
16
14
  hide_toc?: boolean;
17
15
  footer?: React.ReactNode;
18
16
  }) {
19
17
  const [open, setOpen] = useNavOpen();
18
+ const top = useThemeTop();
20
19
  if (hide_toc) return <>{children}</>;
21
20
  return (
22
21
  <>
@@ -28,7 +27,7 @@ export function Navigation({
28
27
  onClick={() => setOpen(false)}
29
28
  ></div>
30
29
  )}
31
- <TableOfContents tocRef={tocRef} projectSlug={projectSlug} top={top} footer={footer} />
30
+ <TableOfContents tocRef={tocRef} projectSlug={projectSlug} footer={footer} />
32
31
  </>
33
32
  );
34
33
  }
@@ -9,6 +9,7 @@ import {
9
9
  useBaseurl,
10
10
  withBaseurl,
11
11
  useGridSystemProvider,
12
+ useThemeTop,
12
13
  } from '@myst-theme/providers';
13
14
  import { getProjectHeadings, type Heading } from '@myst-theme/common';
14
15
 
@@ -64,6 +65,7 @@ const HeadingLink = ({
64
65
  };
65
66
 
66
67
  const HEADING_CLASSES = 'text-slate-900 leading-5 dark:text-slate-100';
68
+
67
69
  const Headings = ({ folder, headings, sections }: Props) => {
68
70
  const secs = sections || [];
69
71
  return (
@@ -135,23 +137,18 @@ export function useTocHeight<T extends HTMLElement = HTMLElement>(top = 0, inset
135
137
 
136
138
  export const TableOfContents = ({
137
139
  projectSlug,
138
- top,
139
140
  tocRef,
140
141
  footer,
141
142
  }: {
142
- top?: number;
143
143
  tocRef?: React.RefObject<HTMLElement>;
144
144
  projectSlug?: string;
145
145
  footer?: React.ReactNode;
146
146
  }) => {
147
+ const top = useThemeTop();
147
148
  const grid = useGridSystemProvider();
148
149
  const footerRef = useRef<HTMLDivElement>(null);
149
150
  const [open] = useNavOpen();
150
151
  const config = useSiteManifest();
151
- if (!config) return null;
152
- const headings = getProjectHeadings(config, projectSlug, {
153
- addGroups: false,
154
- });
155
152
  useEffect(() => {
156
153
  setTimeout(() => {
157
154
  if (!footerRef.current) return;
@@ -159,6 +156,10 @@ export const TableOfContents = ({
159
156
  footerRef.current.style.transform = 'none';
160
157
  }, 500);
161
158
  }, [footerRef]);
159
+ if (!config) return null;
160
+ const headings = getProjectHeadings(config, projectSlug, {
161
+ addGroups: false,
162
+ });
162
163
  if (!headings) return null;
163
164
  return (
164
165
  <div
@@ -170,9 +171,7 @@ export const TableOfContents = ({
170
171
  { hidden: !open },
171
172
  { 'z-30': open },
172
173
  )}
173
- style={{
174
- top: top ?? 0,
175
- }}
174
+ style={{ top }}
176
175
  >
177
176
  <div
178
177
  className={classNames(
@@ -205,3 +204,25 @@ export const TableOfContents = ({
205
204
  </div>
206
205
  );
207
206
  };
207
+
208
+ export const InlineTableOfContents = ({
209
+ projectSlug,
210
+ tocRef,
211
+ className = 'flex-grow overflow-y-auto max-w-[350px]',
212
+ }: {
213
+ projectSlug?: string;
214
+ className?: string;
215
+ tocRef?: React.RefObject<HTMLElement>;
216
+ }) => {
217
+ const config = useSiteManifest();
218
+ if (!config) return null;
219
+ const headings = getProjectHeadings(config, projectSlug, {
220
+ addGroups: false,
221
+ });
222
+ if (!headings) return null;
223
+ return (
224
+ <nav aria-label="Table of Contents" className={className} ref={tocRef}>
225
+ <Headings folder={projectSlug} headings={headings} sections={config?.projects} />
226
+ </nav>
227
+ );
228
+ };
@@ -80,7 +80,11 @@ function NavItem({ item }: { item: SiteNavItem }) {
80
80
  <div className="inline-block">
81
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
- <ChevronDownIcon className="w-5 h-5 ml-2 -mr-1 text-violet-200 hover:text-violet-100" />
83
+ <ChevronDownIcon
84
+ width="1.25rem"
85
+ height="1.25rem"
86
+ className="ml-2 -mr-1 text-violet-200 hover:text-violet-100"
87
+ />
84
88
  </Menu.Button>
85
89
  </div>
86
90
  <Transition
@@ -92,7 +96,7 @@ function NavItem({ item }: { item: SiteNavItem }) {
92
96
  leaveFrom="transform opacity-100 scale-100"
93
97
  leaveTo="transform opacity-0 scale-95"
94
98
  >
95
- <Menu.Items className="absolute w-48 py-1 mt-2 bg-white rounded-sm shadow-lg origin-top-left left-4 ring-1 ring-black ring-opacity-5 focus:outline-none">
99
+ <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
100
  {item.children?.map((action) => (
97
101
  <Menu.Item key={action.url}>
98
102
  {/* This is really ugly, BUT, the action needs to be defined HERE or the click away doesn't work for some reason */}
@@ -147,7 +151,7 @@ function ActionMenu({ actions }: { actions?: SiteManifest['actions'] }) {
147
151
  <Menu.Button className="flex text-sm bg-transparent rounded-full focus:outline-none">
148
152
  <span className="sr-only">Open Menu</span>
149
153
  <div className="flex items-center text-stone-200 hover:text-white">
150
- <EllipsisVerticalIcon className="w-8 h-8 p-1" />
154
+ <EllipsisVerticalIcon width="2rem" height="2rem" className="p-1" />
151
155
  </div>
152
156
  </Menu.Button>
153
157
  </div>
@@ -160,7 +164,7 @@ function ActionMenu({ actions }: { actions?: SiteManifest['actions'] }) {
160
164
  leaveFrom="transform opacity-100 scale-100"
161
165
  leaveTo="transform opacity-0 scale-95"
162
166
  >
163
- <Menu.Items className="absolute right-0 w-48 py-1 mt-2 bg-white rounded-sm shadow-lg origin-top-right ring-1 ring-black ring-opacity-5 focus:outline-none">
167
+ <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
168
  {actions?.map((action) => (
165
169
  <Menu.Item key={action.url}>
166
170
  {({ active }) => (
@@ -251,7 +255,7 @@ export function TopNav() {
251
255
  setOpen(!open);
252
256
  }}
253
257
  >
254
- <MenuIcon className="w-8 h-8 p-1" />
258
+ <MenuIcon width="2rem" height="2rem" className="m-1" />
255
259
  <span className="sr-only">Open Menu</span>
256
260
  </button>
257
261
  </div>
@@ -1,5 +1,5 @@
1
1
  export { ThemeButton } from './ThemeButton';
2
2
  export { TopNav, DEFAULT_NAV_HEIGHT } from './TopNav';
3
3
  export { Navigation } from './Navigation';
4
- export { TableOfContents, useTocHeight } from './TableOfContents';
4
+ export { TableOfContents, InlineTableOfContents, useTocHeight } from './TableOfContents';
5
5
  export { LoadingBar } from './Loading';
@@ -50,7 +50,7 @@ export const ArticlePage = React.memo(function ({
50
50
  <FrontmatterBlock
51
51
  kind={article.kind}
52
52
  frontmatter={article.frontmatter}
53
- className="mb-8"
53
+ className="pt-5 mb-8"
54
54
  />
55
55
  )}
56
56
  {binderUrl && !canCompute && (
@@ -12,7 +12,7 @@ import {
12
12
  Link,
13
13
  NavLink,
14
14
  } from '@remix-run/react';
15
- import { renderers } from '../components';
15
+ import { DEFAULT_NAV_HEIGHT, renderers } from '../components';
16
16
  import { Analytics } from '../seo';
17
17
  import { Error404 } from './Error404';
18
18
  import classNames from 'classnames';
@@ -25,18 +25,18 @@ export function Document({
25
25
  theme,
26
26
  config,
27
27
  title,
28
- scrollTopClass = 'scroll-p-20',
29
28
  staticBuild,
30
29
  baseurl,
30
+ top = DEFAULT_NAV_HEIGHT,
31
31
  }: {
32
32
  children: React.ReactNode;
33
33
  scripts?: React.ReactNode;
34
34
  theme: Theme;
35
35
  config?: SiteManifest;
36
36
  title?: string;
37
- scrollTopClass?: string;
38
37
  staticBuild?: boolean;
39
38
  baseurl?: string;
39
+ top?: number;
40
40
  }) {
41
41
  const links = staticBuild
42
42
  ? {
@@ -48,7 +48,7 @@ export function Document({
48
48
  NavLink: NavLink as any,
49
49
  };
50
50
  return (
51
- <html lang="en" className={classNames(theme, scrollTopClass)}>
51
+ <html lang="en" className={classNames(theme)} style={{ scrollPadding: top }}>
52
52
  <head>
53
53
  <meta charSet="utf-8" />
54
54
  <meta name="viewport" content="width=device-width,initial-scale=1" />
@@ -61,7 +61,7 @@ export function Document({
61
61
  />
62
62
  </head>
63
63
  <body className="m-0 transition-colors duration-500 bg-white dark:bg-stone-900">
64
- <ThemeProvider theme={theme} renderers={renderers} {...links}>
64
+ <ThemeProvider theme={theme} renderers={renderers} {...links} top={top}>
65
65
  <BaseUrlProvider baseurl={baseurl}>
66
66
  <ThebeBundleLoaderProvider loadThebeLite publicPath={baseurl}>
67
67
  <SiteProvider config={config}>