Skip to content
This repository was archived by the owner on Oct 20, 2025. It is now read-only.

Commit 944c566

Browse files
committed
Dropdown refactor
1 parent adbae32 commit 944c566

File tree

11 files changed

+156
-35
lines changed

11 files changed

+156
-35
lines changed

lib/Components/ButtonWithDropdown.vue renamed to lib/Components/Dropdown.vue

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
<template>
2-
<OnClickOutside :do="hide">
3-
<button ref="button">
2+
<OnClickOutside
3+
class="relative"
4+
:do="hide"
5+
:opened="opened"
6+
>
7+
<div ref="button">
48
<slot
59
name="button"
610
:toggle="toggle"
11+
:disabled="disabled"
712
/>
8-
</button>
13+
</div>
914

1015
<div
11-
v-show="opened"
1216
ref="tooltip"
1317
>
1418
<slot
1519
:hide="hide"
20+
:opened="opened"
1621
/>
1722
</div>
1823
</OnClickOutside>
@@ -35,11 +40,6 @@ export default {
3540
default: "bottom-start",
3641
required: false,
3742
},
38-
active: {
39-
type: Boolean,
40-
default: false,
41-
required: false,
42-
},
4343
disabled: {
4444
type: Boolean,
4545
default: false,

lib/Components/OnClickOutside.vue

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,21 @@ const props = defineProps({
1212
type: Function,
1313
required: true,
1414
},
15+
opened: {
16+
type: Boolean,
17+
required: true,
18+
},
19+
closeOnEscape: {
20+
type: Boolean,
21+
required: false,
22+
default: true
23+
}
1524
});
1625
1726
const listener = ref(null);
1827
const root = ref(null);
28+
const closeOnEscapeHandler = ref(null);
29+
1930
2031
onMounted(() => {
2132
listener.value = (e) => {
@@ -28,10 +39,26 @@ onMounted(() => {
2839
2940
document.addEventListener("click", listener.value);
3041
document.addEventListener("touchstart", listener.value);
42+
43+
//
44+
45+
if(props.closeOnEscape) {
46+
closeOnEscapeHandler.value = (e) => {
47+
if (props.opened && e.key === "Escape") {
48+
props.do();
49+
}
50+
};
51+
52+
document.addEventListener("keydown", closeOnEscapeHandler.value);
53+
}
3154
});
3255
3356
onBeforeUnmount(() => {
3457
document.removeEventListener("click", listener.value);
3558
document.removeEventListener("touchstart", listener.value);
59+
60+
if(props.closeOnEscape) {
61+
document.removeEventListener("keydown", closeOnEscapeHandler.value);
62+
}
3663
});
3764
</script>

lib/Components/Transition.vue

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<script>
2+
import { TransitionRoot, TransitionChild } from "@headlessui/vue";
3+
4+
export default {
5+
render() {
6+
return this.$slots.default({
7+
TransitionRoot,
8+
TransitionChild,
9+
});
10+
},
11+
};
12+
</script>

lib/SpladePlugin.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import has from "lodash-es/has";
2-
import ButtonWithDropdown from "./Components/ButtonWithDropdown.vue";
32
import Confirm from "./Components/Confirm.vue";
43
import Data from "./Components/Data.vue";
54
import Defer from "./Components/Defer.vue";
5+
import Dropdown from "./Components/Dropdown.vue";
66
import Errors from "./Components/Errors.vue";
77
import Event from "./Components/Event.vue";
88
import File from "./Components/File.vue";
@@ -19,6 +19,7 @@ import Textarea from "./Components/Textarea.vue";
1919
import Toast from "./Components/Toast.vue";
2020
import Toasts from "./Components/Toasts.vue";
2121
import Toggle from "./Components/Toggle.vue";
22+
import Transition from "./Components/Transition.vue";
2223
import { Splade } from "./Splade.js";
2324

2425
export default {
@@ -32,10 +33,10 @@ export default {
3233
const prefix = options.prefix;
3334

3435
app
35-
.component(`${prefix}ButtonWithDropdown`, ButtonWithDropdown)
3636
.component(`${prefix}Confirm`, Confirm)
3737
.component(`${prefix}Data`, Data)
3838
.component(`${prefix}Defer`, Defer)
39+
.component(`${prefix}Dropdown`, Dropdown)
3940
.component(`${prefix}Errors`, Errors)
4041
.component(`${prefix}Event`, Event)
4142
.component(`${prefix}File`, File)
@@ -51,6 +52,7 @@ export default {
5152
.component(`${prefix}Toast`, Toast)
5253
.component(`${prefix}Toasts`, Toasts)
5354
.component(`${prefix}Toggle`, Toggle)
55+
.component(`${prefix}Transition`, Transition)
5456
.component(options.link_component, Link);
5557

5658
Object.defineProperty(app.config.globalProperties, "$splade", { get: () => Splade });
Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,9 @@
1-
<div class="relative" {{ $attributes }}>
2-
<SpladeButtonWithDropdown placement="bottom-start">
3-
<template #button="dropdown">
4-
<button
5-
type="button"
6-
{{-- :disabled="disabled" --}}
7-
class="w-full bg-white border rounded-md shadow-sm px-4 py-2 inline-flex justify-center text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
8-
{{-- :class="{'border-green-300': active, 'border-gray-300': !active, 'cursor-not-allowed': disabled }" --}}
9-
aria-haspopup="true"
10-
@click.prevent="dropdown.toggle"
11-
>
12-
{{ $button }}
13-
</button>
14-
</template>
1+
<x-splade-dropdown {{ $attributes->class('w-full bg-white border border-gray-300 rounded-md shadow-sm px-4 py-2 inline-flex justify-center text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500') }}>
2+
<x-slot:trigger>
3+
{{ $button }}
4+
</x-slot:trigger>
155

16-
<template #default="dropdown">
17-
<div class="absolute z-10">
18-
<div class="mt-2 min-w-max rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5">
19-
{{ $slot }}
20-
</div>
21-
</div>
22-
</template>
23-
</SpladeButtonWithDropdown>
24-
</div>
6+
<div class="mt-2 min-w-max rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5">
7+
{{ $slot }}
8+
</div>
9+
</x-splade-dropdown>

resources/views/dropdown.blade.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<SpladeDropdown {{ $attributes->except('class')->merge(['placement' => 'bottom-start']) }}>
2+
<template #button="dropdown">
3+
<button
4+
type="button"
5+
aria-haspopup="true"
6+
{{ $attributes->only('class') }}
7+
:class="{ 'cursor-not-allowed': dropdown.disabled }"
8+
:disabled="dropdown.disabled"
9+
@click.prevent="dropdown.toggle"
10+
>
11+
{{ $trigger }}
12+
</button>
13+
</template>
14+
15+
<template #default="dropdown">
16+
<x-splade-transition v-bind:show="dropdown.opened" class="absolute z-40">
17+
{{ $slot }}
18+
</x-splade-transition>
19+
</template>
20+
</SpladeDropdown>

resources/views/table/filters.blade.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
role="menu"
1515
aria-orientation="horizontal"
1616
aria-labelledby="filter-menu"
17-
class="min-w-max"
1817
>
1918
@foreach($table->filters() as $filter)
2019
<div>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
@php $transitionAttributes = [':show', 'v-bind:show', 'enter', 'enter-from', 'enter-to', 'leave', 'leave-from', 'leave-to'] @endphp
2+
3+
<div {{ $attributes->except($transitionAttributes) }}>
4+
<SpladeTransition #default="{!! $scope !!}">
5+
<component
6+
as="div"
7+
:is="transition.TransitionRoot"
8+
{{ $attributes->only($transitionAttributes)->merge([
9+
'enter' => 'transition ease-out duration-200',
10+
'enter-from' => 'opacity-0 scale-95',
11+
'enter-to' => 'opacity-100 scale-100',
12+
'leave' => 'transition ease-in duration-200',
13+
'leave-from' => 'opacity-100 scale-100',
14+
'leave-to' => 'opacity-0 scale-95',
15+
]) }}
16+
>
17+
{{ $slot }}
18+
</component>
19+
</SpladeTransition>
20+
</div>

src/Components/Dropdown.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace ProtoneMedia\Splade\Components;
4+
5+
use Illuminate\View\Component;
6+
7+
class Dropdown extends Component
8+
{
9+
/**
10+
* Create a new component instance.
11+
*
12+
* @return void
13+
*/
14+
public function __construct(public string $scope = 'dropdown')
15+
{
16+
}
17+
18+
/**
19+
* Get the view / contents that represent the component.
20+
*
21+
* @return \Illuminate\Contracts\View\View|\Closure|string
22+
*/
23+
public function render()
24+
{
25+
return view('splade::dropdown');
26+
}
27+
}

src/Components/Transition.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace ProtoneMedia\Splade\Components;
4+
5+
use Illuminate\View\Component;
6+
7+
class Transition extends Component
8+
{
9+
/**
10+
* Create a new component instance.
11+
*
12+
* @return void
13+
*/
14+
public function __construct(public string $scope = 'transition')
15+
{
16+
}
17+
18+
/**
19+
* Get the view / contents that represent the component.
20+
*
21+
* @return \Illuminate\Contracts\View\View|\Closure|string
22+
*/
23+
public function render()
24+
{
25+
return view('splade::transition');
26+
}
27+
}

0 commit comments

Comments
 (0)