Recently I needed a way to place a custom component on the main header of Laravel Nova. There’s no specific way documented to do this, so I had to get creative.

I decided I would try to extend an existing component from the header and insert mine as an add-on to that. Strange enough, this was pretty easy to do. I was expecting some trouble, because in v3, this wasn’t as easy.

Finding the Original Component

I’ve inspected the interface and found a pretty long class attribute which I could use to search in all files by:

toolbar-button flex items-center cursor-pointer select-none h-10 w-10 hover:text-primary-500

Searched that in the vendor/nova directory, and found ThemeDropdown.vue, under vendor/nova/resources/js/components/Dropdowns/.

Extending the Component

I used a custom tool’s JS file to do this, but you should be able to do it from the context of any custom Nova element (Field, Filter, Asset, etc). I typically create one single custom tool, and define all my helper custom elements inside it.

The current path is:

nova-components/Helpers/resources/js/helpers.js

Therefore, I’m importing the original component as such:

import OriginalThemeDropdown from '../../../../vendor/laravel/nova/resources/js/components/Dropdowns/ThemeDropdown.vue'

To make that a bit cleaner, I’ve defined an alias in my nova-components/Helpers/webpack.mix.js file:

mix.alias({ '&': path.join(__dirname, '../../vendor/laravel/nova/resources/js/') })

That allows me to reference Nova’s ../resources/js path by the & character. So, now I can just type:

import OriginalThemeDropdown from '&/components/Dropdowns/ThemeDropdown.vue'

Use that import in your custom component, and reference OriginalThemeDropdown in your components: {...} object.

Next, use the component in your custom component, to bring it back to the menu.

This is how a test component would look like:

<template>
    <strong class="mr-4">testing...</strong>

    <OriginalThemeDropdown />
</template>

<script>
import OriginalThemeDropdown from '&/components/Dropdowns/ThemeDropdown.vue'

export default {
    components: {
        OriginalThemeDropdown,
    },
}
</script>

Now we simply need to replace the original component with our own.

To do that, in my nova-components/Helpers/resources/js/helpers.js file, I have this:

import Tasklist from './tools/tasklist.vue'
// ... other imports

Nova.booting((app, store) => {
    app.component('ThemeDropdown', Tasklist)

    // other components/tools/filter/etc...
})

Remember, the component name must be the name of the component you’re replacing, otherwise, Nova doesn’t know how to use your new component.

And this is how it looks in the interface:

Now I can carry on with defining my custom component in that spot.

Please let me know in the comments if you have any issues with this and I’ll try to help.