vitepress icon indicating copy to clipboard operation
vitepress copied to clipboard

How to add a custom element next to a specific existing navbar element?

Open jkrumbiegel opened this issue 1 year ago • 3 comments
trafficstars

Is your feature request related to a problem? Please describe.

On our page, we have this navbar section currently: image

I want to have a version selector between Resources and the dark/light toggle preferably. The existing slots nav-bar-title-before, nav-bar-title-after, nav-bar-content-before, nav-bar-content-after can only put elements outside of the navbar flow or at the least not at the position I'd like. I have not found a way yet to splice components into specific places in the layout.

The version picker can only be populated at load time because it has to read a javascript file from the server, so I can't just add it as a normal menu, although I want it to look like one.

Describe the solution you'd like

Ideally I'd want some way to access the navbar elements like an array, putting a custom component into it in a position I decide, without having to clone and modify the complete theme.

Describe alternatives you've considered

I've only found issues where people wanted to replace the elements in the navbar with their own implementations completely, not one where you'd be able to place additional elements.

Additional context

No response

Validations

jkrumbiegel avatar May 29 '24 07:05 jkrumbiegel

Not a stable option, but you can patch VPNavBar.vue using a vite alias / plugin or pnpm patch / patch-package to add an extra component after VPNavBarMenu.

brc-dd avatar May 29 '24 07:05 brc-dd

Not easy, maybe we can add a few more slots (then we'll have some problems with styles): check this PR to add just a new switcher https://github.com/unocss/unocss/pull/3931

userquin avatar Jun 28 '24 20:06 userquin

@jkrumbiegel check https://github.com/vuejs/vitepress/pull/4000 , maybe solves your issue, check https://github.com/vuejs/vitepress/pull/4000/files#diff-a7061f07ab6f5b99e8aa7e4d0c13c357f9bbcc77ce46b99d32b10fd86df8452dR96-R105 (you can include a custom component with the version selector at the end of your nav):

imagen

userquin avatar Jun 29 '24 13:06 userquin

@userquin thanks so much for the link, I tried adding a custom component copying this code https://github.com/vuejs/vitepress/blob/main/tests/e2e/.vitepress/theme/components/NavVersion.vue and the component is rendered correctly, that's great!

I now just have the conceptual problem that I don't know how to populate this version dropdown with data that's only available at load time. Some global javascript variable will be populated with the list of versions from somewhere else, I can't add this information statically in the config file as the example shows as it is not known at build time which versions may exist later.

Do you maybe have a pointer for me?

jkrumbiegel avatar Jul 14 '24 18:07 jkrumbiegel

By load time, I'm guessing you meant when the component is loaded, i.e. on browser? If it's coming from some API, you can just do fetch inside onMounted and map and assign the response data to your versions ref, no need to pass it as a prop. If it's in some global variable, you probably can wait for that variable to be available using setInterval inside onMounted 👀

brc-dd avatar Jul 15 '24 03:07 brc-dd

Yes, in the browser. The way it works is that after the build of our docs, a separate process checks which docs versions are now available in total and populates something like a VERSIONS.js file which is at top-level so like mydomain.com/VERSIONS.js. This way, older docs can still link to newer builds (I didn't come up with this system, just have to comply with it).

I will check if onMounted can help me out, thanks!

jkrumbiegel avatar Jul 15 '24 05:07 jkrumbiegel

Yeah so in this case you should be able to just fetch or import it inside onMounted:

import { ref, onMounted } from 'vue'

const versions = ref<YourVersionType[]>([])

onMounted(async () => {
  const mod = await import(/*@vite-ignore*/ '/VERSIONS.js')
  versions.value = mod.default.map((version) => ({ version: version.version, link: version.link })).sort(...)
})

// use versions in template

brc-dd avatar Jul 15 '24 06:07 brc-dd

Thanks for your help!

jkrumbiegel avatar Jul 15 '24 06:07 jkrumbiegel