mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-22 21:47:01 +02:00
feat(v2): add unique page/wrapper className to each theme pages (#4511)
* chore: add theme classnames for blog pages * fix: component syntax error in blog pages * style: fix camelcase issue with theme class names * chore: add theme classnames for doc page and mdx page * chore: make wrapper classnames in blog and doc page into constants * chore: add main wrapper theme class name for layout component * fix: change wrong theme classnames and improve naming * chore: add wrapper theme class name for mdx page * docs: add docs for theme class names * docs: use raw-loader to import documentation and add some comments * docs: provide more detail to comment * chore: rename ThemeClassname.ts to ThemeClassName.ts Co-authored-by: Lisa Chandra <52909743+lisa761@users.noreply.github.com> Co-authored-by: Javid <singularity.javid@gmail.com>
This commit is contained in:
parent
db79d462ab
commit
cd47d8a815
11 changed files with 67 additions and 10 deletions
|
@ -13,6 +13,7 @@ import BlogPostItem from '@theme/BlogPostItem';
|
||||||
import BlogListPaginator from '@theme/BlogListPaginator';
|
import BlogListPaginator from '@theme/BlogListPaginator';
|
||||||
import type {Props} from '@theme/BlogListPage';
|
import type {Props} from '@theme/BlogListPage';
|
||||||
import BlogSidebar from '@theme/BlogSidebar';
|
import BlogSidebar from '@theme/BlogSidebar';
|
||||||
|
import {ThemeClassNames} from '@docusaurus/theme-common';
|
||||||
|
|
||||||
function BlogListPage(props: Props): JSX.Element {
|
function BlogListPage(props: Props): JSX.Element {
|
||||||
const {metadata, items, sidebar} = props;
|
const {metadata, items, sidebar} = props;
|
||||||
|
@ -26,7 +27,8 @@ function BlogListPage(props: Props): JSX.Element {
|
||||||
<Layout
|
<Layout
|
||||||
title={title}
|
title={title}
|
||||||
description={blogDescription}
|
description={blogDescription}
|
||||||
wrapperClassName="blog-wrapper"
|
wrapperClassName={ThemeClassNames.wrapper.blogPages}
|
||||||
|
pageClassName={ThemeClassNames.page.blogListPage}
|
||||||
searchMetadatas={{
|
searchMetadatas={{
|
||||||
// assign unique search tag to exclude this page from search results!
|
// assign unique search tag to exclude this page from search results!
|
||||||
tag: 'blog_posts_list',
|
tag: 'blog_posts_list',
|
||||||
|
|
|
@ -13,6 +13,7 @@ import type {Props} from '@theme/BlogPostPage';
|
||||||
import BlogSidebar from '@theme/BlogSidebar';
|
import BlogSidebar from '@theme/BlogSidebar';
|
||||||
import TOC from '@theme/TOC';
|
import TOC from '@theme/TOC';
|
||||||
import EditThisPage from '@theme/EditThisPage';
|
import EditThisPage from '@theme/EditThisPage';
|
||||||
|
import {ThemeClassNames} from '@docusaurus/theme-common';
|
||||||
|
|
||||||
function BlogPostPage(props: Props): JSX.Element {
|
function BlogPostPage(props: Props): JSX.Element {
|
||||||
const {content: BlogPostContents, sidebar} = props;
|
const {content: BlogPostContents, sidebar} = props;
|
||||||
|
@ -24,7 +25,8 @@ function BlogPostPage(props: Props): JSX.Element {
|
||||||
<Layout
|
<Layout
|
||||||
title={title}
|
title={title}
|
||||||
description={description}
|
description={description}
|
||||||
wrapperClassName="blog-wrapper">
|
wrapperClassName={ThemeClassNames.wrapper.blogPages}
|
||||||
|
pageClassName={ThemeClassNames.page.blogPostPage}>
|
||||||
{BlogPostContents && (
|
{BlogPostContents && (
|
||||||
<div className="container margin-vert--lg">
|
<div className="container margin-vert--lg">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
|
|
|
@ -12,6 +12,7 @@ import Link from '@docusaurus/Link';
|
||||||
import type {Props} from '@theme/BlogTagsListPage';
|
import type {Props} from '@theme/BlogTagsListPage';
|
||||||
import BlogSidebar from '@theme/BlogSidebar';
|
import BlogSidebar from '@theme/BlogSidebar';
|
||||||
import Translate from '@docusaurus/Translate';
|
import Translate from '@docusaurus/Translate';
|
||||||
|
import {ThemeClassNames} from '@docusaurus/theme-common';
|
||||||
|
|
||||||
function getCategoryOfTag(tag: string) {
|
function getCategoryOfTag(tag: string) {
|
||||||
// tag's category should be customizable
|
// tag's category should be customizable
|
||||||
|
@ -54,7 +55,8 @@ function BlogTagsListPage(props: Props): JSX.Element {
|
||||||
<Layout
|
<Layout
|
||||||
title="Tags"
|
title="Tags"
|
||||||
description="Blog Tags"
|
description="Blog Tags"
|
||||||
wrapperClassName="blog-wrapper"
|
wrapperClassName={ThemeClassNames.wrapper.blogPages}
|
||||||
|
pageClassName={ThemeClassNames.page.blogTagsListPage}
|
||||||
searchMetadatas={{
|
searchMetadatas={{
|
||||||
// assign unique search tag to exclude this page from search results!
|
// assign unique search tag to exclude this page from search results!
|
||||||
tag: 'blog_tags_list',
|
tag: 'blog_tags_list',
|
||||||
|
|
|
@ -13,7 +13,7 @@ import Link from '@docusaurus/Link';
|
||||||
import type {Props} from '@theme/BlogTagsPostsPage';
|
import type {Props} from '@theme/BlogTagsPostsPage';
|
||||||
import BlogSidebar from '@theme/BlogSidebar';
|
import BlogSidebar from '@theme/BlogSidebar';
|
||||||
import Translate, {translate} from '@docusaurus/Translate';
|
import Translate, {translate} from '@docusaurus/Translate';
|
||||||
import {usePluralForm} from '@docusaurus/theme-common';
|
import {ThemeClassNames, usePluralForm} from '@docusaurus/theme-common';
|
||||||
|
|
||||||
// Very simple pluralization: probably good enough for now
|
// Very simple pluralization: probably good enough for now
|
||||||
function useBlogPostsPlural() {
|
function useBlogPostsPlural() {
|
||||||
|
@ -59,7 +59,8 @@ function BlogTagsPostPage(props: Props): JSX.Element {
|
||||||
<Layout
|
<Layout
|
||||||
title={`Posts tagged "${tagName}"`}
|
title={`Posts tagged "${tagName}"`}
|
||||||
description={`Blog | Tagged "${tagName}"`}
|
description={`Blog | Tagged "${tagName}"`}
|
||||||
wrapperClassName="blog-wrapper"
|
wrapperClassName={ThemeClassNames.wrapper.blogPages}
|
||||||
|
pageClassName={ThemeClassNames.page.blogTagsPostPage}
|
||||||
searchMetadatas={{
|
searchMetadatas={{
|
||||||
// assign unique search tag to exclude this page from search results!
|
// assign unique search tag to exclude this page from search results!
|
||||||
tag: 'blog_tags_posts',
|
tag: 'blog_tags_posts',
|
||||||
|
|
|
@ -23,7 +23,7 @@ import {translate} from '@docusaurus/Translate';
|
||||||
|
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import styles from './styles.module.css';
|
import styles from './styles.module.css';
|
||||||
import {docVersionSearchTag} from '@docusaurus/theme-common';
|
import {ThemeClassNames, docVersionSearchTag} from '@docusaurus/theme-common';
|
||||||
|
|
||||||
type DocPageContentProps = {
|
type DocPageContentProps = {
|
||||||
readonly currentDocRoute: DocumentRoute;
|
readonly currentDocRoute: DocumentRoute;
|
||||||
|
@ -54,7 +54,8 @@ function DocPageContent({
|
||||||
return (
|
return (
|
||||||
<Layout
|
<Layout
|
||||||
key={isClient}
|
key={isClient}
|
||||||
wrapperClassName="main-docs-wrapper"
|
wrapperClassName={ThemeClassNames.wrapper.docPages}
|
||||||
|
pageClassName={ThemeClassNames.page.docPage}
|
||||||
searchMetadatas={{
|
searchMetadatas={{
|
||||||
version,
|
version,
|
||||||
tag: docVersionSearchTag(pluginId, version),
|
tag: docVersionSearchTag(pluginId, version),
|
||||||
|
|
|
@ -15,10 +15,11 @@ import LayoutProviders from '@theme/LayoutProviders';
|
||||||
import LayoutHead from '@theme/LayoutHead';
|
import LayoutHead from '@theme/LayoutHead';
|
||||||
import type {Props} from '@theme/Layout';
|
import type {Props} from '@theme/Layout';
|
||||||
import useKeyboardNavigation from '@theme/hooks/useKeyboardNavigation';
|
import useKeyboardNavigation from '@theme/hooks/useKeyboardNavigation';
|
||||||
|
import {ThemeClassNames} from '@docusaurus/theme-common';
|
||||||
import './styles.css';
|
import './styles.css';
|
||||||
|
|
||||||
function Layout(props: Props): JSX.Element {
|
function Layout(props: Props): JSX.Element {
|
||||||
const {children, noFooter, wrapperClassName} = props;
|
const {children, noFooter, wrapperClassName, pageClassName} = props;
|
||||||
|
|
||||||
useKeyboardNavigation();
|
useKeyboardNavigation();
|
||||||
|
|
||||||
|
@ -32,7 +33,14 @@ function Layout(props: Props): JSX.Element {
|
||||||
|
|
||||||
<Navbar />
|
<Navbar />
|
||||||
|
|
||||||
<div className={clsx('main-wrapper', wrapperClassName)}>{children}</div>
|
<div
|
||||||
|
className={clsx(
|
||||||
|
ThemeClassNames.wrapper.main,
|
||||||
|
wrapperClassName,
|
||||||
|
pageClassName,
|
||||||
|
)}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
|
||||||
{!noFooter && <Footer />}
|
{!noFooter && <Footer />}
|
||||||
</LayoutProviders>
|
</LayoutProviders>
|
||||||
|
|
|
@ -11,6 +11,7 @@ import {MDXProvider} from '@mdx-js/react';
|
||||||
import MDXComponents from '@theme/MDXComponents';
|
import MDXComponents from '@theme/MDXComponents';
|
||||||
import type {Props} from '@theme/MDXPage';
|
import type {Props} from '@theme/MDXPage';
|
||||||
import TOC from '@theme/TOC';
|
import TOC from '@theme/TOC';
|
||||||
|
import {ThemeClassNames} from '@docusaurus/theme-common';
|
||||||
|
|
||||||
function MDXPage(props: Props): JSX.Element {
|
function MDXPage(props: Props): JSX.Element {
|
||||||
const {content: MDXPageContent} = props;
|
const {content: MDXPageContent} = props;
|
||||||
|
@ -29,7 +30,8 @@ function MDXPage(props: Props): JSX.Element {
|
||||||
title={title}
|
title={title}
|
||||||
description={description}
|
description={description}
|
||||||
permalink={permalink}
|
permalink={permalink}
|
||||||
wrapperClassName={wrapperClassName}>
|
wrapperClassName={wrapperClassName ?? ThemeClassNames.wrapper.mdxPages}
|
||||||
|
pageClassName={ThemeClassNames.page.mdxPage}>
|
||||||
<main>
|
<main>
|
||||||
<div className="container container--fluid">
|
<div className="container container--fluid">
|
||||||
<div className="margin-vert--lg padding-vert--lg">
|
<div className="margin-vert--lg padding-vert--lg">
|
||||||
|
|
|
@ -249,6 +249,7 @@ declare module '@theme/Layout' {
|
||||||
keywords?: string | string[];
|
keywords?: string | string[];
|
||||||
permalink?: string;
|
permalink?: string;
|
||||||
wrapperClassName?: string;
|
wrapperClassName?: string;
|
||||||
|
pageClassName?: string;
|
||||||
searchMetadatas?: {
|
searchMetadatas?: {
|
||||||
version?: string;
|
version?: string;
|
||||||
tag?: string;
|
tag?: string;
|
||||||
|
|
|
@ -38,3 +38,5 @@ export {
|
||||||
} from './utils/docsPreferredVersion/useDocsPreferredVersion';
|
} from './utils/docsPreferredVersion/useDocsPreferredVersion';
|
||||||
|
|
||||||
export {DocsPreferredVersionContextProvider} from './utils/docsPreferredVersion/DocsPreferredVersionProvider';
|
export {DocsPreferredVersionContextProvider} from './utils/docsPreferredVersion/DocsPreferredVersionProvider';
|
||||||
|
|
||||||
|
export {ThemeClassNames} from './utils/ThemeClassNames';
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// These class names are used to style page layouts in Docusaurus
|
||||||
|
export const ThemeClassNames = {
|
||||||
|
page: {
|
||||||
|
blogListPage: 'blog-list-page',
|
||||||
|
blogPostPage: 'blog-post-page',
|
||||||
|
blogTagsListPage: 'blog-tags-list-page',
|
||||||
|
blogTagsPostPage: 'blog-tags-post-page',
|
||||||
|
docPage: 'doc-page',
|
||||||
|
mdxPage: 'mdx-page',
|
||||||
|
},
|
||||||
|
wrapper: {
|
||||||
|
main: 'main-wrapper',
|
||||||
|
blogPages: 'blog-wrapper',
|
||||||
|
docPages: 'main-docs-wrapper',
|
||||||
|
mdxPages: 'mdx-wrapper',
|
||||||
|
},
|
||||||
|
};
|
|
@ -101,6 +101,18 @@ function MyComponent() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Theme Class Names
|
||||||
|
|
||||||
|
We provide some predefined CSS class names to provide access for developers to style layout of a page globally in Docusaurus. The purpose is to have stable classnames shared by all themes that are meant to be targeted by custom CSS.
|
||||||
|
|
||||||
|
import ThemeClassNamesCode from '!!raw-loader!@site/../packages/docusaurus-theme-common/src/utils/ThemeClassNames.ts'; import CodeBlock from '@theme/CodeBlock';
|
||||||
|
|
||||||
|
<CodeBlock className="language-ts">
|
||||||
|
{ThemeClassNamesCode
|
||||||
|
.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g,'')
|
||||||
|
.trim()}
|
||||||
|
</CodeBlock>
|
||||||
|
|
||||||
### CSS modules {#css-modules}
|
### CSS modules {#css-modules}
|
||||||
|
|
||||||
To style your components using [CSS Modules](https://github.com/css-modules/css-modules), name your stylesheet files with the `.module.css` suffix (e.g. `welcome.module.css`). webpack will load such CSS files as CSS modules and you have to reference the class names from the imported CSS module (as opposed to using plain strings). This is similar to the convention used in [Create React App](https://facebook.github.io/create-react-app/docs/adding-a-css-modules-stylesheet).
|
To style your components using [CSS Modules](https://github.com/css-modules/css-modules), name your stylesheet files with the `.module.css` suffix (e.g. `welcome.module.css`). webpack will load such CSS files as CSS modules and you have to reference the class names from the imported CSS module (as opposed to using plain strings). This is similar to the convention used in [Create React App](https://facebook.github.io/create-react-app/docs/adding-a-css-modules-stylesheet).
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue