mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-21 21:16:59 +02:00
feat: allow using pure HTML as label in navbar links (#7079)
Co-authored-by: sebastienlorber <lorber.sebastien@gmail.com>
This commit is contained in:
parent
529d853ab8
commit
bfbc78e52a
5 changed files with 63 additions and 27 deletions
|
@ -112,6 +112,13 @@ describe('themeConfig', () => {
|
||||||
docId: 'intro',
|
docId: 'intro',
|
||||||
label: 'Introduction',
|
label: 'Introduction',
|
||||||
},
|
},
|
||||||
|
// Doc link with HTML as label
|
||||||
|
{
|
||||||
|
type: 'doc',
|
||||||
|
position: 'left',
|
||||||
|
docId: 'intro',
|
||||||
|
html: '<b>Introduction</b>',
|
||||||
|
},
|
||||||
// Regular link
|
// Regular link
|
||||||
{
|
{
|
||||||
to: '/guide/',
|
to: '/guide/',
|
||||||
|
@ -119,6 +126,13 @@ describe('themeConfig', () => {
|
||||||
position: 'left',
|
position: 'left',
|
||||||
activeBaseRegex: '/guide/',
|
activeBaseRegex: '/guide/',
|
||||||
},
|
},
|
||||||
|
// Regular link with HTML as label
|
||||||
|
{
|
||||||
|
to: '/guide/',
|
||||||
|
html: '<b>Guide</b>',
|
||||||
|
position: 'left',
|
||||||
|
activeBaseRegex: '/guide/',
|
||||||
|
},
|
||||||
// Regular dropdown
|
// Regular dropdown
|
||||||
{
|
{
|
||||||
label: 'Community',
|
label: 'Community',
|
||||||
|
@ -136,10 +150,10 @@ describe('themeConfig', () => {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
// Dropdown with name
|
// Dropdown with label as HTML
|
||||||
{
|
{
|
||||||
type: 'dropdown',
|
type: 'dropdown',
|
||||||
label: 'Tools',
|
label: 'Tools <sup>new</sup>',
|
||||||
position: 'left',
|
position: 'left',
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -651,6 +651,7 @@ declare module '@theme/NavbarItem/NavbarNavLink' {
|
||||||
readonly activeBaseRegex?: string;
|
readonly activeBaseRegex?: string;
|
||||||
readonly exact?: boolean;
|
readonly exact?: boolean;
|
||||||
readonly label?: ReactNode;
|
readonly label?: ReactNode;
|
||||||
|
readonly html?: string;
|
||||||
readonly prependBaseUrlToHref?: string;
|
readonly prependBaseUrlToHref?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ export default function NavbarNavLink({
|
||||||
to,
|
to,
|
||||||
href,
|
href,
|
||||||
label,
|
label,
|
||||||
|
html,
|
||||||
activeClassName = '',
|
activeClassName = '',
|
||||||
prependBaseUrlToHref,
|
prependBaseUrlToHref,
|
||||||
...props
|
...props
|
||||||
|
@ -33,32 +34,47 @@ export default function NavbarNavLink({
|
||||||
const isExternalLink = label && href && !isInternalUrl(href);
|
const isExternalLink = label && href && !isInternalUrl(href);
|
||||||
const isDropdownLink = activeClassName === dropdownLinkActiveClass;
|
const isDropdownLink = activeClassName === dropdownLinkActiveClass;
|
||||||
|
|
||||||
|
// Link content is set through html XOR label
|
||||||
|
const linkContentProps = html
|
||||||
|
? {dangerouslySetInnerHTML: {__html: html}}
|
||||||
|
: {
|
||||||
|
children: (
|
||||||
|
<>
|
||||||
|
{label}
|
||||||
|
{isExternalLink && (
|
||||||
|
<IconExternalLink
|
||||||
|
{...(isDropdownLink && {width: 12, height: 12})}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (href) {
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
href={prependBaseUrlToHref ? normalizedHref : href}
|
||||||
|
{...props}
|
||||||
|
{...linkContentProps}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
{...(href
|
to={toUrl}
|
||||||
? {
|
isNavLink
|
||||||
href: prependBaseUrlToHref ? normalizedHref : href,
|
activeClassName={
|
||||||
}
|
!props.className?.includes(activeClassName) ? activeClassName : ''
|
||||||
: {
|
}
|
||||||
isNavLink: true,
|
{...((activeBasePath || activeBaseRegex) && {
|
||||||
activeClassName: !props.className?.includes(activeClassName)
|
isActive: (_match, location) =>
|
||||||
? activeClassName
|
activeBaseRegex
|
||||||
: '',
|
? isRegexpStringMatch(activeBaseRegex, location.pathname)
|
||||||
to: toUrl,
|
: location.pathname.startsWith(activeBaseUrl),
|
||||||
...(activeBasePath || activeBaseRegex
|
})}
|
||||||
? {
|
{...props}
|
||||||
isActive: (_match, location) =>
|
{...linkContentProps}
|
||||||
activeBaseRegex
|
/>
|
||||||
? isRegexpStringMatch(activeBaseRegex, location.pathname)
|
|
||||||
: location.pathname.startsWith(activeBaseUrl),
|
|
||||||
}
|
|
||||||
: null),
|
|
||||||
})}
|
|
||||||
{...props}>
|
|
||||||
{label}
|
|
||||||
{isExternalLink && (
|
|
||||||
<IconExternalLink {...(isDropdownLink && {width: 12, height: 12})} />
|
|
||||||
)}
|
|
||||||
</Link>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,8 +49,10 @@ const NavbarItemPosition = Joi.string().equal('left', 'right').default('left');
|
||||||
|
|
||||||
const NavbarItemBaseSchema = Joi.object({
|
const NavbarItemBaseSchema = Joi.object({
|
||||||
label: Joi.string(),
|
label: Joi.string(),
|
||||||
|
html: Joi.string(),
|
||||||
className: Joi.string(),
|
className: Joi.string(),
|
||||||
})
|
})
|
||||||
|
.nand('html', 'label')
|
||||||
// We allow any unknown attributes on the links (users may need additional
|
// We allow any unknown attributes on the links (users may need additional
|
||||||
// attributes like target, aria-role, data-customAttribute...)
|
// attributes like target, aria-role, data-customAttribute...)
|
||||||
.unknown();
|
.unknown();
|
||||||
|
|
|
@ -259,6 +259,7 @@ Accepted fields:
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| `type` | `'default'` | Optional | Sets the type of this item to a link. |
|
| `type` | `'default'` | Optional | Sets the type of this item to a link. |
|
||||||
| `label` | `string` | **Required** | The name to be shown for this item. |
|
| `label` | `string` | **Required** | The name to be shown for this item. |
|
||||||
|
| `html` | `string` | Optional | Same as `label`, but renders pure HTML instead of text content. |
|
||||||
| `to` | `string` | **Required** | Client-side routing, used for navigating within the website. The baseUrl will be automatically prepended to this value. |
|
| `to` | `string` | **Required** | Client-side routing, used for navigating within the website. The baseUrl will be automatically prepended to this value. |
|
||||||
| `href` | `string` | **Required** | A full-page navigation, used for navigating outside of the website. **Only one of `to` or `href` should be used.** |
|
| `href` | `string` | **Required** | A full-page navigation, used for navigating outside of the website. **Only one of `to` or `href` should be used.** |
|
||||||
| `prependBaseUrlToHref` | `boolean` | `false` | Prepends the baseUrl to `href` values. |
|
| `prependBaseUrlToHref` | `boolean` | `false` | Prepends the baseUrl to `href` values. |
|
||||||
|
@ -288,6 +289,8 @@ module.exports = {
|
||||||
// Only one of "to" or "href" should be used
|
// Only one of "to" or "href" should be used
|
||||||
// href: 'https://www.facebook.com',
|
// href: 'https://www.facebook.com',
|
||||||
label: 'Introduction',
|
label: 'Introduction',
|
||||||
|
// Only one of "label" or "html" should be used
|
||||||
|
// html: '<b>Introduction</b>'
|
||||||
position: 'left',
|
position: 'left',
|
||||||
activeBaseRegex: 'docs/(next|v8)',
|
activeBaseRegex: 'docs/(next|v8)',
|
||||||
target: '_blank',
|
target: '_blank',
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue