Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

eggplantSword's avatar

Unfocus button Vue 3

How can I unfocus a button in a method? The reason I ask is because I have a Dialog (Headless UI) that I'm using as a slide in menu and when I click outside the menu the Dialog closes and that's all good but the button I use to open the menu is still focused, how can I make it unfocus when the Dialog closes?

This is my code

<nav class="bg-purple border-b border-purple">
        <!-- Primary Navigation Menu -->

        <div class="mx-auto px-6 md:px-12 lg:px-20 xl:px-28">
            <div class="flex justify-between h-20">
                <div class="flex">
                    <div class="flex space-x-4 items-center">
                        <!-- Menu Button-->
                        <div class="-mr-2 flex items-center">
                            <primary-button
                                @click="showMenu = !showMenu"
                                icon type="button"
                                variant="transparent">
                                <menu-icon class="h-6 w-auto"/>
                            </primary-button>
                        </div>

                        <!-- Logo -->
                    </div>
                </div>

                <div class="flex items-center ml-6">
                    <!-- Settings Dropdown -->
                </div>
            </div>
        </div>

        <my-menu :show="showMenu" @close="showMenu = false" :items="menuItems"></my-menu>
    </nav>

I would assume it goes in the @close for my-menu but I'm not sure. Is there a way to do this?

0 likes
11 replies
vincent15000's avatar

I assume that your button is in the parent component and the dialog is the child component.

You can for example emit a close event to the parent and use the blur() method to unfocus the button.

vincent15000's avatar

@msslgomez From the menu, you emit the close event to the parent. And the parent will blur the button.

<my-menu :show="showMenu" @close="showMenu = false; button.blur()" :items="menuItems"></my-menu>

Sure you have to replace button with the right variable to access to your button instance.

You can also extract the actions to a method.

<template>
	<button ref="button">Open the modal</button>
	...
	<my-menu :show="showMenu" @close="close()" :items="menuItems"></my-menu>
</template>

<script setup>
	const showMenu = ref(false);
	const button = ref(null);
	function close() {
		showMenu.value = false;
		button.blur();
	}
</script>
eggplantSword's avatar

@vincent15000 I tried following this https://vuejs.org/guide/essentials/template-refs.html#accessing-the-refs

This is my code

<script setup>
import {ref} from "vue";
const menuButton = ref(null);
</script>

<template>
...
	<!-- Menu Button-->
	<primary-button ref="menuButton"
			@click="showMenu = !showMenu"
        	icon type="button"
        	variant="transparent">
        		<menu-icon class="h-6 w-auto"/>
	</primary-button>
...

<my-menu :show="showMenu" @close="showMenu = false; menuButton.value.blur()" :items="menuItems"></my-menu>

</template>

This doesn't do anything right now, I also tried menuButton.blur() but got an error instead, am I missing something?

1 like
vincent15000's avatar

@msslgomez

menuButton.value.blur() => value is to be put only in the script, not in the template.

So menuButton.blur() will probably work if you write it in the template.

And menuButton.value.blur() will work if you write it in the script.

vincent15000's avatar

@msslgomez

<my-menu :show="showMenu" @close="showMenu = false; menuButton.blur()" :items="menuItems"></my-menu>
eggplantSword's avatar

@vincent15000 primary-button is this component

<script setup>
import {computed} from "vue";

const props = defineProps({
    type: {
        type: String,
        default: 'submit',
    },
    icon: {
        type: Boolean,
        default: false
    },
    variant: {
        type: String,
        default: null
    }
});

const getVariant = computed(() => {
    switch (props.variant) {
        case 'accent':
            return '...'
        case 'secondary':
            return '...'
        case 'transparentDark':
            return '...'
        case 'transparentLight':
            return '...'
        default:
            return '...'
    }
});
</script>

<template>
    <button :type="type"
            :class="[icon ? 'p-2' : 'px-4 py-2', getVariant]"
            class="inline-flex items-center rounded-md text-[13px] font-medium focus:outline-none transition ease-in-out duration-150">
        <slot/>
    </button>
</template>
1 like
eggplantSword's avatar

@vincent15000 I noticed that it does work your way but only if I use a <button> directly with ref but since I'm using a component it doesn't work correctly, how can I pass the ref to the actual <button> in the component?

1 like
vincent15000's avatar

@msslgomez You can for example add a ref to the button in the child component.

<button
	ref="childButton"
	:type="type"
    :class="[icon ? 'p-2' : 'px-4 py-2', getVariant]"
    class="inline-flex items-center rounded-md text-[13px] font-medium focus:outline-none transition ease-in-out duration-150">
    <slot/>
</button>

And the in the script of the parent you can easily access to the button.

<script setup>
	function anyFunction() {
		menuButton.value.childButton.value.blur();
	}
</script>

Please or to participate in this conversation.