11<script setup lang="ts">
2- import { ref , computed } from ' vue'
2+ import { ref , computed , onMounted , onUnmounted } from ' vue'
33import { examples } from ' @/data/examples'
44import type { RExample } from ' @/types'
55
@@ -15,74 +15,189 @@ const emit = defineEmits<{
1515
1616// Initialize with the first example's id
1717const selectedExample = ref <string >(examples [0 ].id )
18+ const isOpen = ref (false )
19+ const dropdownRef = ref <HTMLElement >()
1820
1921const currentExample = computed (() => {
2022 return examples .find ((ex ) => ex .id === selectedExample .value ) || null
2123})
2224
23- const handleExampleChange = (): void => {
24- if (currentExample .value ) {
25- emit (' exampleSelected' , currentExample .value )
25+ const handleExampleSelect = (exampleId : string ): void => {
26+ selectedExample .value = exampleId
27+ isOpen .value = false
28+ const example = examples .find ((ex ) => ex .id === exampleId )
29+ if (example ) {
30+ emit (' exampleSelected' , example )
2631 }
2732}
33+
34+ const toggleDropdown = (): void => {
35+ isOpen .value = ! isOpen .value
36+ }
37+
38+ const handleClickOutside = (event : MouseEvent ): void => {
39+ if (dropdownRef .value && ! dropdownRef .value .contains (event .target as Node )) {
40+ isOpen .value = false
41+ }
42+ }
43+
44+ onMounted (() => {
45+ document .addEventListener (' click' , handleClickOutside )
46+ })
47+
48+ onUnmounted (() => {
49+ document .removeEventListener (' click' , handleClickOutside )
50+ })
2851 </script >
2952
3053<template >
31- <div class =" example-selector" >
32- <select
33- id =" example-select"
34- v-model =" selectedExample"
35- class =" select"
36- @change =" handleExampleChange"
54+ <div
55+ ref =" dropdownRef"
56+ class =" example-selector"
57+ >
58+ <button
59+ class =" example-button"
60+ @click =" toggleDropdown"
3761 >
38- <option
39- v-for =" example in examples"
40- :key =" example.id"
41- :value =" example.id"
42- >
43- {{ example.title }}
44- </option >
45- </select >
62+ <span class =" example-text" >
63+ {{ currentExample?.title || 'Select example' }}
64+ </span >
65+ <span
66+ class =" dropdown-arrow"
67+ :class =" { 'open': isOpen }"
68+ >▼</span >
69+ </button >
70+
71+ <div
72+ v-if =" isOpen"
73+ class =" example-dropdown"
74+ >
75+ <div class =" example-list" >
76+ <button
77+ v-for =" example in examples"
78+ :key =" example.id"
79+ class =" example-item"
80+ :class =" { 'selected': example.id === selectedExample }"
81+ @click =" handleExampleSelect(example.id)"
82+ >
83+ <div class =" example-info" >
84+ <span class =" example-name" >{{ example.title }}</span >
85+ <span class =" example-desc" >{{ example.description }}</span >
86+ </div >
87+ </button >
88+ </div >
89+ </div >
4690 </div >
4791</template >
4892
4993<style scoped>
5094.example-selector {
95+ position : relative ;
5196 display : flex ;
5297 align-items : center ;
5398 min-width : 0 ;
5499 flex : 1 ;
55100 max-width : 250px ;
56101}
57102
58- .select {
103+ .example-button {
104+ display : flex ;
105+ align-items : center ;
106+ gap : 0.5rem ;
59107 background : #f3f4f6 ;
60108 border : 1px solid #d1d5db ;
61109 border-radius : 6px ;
62110 padding : 0.375rem 0.625rem ;
63- padding-right : 1.5rem ;
64111 font-size : 0.875rem ;
65112 cursor : pointer ;
66113 transition : all 0.2s ease ;
114+ white-space : nowrap ;
115+ min-height : 32px ;
67116 width : 100% ;
68117 max-width : 200px ;
69- min-height : 32px ;
70- appearance : none ;
71- background-image : url (' data:image/svg+xml;charset=US-ASCII,%3Csvg%20width%3D%2714%27%20height%3D%278%27%20viewBox%3D%270%200%2014%208%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%3Cpath%20d%3D%27M1%201l6%206%206-6%27%20stroke%3D%27%236B7280%27%20stroke-width%3D%272%27%20fill%3D%27none%27%20fill-rule%3D%27evenodd%27%2F%3E%3C%2Fsvg%3E' );
72- background-repeat : no-repeat ;
73- background-position : right 0.5rem center ;
74- background-size : 12px ;
118+ justify-content : space-between ;
75119}
76120
77- .select :hover {
121+ .example-button :hover {
78122 background : #e5e7eb ;
79123 border-color : #3b82f6 ;
80124}
81125
82- .select :focus {
83- outline : none ;
84- border-color : #3b82f6 ;
85- box-shadow : 0 0 0 2px rgba (59 , 130 , 246 , 0.1 );
126+ .example-text {
127+ font-weight : 500 ;
128+ color : #374151 ;
129+ overflow : hidden ;
130+ text-overflow : ellipsis ;
131+ }
132+
133+ .dropdown-arrow {
134+ font-size : 0.75rem ;
135+ transition : transform 0.3s ease ;
136+ margin-left : 0.25rem ;
137+ flex-shrink : 0 ;
138+ }
139+
140+ .dropdown-arrow.open {
141+ transform : rotate (180deg );
142+ }
143+
144+ .example-dropdown {
145+ position : absolute ;
146+ top : calc (100% + 0.25rem );
147+ left : 0 ;
148+ background : white ;
149+ border : 1px solid #e5e7eb ;
150+ border-radius : 6px ;
151+ box-shadow : 0 4px 12px rgba (0 , 0 , 0 , 0.15 );
152+ z-index : 1000 ;
153+ min-width : 280px ;
154+ max-width : 350px ;
155+ overflow-y : auto ;
156+ max-height : 400px ;
157+ }
158+
159+ .example-list {
160+ padding : 0.375rem ;
161+ }
162+
163+ .example-item {
164+ display : flex ;
165+ align-items : flex-start ;
166+ padding : 0.5rem ;
167+ border-radius : 4px ;
168+ cursor : pointer ;
169+ transition : background-color 0.2s ease ;
170+ width : 100% ;
171+ text-align : left ;
172+ background : none ;
173+ border : none ;
174+ }
175+
176+ .example-item :hover {
177+ background : #f3f4f6 ;
178+ }
179+
180+ .example-item.selected {
181+ background : #e0f2fe ;
182+ }
183+
184+ .example-info {
185+ display : flex ;
186+ flex-direction : column ;
187+ gap : 0.125rem ;
188+ width : 100% ;
189+ }
190+
191+ .example-name {
192+ font-size : 0.875rem ;
193+ font-weight : 500 ;
194+ color : #374151 ;
195+ }
196+
197+ .example-desc {
198+ font-size : 0.6875rem ;
199+ color : #6b7280 ;
200+ line-height : 1.3 ;
86201}
87202
88203@media (max-width : 768px ) {
@@ -93,15 +208,24 @@ const handleExampleChange = (): void => {
93208 align-items : center ;
94209 }
95210
96- .select {
211+ .example-button {
97212 max-width : none ;
98213 min-height : 28px ;
99214 padding : 0.25rem 0.5rem ;
100- padding-right : 1.25rem ;
101215 font-size : 0.8125rem ;
102216 border-radius : 4px ;
103- background-size : 10px ;
104- background-position : right 0.375rem center ;
217+ gap : 0.25rem ;
218+ }
219+
220+ .dropdown-arrow {
221+ font-size : 0.625rem ;
222+ }
223+
224+ .example-dropdown {
225+ left : 0 ;
226+ right : 0 ;
227+ max-width : calc (100vw - 2rem );
228+ z-index : 2000 ;
105229 }
106230}
107231 </style >
0 commit comments