mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-17 19:16:58 +02:00
refactor(theme-classic): split theme footer into smaller components + swizzle config (#6894)
Co-authored-by: Joshua Chen <sidachen2003@gmail.com>
This commit is contained in:
parent
c9ee6e467c
commit
1efc6c6091
14 changed files with 416 additions and 180 deletions
|
@ -37,11 +37,62 @@ export default function getSwizzleConfig(): SwizzleConfig {
|
||||||
},
|
},
|
||||||
Footer: {
|
Footer: {
|
||||||
actions: {
|
actions: {
|
||||||
eject: 'unsafe', // TODO split footer into smaller parts
|
eject: 'safe',
|
||||||
wrap: 'safe',
|
wrap: 'safe',
|
||||||
},
|
},
|
||||||
description: "The footer component of you site's layout",
|
description: "The footer component of you site's layout",
|
||||||
},
|
},
|
||||||
|
'Footer/Copyright': {
|
||||||
|
actions: {
|
||||||
|
eject: 'safe',
|
||||||
|
wrap: 'safe',
|
||||||
|
},
|
||||||
|
description: 'The footer copyright',
|
||||||
|
},
|
||||||
|
'Footer/Layout': {
|
||||||
|
actions: {
|
||||||
|
eject: 'safe',
|
||||||
|
wrap: 'safe',
|
||||||
|
},
|
||||||
|
description: 'The footer main layout component',
|
||||||
|
},
|
||||||
|
'Footer/LinkItem': {
|
||||||
|
actions: {
|
||||||
|
eject: 'safe',
|
||||||
|
wrap: 'safe',
|
||||||
|
},
|
||||||
|
description: 'The footer link item component',
|
||||||
|
},
|
||||||
|
'Footer/Links': {
|
||||||
|
actions: {
|
||||||
|
eject: 'safe',
|
||||||
|
wrap: 'safe',
|
||||||
|
},
|
||||||
|
description: 'The footer component rendering the footer links',
|
||||||
|
},
|
||||||
|
'Footer/Links/MultiColumn': {
|
||||||
|
actions: {
|
||||||
|
eject: 'safe',
|
||||||
|
wrap: 'safe',
|
||||||
|
},
|
||||||
|
description:
|
||||||
|
'The footer component rendering the footer links with a multi-column layout',
|
||||||
|
},
|
||||||
|
'Footer/Links/Simple': {
|
||||||
|
actions: {
|
||||||
|
eject: 'safe',
|
||||||
|
wrap: 'safe',
|
||||||
|
},
|
||||||
|
description:
|
||||||
|
'The footer component rendering the footer links with a simple layout (single row)',
|
||||||
|
},
|
||||||
|
'Footer/Logo': {
|
||||||
|
actions: {
|
||||||
|
eject: 'safe',
|
||||||
|
wrap: 'safe',
|
||||||
|
},
|
||||||
|
description: 'The footer logo',
|
||||||
|
},
|
||||||
IconArrow: {
|
IconArrow: {
|
||||||
actions: {
|
actions: {
|
||||||
eject: 'safe',
|
eject: 'safe',
|
||||||
|
|
|
@ -205,7 +205,7 @@ declare module '@theme/DocSidebar/Desktop/Content' {
|
||||||
readonly sidebar: readonly PropSidebarItem[];
|
readonly sidebar: readonly PropSidebarItem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function CollapseButton(props: Props): JSX.Element;
|
export default function Content(props: Props): JSX.Element;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module '@theme/DocSidebar/Desktop/CollapseButton' {
|
declare module '@theme/DocSidebar/Desktop/CollapseButton' {
|
||||||
|
@ -280,6 +280,77 @@ declare module '@theme/Footer' {
|
||||||
export default function Footer(): JSX.Element | null;
|
export default function Footer(): JSX.Element | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module '@theme/Footer/Logo' {
|
||||||
|
import type {FooterLogo} from '@docusaurus/theme-common';
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
logo: FooterLogo;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function FooterLogo(props: Props): JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@theme/Footer/Copyright' {
|
||||||
|
export interface Props {
|
||||||
|
copyright: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function FooterCopyright(props: Props): JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@theme/Footer/LinkItem' {
|
||||||
|
import type {FooterLinkItem} from '@docusaurus/theme-common';
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
item: FooterLinkItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function FooterLinkItem(props: Props): JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@theme/Footer/Layout' {
|
||||||
|
import type {ReactNode} from 'react';
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
style: 'light' | 'dark';
|
||||||
|
links: ReactNode;
|
||||||
|
logo: ReactNode;
|
||||||
|
copyright: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function FooterLayout(props: Props): JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@theme/Footer/Links' {
|
||||||
|
import type {Footer} from '@docusaurus/theme-common';
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
links: Footer['links'];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function FooterLinks(props: Props): JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@theme/Footer/Links/MultiColumn' {
|
||||||
|
import type {MultiColumnFooter} from '@docusaurus/theme-common';
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
columns: MultiColumnFooter['links'];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function FooterLinksMultiColumn(props: Props): JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@theme/Footer/Links/Simple' {
|
||||||
|
import type {SimpleFooter} from '@docusaurus/theme-common';
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
links: SimpleFooter['links'];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function FooterLinksSimple(props: Props): JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
declare module '@theme/Heading' {
|
declare module '@theme/Heading' {
|
||||||
import type {ComponentProps} from 'react';
|
import type {ComponentProps} from 'react';
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import type {Props} from '@theme/Footer/Copyright';
|
||||||
|
|
||||||
|
export default function FooterCopyright({copyright}: Props): JSX.Element {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="footer__copyright"
|
||||||
|
// Developer provided the HTML, so assume it's safe.
|
||||||
|
// eslint-disable-next-line react/no-danger
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: copyright,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import type {Props} from '@theme/Footer/Layout';
|
||||||
|
|
||||||
|
export default function FooterLayout({
|
||||||
|
style,
|
||||||
|
links,
|
||||||
|
logo,
|
||||||
|
copyright,
|
||||||
|
}: Props): JSX.Element {
|
||||||
|
return (
|
||||||
|
<footer
|
||||||
|
className={clsx('footer', {
|
||||||
|
'footer--dark': style === 'dark',
|
||||||
|
})}>
|
||||||
|
<div className="container container-fluid">
|
||||||
|
{links}
|
||||||
|
{(logo || copyright) && (
|
||||||
|
<div className="footer__bottom text--center">
|
||||||
|
{logo && <div className="margin-bottom--sm">{logo}</div>}
|
||||||
|
{copyright}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import Link from '@docusaurus/Link';
|
||||||
|
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||||
|
import isInternalUrl from '@docusaurus/isInternalUrl';
|
||||||
|
import IconExternalLink from '@theme/IconExternalLink';
|
||||||
|
import type {Props} from '@theme/Footer/LinkItem';
|
||||||
|
|
||||||
|
export default function FooterLinkItem({item}: Props): JSX.Element {
|
||||||
|
const {to, href, label, prependBaseUrlToHref, ...props} = item;
|
||||||
|
const toUrl = useBaseUrl(to);
|
||||||
|
const normalizedHref = useBaseUrl(href, {forcePrependBaseUrl: true});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
className="footer__link-item"
|
||||||
|
{...(href
|
||||||
|
? {
|
||||||
|
href: prependBaseUrlToHref ? normalizedHref : href,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
to: toUrl,
|
||||||
|
})}
|
||||||
|
{...props}>
|
||||||
|
<span>
|
||||||
|
{label}
|
||||||
|
{href && !isInternalUrl(href) && <IconExternalLink />}
|
||||||
|
</span>
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import type {Props} from '@theme/Footer/Links/MultiColumn';
|
||||||
|
import LinkItem from '@theme/Footer/LinkItem';
|
||||||
|
|
||||||
|
type ColumnType = Props['columns'][number];
|
||||||
|
type ColumnItemType = ColumnType['items'][number];
|
||||||
|
|
||||||
|
function ColumnLinkItem({item}: {item: ColumnItemType}) {
|
||||||
|
return item.html ? (
|
||||||
|
<li
|
||||||
|
className="footer__item"
|
||||||
|
// Developer provided the HTML, so assume it's safe.
|
||||||
|
// eslint-disable-next-line react/no-danger
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: item.html,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<li key={item.href || item.to} className="footer__item">
|
||||||
|
<LinkItem item={item} />
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Column({column}: {column: ColumnType}) {
|
||||||
|
return (
|
||||||
|
<div className="col footer__col">
|
||||||
|
<div className="footer__title">{column.title}</div>
|
||||||
|
<ul className="footer__items">
|
||||||
|
{column.items.map((item, i) => (
|
||||||
|
<ColumnLinkItem key={i} item={item} />
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function FooterLinksMultiColumn({columns}: Props): JSX.Element {
|
||||||
|
return (
|
||||||
|
<div className="row footer__links">
|
||||||
|
{columns.map((column, i) => (
|
||||||
|
<Column key={i} column={column} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import type {Props} from '@theme/Footer/Links/Simple';
|
||||||
|
import LinkItem from '@theme/Footer/LinkItem';
|
||||||
|
|
||||||
|
function Separator() {
|
||||||
|
return <span className="footer__link-separator">·</span>;
|
||||||
|
}
|
||||||
|
|
||||||
|
function SimpleLinkItem({item}: {item: Props['links'][number]}) {
|
||||||
|
return item.html ? (
|
||||||
|
<span
|
||||||
|
className="footer__link-item"
|
||||||
|
// Developer provided the HTML, so assume it's safe.
|
||||||
|
// eslint-disable-next-line react/no-danger
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: item.html,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<LinkItem item={item} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function FooterLinksSimple({links}: Props): JSX.Element {
|
||||||
|
return (
|
||||||
|
<div className="footer__links text--center">
|
||||||
|
<div className="footer__links">
|
||||||
|
{links.map((item, i) => (
|
||||||
|
<React.Fragment key={i}>
|
||||||
|
<SimpleLinkItem item={item} />
|
||||||
|
{links.length !== i + 1 && <Separator />}
|
||||||
|
</React.Fragment>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import {isMultiColumnFooterLinks} from '@docusaurus/theme-common';
|
||||||
|
import type {Props} from '@theme/Footer/Links';
|
||||||
|
import FooterLinksMultiColumn from '@theme/Footer/Links/MultiColumn';
|
||||||
|
import FooterLinksSimple from '@theme/Footer/Links/Simple';
|
||||||
|
|
||||||
|
export default function FooterLinks({links}: Props): JSX.Element {
|
||||||
|
return isMultiColumnFooterLinks(links) ? (
|
||||||
|
<FooterLinksMultiColumn columns={links} />
|
||||||
|
) : (
|
||||||
|
<FooterLinksSimple links={links} />
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import Link from '@docusaurus/Link';
|
||||||
|
import {useBaseUrlUtils} from '@docusaurus/useBaseUrl';
|
||||||
|
import styles from './styles.module.css';
|
||||||
|
import ThemedImage from '@theme/ThemedImage';
|
||||||
|
import type {Props} from '@theme/Footer/Logo';
|
||||||
|
|
||||||
|
function LogoImage({logo}: Props) {
|
||||||
|
const {withBaseUrl} = useBaseUrlUtils();
|
||||||
|
const sources = {
|
||||||
|
light: withBaseUrl(logo.src),
|
||||||
|
dark: withBaseUrl(logo.srcDark ?? logo.src),
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<ThemedImage
|
||||||
|
className="footer__logo"
|
||||||
|
alt={logo.alt}
|
||||||
|
sources={sources}
|
||||||
|
width={logo.width}
|
||||||
|
height={logo.height}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function FooterLogo({logo}: Props): JSX.Element {
|
||||||
|
return logo.href ? (
|
||||||
|
<Link href={logo.href} className={styles.footerLogoLink}>
|
||||||
|
<LogoImage logo={logo} />
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
<LogoImage logo={logo} />
|
||||||
|
);
|
||||||
|
}
|
|
@ -6,185 +6,27 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import Link from '@docusaurus/Link';
|
import {useThemeConfig} from '@docusaurus/theme-common';
|
||||||
import {
|
import FooterLinks from '@theme/Footer/Links';
|
||||||
type FooterLinkItem,
|
import FooterLogo from '@theme/Footer/Logo';
|
||||||
useThemeConfig,
|
import FooterCopyright from '@theme/Footer/Copyright';
|
||||||
type MultiColumnFooter,
|
import FooterLayout from '@theme/Footer/Layout';
|
||||||
type SimpleFooter,
|
|
||||||
} from '@docusaurus/theme-common';
|
|
||||||
import useBaseUrl, {useBaseUrlUtils} from '@docusaurus/useBaseUrl';
|
|
||||||
import isInternalUrl from '@docusaurus/isInternalUrl';
|
|
||||||
import styles from './styles.module.css';
|
|
||||||
import ThemedImage from '@theme/ThemedImage';
|
|
||||||
import IconExternalLink from '@theme/IconExternalLink';
|
|
||||||
|
|
||||||
function FooterLink({
|
|
||||||
to,
|
|
||||||
href,
|
|
||||||
label,
|
|
||||||
prependBaseUrlToHref,
|
|
||||||
...props
|
|
||||||
}: FooterLinkItem) {
|
|
||||||
const toUrl = useBaseUrl(to);
|
|
||||||
const normalizedHref = useBaseUrl(href, {forcePrependBaseUrl: true});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Link
|
|
||||||
className="footer__link-item"
|
|
||||||
{...(href
|
|
||||||
? {
|
|
||||||
href: prependBaseUrlToHref ? normalizedHref : href,
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
to: toUrl,
|
|
||||||
})}
|
|
||||||
{...props}>
|
|
||||||
<span>
|
|
||||||
{label}
|
|
||||||
{href && !isInternalUrl(href) && <IconExternalLink />}
|
|
||||||
</span>
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function FooterLogo({logo}: {logo: SimpleFooter['logo']}) {
|
|
||||||
const {withBaseUrl} = useBaseUrlUtils();
|
|
||||||
if (!logo?.src) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const sources = {
|
|
||||||
light: withBaseUrl(logo.src),
|
|
||||||
dark: withBaseUrl(logo.srcDark ?? logo.src),
|
|
||||||
};
|
|
||||||
const image = (
|
|
||||||
<ThemedImage
|
|
||||||
className="footer__logo"
|
|
||||||
alt={logo.alt}
|
|
||||||
sources={sources}
|
|
||||||
width={logo.width}
|
|
||||||
height={logo.height}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
<div className="margin-bottom--sm">
|
|
||||||
{logo.href ? (
|
|
||||||
<Link href={logo.href} className={styles.footerLogoLink}>
|
|
||||||
{image}
|
|
||||||
</Link>
|
|
||||||
) : (
|
|
||||||
image
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function MultiColumnLinks({links}: {links: MultiColumnFooter['links']}) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{links.map((linkItem, i) => (
|
|
||||||
<div key={i} className="col footer__col">
|
|
||||||
<div className="footer__title">{linkItem.title}</div>
|
|
||||||
<ul className="footer__items">
|
|
||||||
{linkItem.items.map((item, key) =>
|
|
||||||
item.html ? (
|
|
||||||
<li
|
|
||||||
key={key}
|
|
||||||
className="footer__item"
|
|
||||||
// Developer provided the HTML, so assume it's safe.
|
|
||||||
// eslint-disable-next-line react/no-danger
|
|
||||||
dangerouslySetInnerHTML={{
|
|
||||||
__html: item.html,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<li key={item.href || item.to} className="footer__item">
|
|
||||||
<FooterLink {...item} />
|
|
||||||
</li>
|
|
||||||
),
|
|
||||||
)}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function SimpleLinks({links}: {links: SimpleFooter['links']}) {
|
|
||||||
return (
|
|
||||||
<div className="footer__links">
|
|
||||||
{links.map((item, key) => (
|
|
||||||
<React.Fragment key={key}>
|
|
||||||
{item.html ? (
|
|
||||||
<span
|
|
||||||
className="footer__link-item"
|
|
||||||
// Developer provided the HTML, so assume it's safe.
|
|
||||||
// eslint-disable-next-line react/no-danger
|
|
||||||
dangerouslySetInnerHTML={{
|
|
||||||
__html: item.html,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<FooterLink {...item} />
|
|
||||||
)}
|
|
||||||
{links.length !== key + 1 && (
|
|
||||||
<span className="footer__link-separator">·</span>
|
|
||||||
)}
|
|
||||||
</React.Fragment>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isMultiColumnFooterLinks(
|
|
||||||
links: MultiColumnFooter['links'] | SimpleFooter['links'],
|
|
||||||
): links is MultiColumnFooter['links'] {
|
|
||||||
return 'title' in links[0]!;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Footer(): JSX.Element | null {
|
function Footer(): JSX.Element | null {
|
||||||
const {footer} = useThemeConfig();
|
const {footer} = useThemeConfig();
|
||||||
if (!footer) {
|
if (!footer) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const {copyright, links, logo} = footer;
|
const {copyright, links, logo, style} = footer;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<footer
|
<FooterLayout
|
||||||
className={clsx('footer', {
|
style={style}
|
||||||
'footer--dark': footer.style === 'dark',
|
links={links && links.length > 0 && <FooterLinks links={links} />}
|
||||||
})}>
|
logo={logo && <FooterLogo logo={logo} />}
|
||||||
<div className="container container-fluid">
|
copyright={copyright && <FooterCopyright copyright={copyright} />}
|
||||||
{links &&
|
/>
|
||||||
links.length > 0 &&
|
|
||||||
(isMultiColumnFooterLinks(links) ? (
|
|
||||||
<div className="row footer__links">
|
|
||||||
<MultiColumnLinks links={links} />
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="footer__links text--center">
|
|
||||||
<SimpleLinks links={links} />
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
{(logo || copyright) && (
|
|
||||||
<div className="footer__bottom text--center">
|
|
||||||
<FooterLogo logo={logo} />
|
|
||||||
{copyright && (
|
|
||||||
<div
|
|
||||||
className="footer__copyright"
|
|
||||||
// Developer provided the HTML, so assume it's safe.
|
|
||||||
// eslint-disable-next-line react/no-danger
|
|
||||||
dangerouslySetInnerHTML={{
|
|
||||||
__html: copyright,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ export type {
|
||||||
MultiColumnFooter,
|
MultiColumnFooter,
|
||||||
SimpleFooter,
|
SimpleFooter,
|
||||||
Footer,
|
Footer,
|
||||||
|
FooterLogo,
|
||||||
FooterLinkItem,
|
FooterLinkItem,
|
||||||
ColorModeConfig,
|
ColorModeConfig,
|
||||||
} from './utils/useThemeConfig';
|
} from './utils/useThemeConfig';
|
||||||
|
@ -110,6 +111,8 @@ export {
|
||||||
type TOCTreeNode,
|
type TOCTreeNode,
|
||||||
} from './utils/tocUtils';
|
} from './utils/tocUtils';
|
||||||
|
|
||||||
|
export {isMultiColumnFooterLinks} from './utils/footerUtils';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
ScrollControllerProvider,
|
ScrollControllerProvider,
|
||||||
useScrollController,
|
useScrollController,
|
||||||
|
|
14
packages/docusaurus-theme-common/src/utils/footerUtils.ts
Normal file
14
packages/docusaurus-theme-common/src/utils/footerUtils.ts
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type {MultiColumnFooter, SimpleFooter} from './useThemeConfig';
|
||||||
|
|
||||||
|
export function isMultiColumnFooterLinks(
|
||||||
|
links: MultiColumnFooter['links'] | SimpleFooter['links'],
|
||||||
|
): links is MultiColumnFooter['links'] {
|
||||||
|
return 'title' in links[0]!;
|
||||||
|
}
|
|
@ -65,18 +65,20 @@ export type FooterLinkItem = {
|
||||||
href?: string;
|
href?: string;
|
||||||
html?: string;
|
html?: string;
|
||||||
prependBaseUrlToHref?: string;
|
prependBaseUrlToHref?: string;
|
||||||
|
} & Record<string, unknown>;
|
||||||
|
|
||||||
|
export type FooterLogo = {
|
||||||
|
alt?: string;
|
||||||
|
src: string;
|
||||||
|
srcDark?: string;
|
||||||
|
width?: string | number;
|
||||||
|
height?: string | number;
|
||||||
|
href?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type FooterBase = {
|
export type FooterBase = {
|
||||||
style: 'light' | 'dark';
|
style: 'light' | 'dark';
|
||||||
logo?: {
|
logo?: FooterLogo;
|
||||||
alt?: string;
|
|
||||||
src: string;
|
|
||||||
srcDark?: string;
|
|
||||||
width?: string | number;
|
|
||||||
height?: string | number;
|
|
||||||
href?: string;
|
|
||||||
};
|
|
||||||
copyright?: string;
|
copyright?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue