-
-
Notifications
You must be signed in to change notification settings - Fork 8.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[2.0] RFC: docusaurus swizzle --wrap/copy #5380
Comments
Agreed. I also think a more hierarchical component structure is better than crowding No strong feelings about extending the CLI. I think we can make it fully interactive (just like |
I created a swizzle meta issue here: #6114 We can probably keep this one open to have more focused discussions on this specific topic |
From what I imagine, const content = `
import React from 'react';
import ${component} from '@theme-original/${component}';
export default function Wrapped${component.split('/').at(-1)}(props) {
return (
<>
<${component.split('/').at(-1)} {...props} />
</>
);
}`;
fs.writeFileSync(`src/theme/${component}.js`, content); Anything beyond that? |
@Josh-Cena This will have issues with components that export anything other than a default. For example, wrapping the Heading component requires: import Heading, { MainHeading as OriginalMainHeading } from '@theme-original/Heading';
import React, { Fragment } from 'react';
export default Heading;
export const MainHeading: typeof OriginalMainHeading = ({ ...props }) => <Fragment>
<p>My additionalness.</p>
<OriginalMainHeading {...props} />
</Fragment>; I think the user experience would be better if components that support wrapping only ever export a default. So the Heading component might be separated into two. |
Ah... Yes, thanks for reminding! That would be a bit more troublesome... I think we would refactor that as well |
@slorber What do you think about turning on |
Did some tests and I believe it should technically be possible to support named exports with Still, for our own codebase we only have very few named exports, I'll refactor that and apply the rule We can figure out later for third-party themes, there are probably not a lot of themes out there and it's not the most common customization pattern. For some reasons I don't understand yet (maybe related to CJS/ESM modules config 🤷♂️ ), the following does not work while it should. import React from 'react';
export function MainHeading() {
return <div>test2</div>;
}
export default function HeadingWrapper() {
return <div>test</div>;
} Edit: oh found out: it's because the default export is not a component 😅 Another problem is that when using import {useThemeConfig} from '@docusaurus/theme-common'; In such case the dependency must be explicitly added to the website. Maybe we should automate this and add a console warning to explain why it was added? Another issue is the TypeScript story When using Note that the theme does not expose types for And the This output does not look so good to me, we should try to find something better? import React, {ComponentProps} from 'react';
import Heading from '@theme-original/Heading';
import type HeadingComponentType from '@theme/Heading';
export default function HeadingWrapper(
props: ComponentProps<typeof HeadingComponentType>,
) {
return <Heading {...props} />;
} In this specific case, it's not even good because the export is not a component but a component factory. In such case it's quite impossible to write a wrapper of a higher-order function, it's quite specific to the context and there's no generic way to do so. We can only wrap regular React components in a generic way, and we probably need a way to disable the Another similar case to think about: theme hooks. Do we allow/disallow to wrap them? Do we move all of them to What could a wrapper look like? import useHideableNavbar from "@theme-original/hooks/useHideableNavbar"
export default
function useHideableNavbarWrapper(
...params: Parameters<typeof useHideableNavbar>
): ReturnType<typeof useHideableNavbar> {
return useHideableNavbar(...params);
} That looks quite ugly TS code for the end-user We can't even be sure that the hook returns a value IMHO in general the hooks we have shouldn't be wrapped, but we might have cases later where this might become useful. I'm thinking of We can probably disallow wrapping with the CLI (or fail with a nice error message?) and explain to the user to do the wrapping manually 🤷♂️ |
Not always needed? Extraneous dependencies are bad but don't prevent sites from building unless you are using PnP. Would still be nice to fix it though I would want to move all docs hooks, at least, to theme-common since we already have About TypeScript, I think we can just go with emitting no types for props? Or default to |
Agree, this is not a blocker as it can be fixed manually anyway, just a think to keep in mind.
Yes, that's my next plan to move much more things to theme-common, starting with those hooks. I'll start now but let me know if you want to split the work. |
Great, you can go ahead 👍 I would be relaxing a little |
May not be a blocker to get started. But this means that we enable implicit any on the default config? I think it's better to be strict by default so that swizzle eject users can have type errors when we refactor a theme component's prop, without having to read the changelogs. This can also prevent weird errors where we add a new prop, thinking it's harmless but the user is spreading props to an element that should not receive it. Hopefully someday TS will allow a module to implement an interface: |
🚀 Feature
We have a feature to wrap existing theme components:
https://docusaurus.io/docs/using-themes#wrapping-theme-components
It's a very useful pattern to use to customize your Docusaurus site.
It allows you to enhance a Docusaurus theme without having to copy (and maintain) theme code.
Unfortunately, this feature is not very visible and we don't encourage its usage, as the code above is only found in our doc, and the swizzle CLI command does not produce such code.
Some use-cases:
I suggest to do some changes:
docusaurus swizzle --wrap
option to produce such code. It wouldn't require the usage of--danger
because it's way safer than copying.--copy
option, keep--danger
for unsafe components and suggest to prefer usage of--wrap
--wrap
or--copy
, hint to prefer--wrap
Other changes to consider in the long term:
docusaurus swizzle
to something more intuitive likedocusaurus theme
?The text was updated successfully, but these errors were encountered: