Open jlvandenhout opened 2 years ago
I mentioned on Discord we should allow type: /custom-.*/
as a pattern, because we'd still like to catch potential mistakes
Hey
We definitively want to support that, and we've discussed it in a few issues already. This is not the navbar, but we'd also want custom items in other places too: doc sidebar, blog sidebar, footer...
This is an important feature requiring a bit of new infra and that we should design well, for which there are various implications (item schema validation, code-splitting, tree-shaking and lazy loading of unused custom item types, server-side-rendering, the ability for a plugin to register item types...).
As we want to launch 2.0 soon, all this is likely to be implemented later.
I mentioned on Discord we should allow type: /custom-.*/ as a pattern, because we'd still like to catch potential mistakes
Agree: in the short term the easiest workaround would be to allow pass-through of a type that starts with custom-
We should extract the component map to @theme/NavbarItem/Components
or something so that it can be easily swizzled and that you can easily add your own components to this map.
And exposing a new hook like useCurrentLayout() === "mobile"
can also be convenient to use in many places where we currently forward a mobile
prop. (useCurrentLayout()
is probably a bad name as even mobile renders both regular navbar (responsive) + mobile navbar (hamburger))
Can this be good enough for now?
we'd also want custom items in other places too
Even better!
in the short term the easiest workaround would be to allow pass-through of a type that starts with custom- We should extract the component map to @theme/NavbarItem/Components or something so that it can be easily swizzled and that you can easily add your own components to this map.
I'll happily start working on a PR for this, I'm not strong on the schema validation logic, but I'll see how far I get. For the name of the map, what do you think of @theme/NavbarItem/ComponentTypeMap
or is that too verbose?
And exposing a new hook like useCurrentLayout() === "mobile" can also be convenient to use in many places where we currently forward a mobile prop. (useCurrentLayout() is probably a bad name as even mobile renders both regular navbar (responsive) + mobile navbar (hamburger))
Looking into the codebase it looks like this is already pretty much covered by the Never mind, that hook won't help. We need a way to determine if we are in a mobile layout or a desktop layout, not if we are currently on mobile or desktop. So yes such a hook would be a nice addition, but how would the hook determine the local layout? What about calling it useWindowSize
hook. What do you think?useLayoutContext()
?
I'll happily start working on a PR for this
I'd rather do this myself asap there are a few things that will end up becoming part of the API surface and I'd like the whole thing (including naming) to be consistent. Sometimes it's faster for me to do things directly instead of delegating and reviewing.
what do you think of @theme/NavbarItem/ComponentTypeMap
If we adopt this naming convenient we'd rather apply it as well in other places (now and future places). See for example MDXComponents
What about calling it
useLayoutContext()
?
That's the initial name I thought using but maybe this will be confusing considering "context" name is associated with React and we already have a Layout component π As this API is likely to be adopted by power users (like you) asap, and become official later once we officially have a config api for custom navbar items, we'd rather find a good name
Here's an initial version to support a custom item type: https://github.com/facebook/docusaurus/pull/7231
I didn't add a useLayoutContext()
API for now. Considering the item receives a mobile?: boolean
prop, I guess you don't really need it and would be just a convenience.
We'll keep this PR open until we have a proper API to register custom components
Note that Ionic doc devs managed to implement custom navbar item types in their site, including validation of custom items: https://github.com/facebook/docusaurus/pull/7231#issuecomment-1112387165
It's a bit hacky but can also be another useful workaround to extend our classic theme
As far as I can tell, this feature has been merged, but I can't find any documention on how to use it. Can anyone share what works for them?
@lukedukeus Have a look at the top post. Sebastian updated it with a recommended workaround. Hope that helps!
Oh, that makes sense, thanks. I didn't think to try that because I assumed it was just a suggestion of how it should work. This can be closed then?
We'll keep this issue open until we provide a first-class API/documentation to achieve this
Until then, the suggested workaround is good enough
There is a bug right now.
if i use custom-navbar, somehow, in the "position:right" navbar items, if they are links, the build shows all navbar items have the last link item's href. but if you run "yarn start", all is good.
@medmin it's really difficult to understand what you mean. Please add a repro, at least a screenshot of dev vs prod + a config sample.
Is this feature still in plan? I want to display an custom avatar component at the most right, but it's not supported yet.
Feature is still planned and one of next features we plan to work on.
The plan is to use a separate client-side file for themeConfig
and let you import React components from there.
In the meantime you shouldn't be blocked, because you can swizzle.
Is there a workaround for a custom doc sidebar component like the custom navbar component in your workaround?
Is there a workaround for a custom doc sidebar component like the custom navbar component in your workaround?
@timothymcmackin all our theme components can be swizzled so technically you can render the sidebar tree the way you want, including hardcoding your own components anywhere in that tree.
If you want to control where your custom components will render in a tree through the sidebars.js
file, I can suggest using the sidebar items custom props alongside swizzling DocSidebarItem
and wrapping it with extra logic:
import React from 'react';
import DocSidebarItem from '@theme-original/DocSidebarItem';
const CustomComponents = {
'my-custom-component': (props) => (
<div style={{ border: 'solid' }}>{JSON.stringify(props)}</div>
),
};
export default function DocSidebarItemWrapper(props) {
const CustomComponent = CustomComponents[props.item?.customProps?.type];
if (CustomComponent) {
return <CustomComponent {...props.item?.customProps?.props} />;
}
return (
<>
<DocSidebarItem {...props} />
</>
);
}
/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
const sidebars = {
tutorialSidebar: [
'intro',
{
type: 'doc',
id: 'intro',
customProps: {
type: 'my-custom-component',
props: { name: 'Hello World', age: 42 },
},
},
{
type: 'category',
label: 'Tutorial',
items: ['tutorial-basics/create-a-document'],
},
],
};
export default sidebars;
Live demo: https://stackblitz.com/edit/github-rvozvb
Yes, this is awkward to use type: 'doc'
for injecting your own custom component, but at least that works and already passes validation. Note in reality you can use any sidebar item type you want, as long as the validation accepts it. In the end you'll remap the rendering of that component to your own custom component so this will be ignored.
Note: we are exploring moving themeConfig
to a separate browser-based file (https://github.com/facebook/docusaurus/pull/9619), which would solve this problem properly. But we are facing some challenges to make it happen. Follow that issue to track progress.
Temporary recommended workaround
Until we have first-class support and a convenient API to support this, here's the recommended way to add custom navbar items to your site (see also #7231)
Create a file in
src/theme/NavbarItem/ComponentTypes.js
to add a custom navbar item type to the existing mapping:
This was very helpful. π
It would be great if this was included in the website docs somewhere, since it took some hunting to find this issue. π
Edit from @slorber:
Temporary recommended workaround
Until we have first-class support and a convenient API to support this, here's the recommended way to add custom navbar items to your site (see also https://github.com/facebook/docusaurus/pull/7231)
Create a file in
src/theme/NavbarItem/ComponentTypes.js
to add a custom navbar item type to the existing mapping:Use it in your config:
Note: using the
custom-
prefix is important: the config validation schema will only allow item types with this prefix.Original issue
Have you read the Contributing Guidelines on issues?
Description
We'd like to propose a way to add custom navbar item components through the navbar items configuration, so they remain part of the regular layout of items in the navbar and mobile primary menu. To our understanding three things need to change:
Adjust the navbar items configuration validation to allow objects with a custom type property and a custom component property, similar to how the docs plugin allows a custom
docItemComponent
property to override the default rendering component. This object should allow arbitrary properties, which are passed as React properties to the custom component.Adjust the
NavbarItem
component to allow for custom types, require their configured custom component and passing any additional custom properties to the custom component.Improve API documentation on how navbar items should distinguish between if they are rendered for mobile or desktop, so the user can properly implement the component in case such a distinction is needed.
Open questions:
Has this been requested on Canny?
No response
Motivation
We've implemented a custom dropdown component, which currently abuses the Docusaurus provided dropdown component configuration to bypass the configuration validation. This worked until beta.17, but from beta.18 onwards our implementation breaks, because of a major refactor in the navbar, which brought us to the point where we would like to propose a properly supported way of adding custom components to the navbar.
API design
Configuration of the custom component in the navbar items configuration:
Have you tried building it?
We tried swizzling the
NavbarItem
component, but we ran into multiple issues, including correctly typing the custom component in the type to component map and configuration validation warnings. We'd be happy to create a PR after discussing the implementation proposed above.Self-service