DropdownLink.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. <template>
  2. <div
  3. class="dropdown-wrapper"
  4. :class="{ open }"
  5. >
  6. <button
  7. class="dropdown-title"
  8. type="button"
  9. :aria-label="dropdownAriaLabel"
  10. @click="setOpen(!open)"
  11. >
  12. <span class="title">{{ item.text }}</span>
  13. <span
  14. class="arrow"
  15. :class="open ? 'down' : 'right'"
  16. ></span>
  17. </button>
  18. <DropdownTransition>
  19. <ul
  20. class="nav-dropdown"
  21. v-show="open"
  22. >
  23. <li
  24. class="dropdown-item"
  25. :key="subItem.link || index"
  26. v-for="(subItem, index) in item.items"
  27. >
  28. <h4 v-if="subItem.type === 'links'">{{ subItem.text }}</h4>
  29. <ul
  30. class="dropdown-subitem-wrapper"
  31. v-if="subItem.type === 'links'"
  32. >
  33. <li
  34. class="dropdown-subitem"
  35. :key="childSubItem.link"
  36. v-for="childSubItem in subItem.items"
  37. >
  38. <NavLink
  39. @focusout="
  40. isLastItemOfArray(childSubItem, subItem.items) &&
  41. isLastItemOfArray(subItem, item.items) &&
  42. setOpen(false)
  43. "
  44. :item="childSubItem"/>
  45. </li>
  46. </ul>
  47. <NavLink
  48. v-else
  49. @focusout="isLastItemOfArray(subItem, item.items) && setOpen(false)"
  50. :item="subItem"
  51. />
  52. </li>
  53. </ul>
  54. </DropdownTransition>
  55. </div>
  56. </template>
  57. <script>
  58. import NavLink from '@theme/components/NavLink.vue'
  59. import DropdownTransition from '@theme/components/DropdownTransition.vue'
  60. import last from 'lodash/last'
  61. export default {
  62. components: { NavLink, DropdownTransition },
  63. data () {
  64. return {
  65. open: false
  66. }
  67. },
  68. props: {
  69. item: {
  70. required: true
  71. }
  72. },
  73. computed: {
  74. dropdownAriaLabel () {
  75. return this.item.ariaLabel || this.item.text
  76. }
  77. },
  78. methods: {
  79. setOpen (value) {
  80. this.open = value
  81. },
  82. isLastItemOfArray (item, array) {
  83. return last(array) === item
  84. }
  85. },
  86. watch: {
  87. $route () {
  88. this.open = false
  89. }
  90. }
  91. }
  92. </script>
  93. <style lang="stylus">
  94. .dropdown-wrapper
  95. cursor pointer
  96. .dropdown-title
  97. display block
  98. font-size 0.9rem
  99. font-family inherit
  100. cursor inherit
  101. padding inherit
  102. line-height 1.4rem
  103. background transparent
  104. border none
  105. font-weight 500
  106. color $textColor
  107. &:hover
  108. border-color transparent
  109. .arrow
  110. vertical-align middle
  111. margin-top -1px
  112. margin-left 0.4rem
  113. .nav-dropdown
  114. .dropdown-item
  115. color inherit
  116. line-height 1.7rem
  117. h4
  118. margin 0.45rem 0 0
  119. border-top 1px solid #eee
  120. padding 0.45rem 1.5rem 0 1.25rem
  121. .dropdown-subitem-wrapper
  122. padding 0
  123. list-style none
  124. .dropdown-subitem
  125. font-size 0.9em
  126. a
  127. display block
  128. line-height 1.7rem
  129. position relative
  130. border-bottom none
  131. font-weight 400
  132. margin-bottom 0
  133. padding 0 1.5rem 0 1.25rem
  134. &:hover
  135. color $accentColor
  136. &.router-link-active
  137. color $accentColor
  138. &::after
  139. content ""
  140. width 0
  141. height 0
  142. border-left 5px solid $accentColor
  143. border-top 3px solid transparent
  144. border-bottom 3px solid transparent
  145. position absolute
  146. top calc(50% - 2px)
  147. left 9px
  148. &:first-child h4
  149. margin-top 0
  150. padding-top 0
  151. border-top 0
  152. @media (max-width: $MQMobile)
  153. .dropdown-wrapper
  154. &.open .dropdown-title
  155. margin-bottom 0.5rem
  156. .dropdown-title
  157. font-weight 600
  158. font-size inherit
  159. &:hover
  160. color $accentColor
  161. .nav-dropdown
  162. transition height .1s ease-out
  163. overflow hidden
  164. .dropdown-item
  165. h4
  166. border-top 0
  167. margin-top 0
  168. padding-top 0
  169. h4, & > a
  170. font-size 15px
  171. line-height 2rem
  172. .dropdown-subitem
  173. font-size 14px
  174. padding-left 1rem
  175. @media (min-width: $MQMobile)
  176. .dropdown-wrapper
  177. height 1.8rem
  178. &:hover .nav-dropdown,
  179. &.open .nav-dropdown
  180. // override the inline style.
  181. display block !important
  182. &.open:blur
  183. display none
  184. .dropdown-title .arrow
  185. // make the arrow always down at desktop
  186. border-left 4px solid transparent
  187. border-right 4px solid transparent
  188. border-top 6px solid $arrowBgColor
  189. border-bottom 0
  190. .nav-dropdown
  191. display none
  192. // Avoid height shaked by clicking
  193. height auto !important
  194. box-sizing border-box;
  195. max-height calc(100vh - 2.7rem)
  196. overflow-y auto
  197. position absolute
  198. top 100%
  199. right 0
  200. background-color #fff
  201. padding 0.6rem 0
  202. border 1px solid #ddd
  203. border-bottom-color #ccc
  204. text-align left
  205. border-radius 0.25rem
  206. white-space nowrap
  207. margin 0
  208. </style>