diff --git a/knip.ts b/knip.ts
index b0e57bc42442..8c45a68d568c 100644
--- a/knip.ts
+++ b/knip.ts
@@ -87,6 +87,7 @@ export default {
'@docusaurus/mdx-loader',
'@docusaurus/types',
'@docusaurus/plugin-content-docs',
+ '@docusaurus/plugin-content-blog/client',
'@docusaurus/theme-search-algolia',
'@docusaurus/ExecutionEnvironment',
'@docusaurus/Link',
@@ -99,7 +100,6 @@ export default {
'^@theme/.*',
'^@theme-original/.*',
'docusaurus-plugin-typedoc',
- 'typedoc',
'typedoc-plugin-markdown',
],
},
diff --git a/packages/website/package.json b/packages/website/package.json
index ea2d02e2d0fc..ee01833b0077 100644
--- a/packages/website/package.json
+++ b/packages/website/package.json
@@ -35,6 +35,7 @@
"prism-react-renderer": "^2.3.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
+ "react-markdown": "^9.0.1",
"react-resizable-panels": "^0.0.63",
"semver": "^7.6.0",
"typedoc": "^0.25.13",
diff --git a/packages/website/src/theme/BlogPostItem/Header/Title/index.tsx b/packages/website/src/theme/BlogPostItem/Header/Title/index.tsx
new file mode 100644
index 000000000000..65088996f60c
--- /dev/null
+++ b/packages/website/src/theme/BlogPostItem/Header/Title/index.tsx
@@ -0,0 +1,22 @@
+import Link from '@docusaurus/Link';
+import { useBlogPost } from '@docusaurus/plugin-content-blog/client';
+import type { Props } from '@theme/BlogPostItem/Header/Title';
+import clsx from 'clsx';
+import React from 'react';
+import Markdown from 'react-markdown';
+
+import styles from './styles.module.css';
+
+export default function BlogPostItemHeaderTitle({
+ className,
+}: Props): React.JSX.Element {
+ const { metadata, isBlogPostPage } = useBlogPost();
+ const { permalink, title: titleRaw } = metadata;
+ const TitleHeading = isBlogPostPage ? 'h1' : 'h2';
+ const title = {titleRaw};
+ return (
+
+ {isBlogPostPage ? title : {title}}
+
+ );
+}
diff --git a/packages/website/src/theme/BlogPostItem/Header/Title/styles.module.css b/packages/website/src/theme/BlogPostItem/Header/Title/styles.module.css
new file mode 100644
index 000000000000..567b9cfafcb5
--- /dev/null
+++ b/packages/website/src/theme/BlogPostItem/Header/Title/styles.module.css
@@ -0,0 +1,18 @@
+.title {
+ font-size: 3rem;
+}
+
+.title code {
+ background: none;
+ border: none;
+ display: inline;
+}
+
+/**
+ Blog post title should be smaller on smaller devices
+**/
+@media screen and (width <= 576px) {
+ .title {
+ font-size: 2rem;
+ }
+}
diff --git a/packages/website/src/theme/BlogSidebar/Content/index.tsx b/packages/website/src/theme/BlogSidebar/Content/index.tsx
new file mode 100644
index 000000000000..589bf6259dd7
--- /dev/null
+++ b/packages/website/src/theme/BlogSidebar/Content/index.tsx
@@ -0,0 +1,66 @@
+import { groupBlogSidebarItemsByYear } from '@docusaurus/plugin-content-blog/client';
+import { useThemeConfig } from '@docusaurus/theme-common';
+import type { Props } from '@theme/BlogSidebar/Content';
+import Heading from '@theme/Heading';
+import type { ReactNode } from 'react';
+import React, { memo } from 'react';
+import Markdown from 'react-markdown';
+
+import styles from './styles.module.css';
+
+function BlogSidebarYearGroup({
+ year,
+ yearGroupHeadingClassName,
+ children,
+}: {
+ year: string;
+ yearGroupHeadingClassName?: string;
+ children: ReactNode;
+}): React.JSX.Element {
+ return (
+
+
+ {year}
+
+ {children}
+
+ );
+}
+
+function BlogSidebarContent({
+ items: itemsRaw,
+ yearGroupHeadingClassName,
+ ListComponent,
+}: Props): ReactNode {
+ const items = itemsRaw.map(item => ({
+ ...item,
+ title: ({item.title}) as unknown as string,
+ }));
+
+ const themeConfig = useThemeConfig();
+
+ if (themeConfig.blog.sidebar.groupByYear) {
+ const itemsByYear = groupBlogSidebarItemsByYear(items);
+ return (
+ <>
+ {itemsByYear.map(([year, yearItems]) => (
+
+
+
+ ))}
+ >
+ );
+ }
+
+ return (
+
+
+
+ );
+}
+
+export default memo(BlogSidebarContent);
diff --git a/packages/website/src/theme/BlogSidebar/Content/styles.module.css b/packages/website/src/theme/BlogSidebar/Content/styles.module.css
new file mode 100644
index 000000000000..c7d3ef61b9d0
--- /dev/null
+++ b/packages/website/src/theme/BlogSidebar/Content/styles.module.css
@@ -0,0 +1,8 @@
+.blogSidebarContent code {
+ background: none;
+ border: none;
+}
+
+.blogSidebarContent p {
+ margin: 0;
+}
diff --git a/yarn.lock b/yarn.lock
index 3dbfdb0e468a..e61cb0a1d696 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -11606,6 +11606,13 @@ __metadata:
languageName: node
linkType: hard
+"html-url-attributes@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "html-url-attributes@npm:3.0.0"
+ checksum: 9f499d33e6ddff6c2d2766fd73d2f22f3c370b4e485a92b0b2938303665b306dc7f36b2724c9466764e8f702351c01f342f5ec933be41a31c1fa40b72087b91d
+ languageName: node
+ linkType: hard
+
"html-void-elements@npm:^3.0.0":
version: 3.0.0
resolution: "html-void-elements@npm:3.0.0"
@@ -16977,6 +16984,27 @@ __metadata:
languageName: node
linkType: hard
+"react-markdown@npm:^9.0.1":
+ version: 9.0.1
+ resolution: "react-markdown@npm:9.0.1"
+ dependencies:
+ "@types/hast": ^3.0.0
+ devlop: ^1.0.0
+ hast-util-to-jsx-runtime: ^2.0.0
+ html-url-attributes: ^3.0.0
+ mdast-util-to-hast: ^13.0.0
+ remark-parse: ^11.0.0
+ remark-rehype: ^11.0.0
+ unified: ^11.0.0
+ unist-util-visit: ^5.0.0
+ vfile: ^6.0.0
+ peerDependencies:
+ "@types/react": ">=18"
+ react: ">=18"
+ checksum: ca1daa650d48b84a5a9771683cdb3f3d2d418247ce0faf73ede3207c65f2a21cdebb9df37afda67f6fc8f0f0a7b9ce00eb239781954a4d6c7ad88ea4df068add
+ languageName: node
+ linkType: hard
+
"react-resizable-panels@npm:^0.0.63":
version: 0.0.63
resolution: "react-resizable-panels@npm:0.0.63"
@@ -20171,6 +20199,7 @@ __metadata:
raw-loader: ^4.0.2
react: ^18.2.0
react-dom: ^18.2.0
+ react-markdown: ^9.0.1
react-resizable-panels: ^0.0.63
rimraf: "*"
semver: ^7.6.0