tooltip.vue 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. <template>
  2. <span class="tooltip" :class="{ disabled }" @mouseenter="onEnter" @mouseleave="onLeave" @click.capture="onClick">
  3. <slot></slot>
  4. <div v-if="hovered && title && !disabled" class="tooltip-wrap" :class="`tooltip-${adjustedPlacement} tooltip-align-${align}`">
  5. <i></i>
  6. <div><div class="tooltip-text" v-text="title"></div></div>
  7. </div>
  8. </span>
  9. </template>
  10. <script>
  11. export default {
  12. props: {
  13. title: String,
  14. placement: {
  15. type: String,
  16. default: 'auto-y',
  17. },
  18. align: {
  19. type: String,
  20. default: 'center', // start | center | end
  21. },
  22. disabled: Boolean,
  23. },
  24. data() {
  25. return {
  26. hovered: false,
  27. adjustedPlacement: null,
  28. };
  29. },
  30. methods: {
  31. adjustPlacement() {
  32. const { placement } = this;
  33. if (placement === 'auto-y') {
  34. const rect = this.$el.getBoundingClientRect();
  35. this.adjustedPlacement = rect.bottom < document.body.clientHeight / 2 ? 'down' : 'up';
  36. } else {
  37. this.adjustedPlacement = placement;
  38. }
  39. },
  40. onEnter() {
  41. this.adjustPlacement();
  42. this.hovered = true;
  43. },
  44. onLeave() {
  45. this.hovered = false;
  46. },
  47. onClick(e) {
  48. if (this.disabled) e.stopPropagation();
  49. },
  50. },
  51. };
  52. </script>
  53. <style>
  54. $bg-color: rgba(0,0,0,.8);
  55. $border-side-width: 4px;
  56. $border-side: $border-side-width solid transparent;
  57. $border-base: 6px solid $bg-color;
  58. $gap: 10px;
  59. $max-width: 250px;
  60. .tooltip {
  61. display: inline-block;
  62. position: relative;
  63. &-wrap {
  64. position: absolute;
  65. color: white;
  66. font-size: 12px;
  67. line-height: 1.4;
  68. z-index: 100;
  69. > * {
  70. position: absolute;
  71. }
  72. > div {
  73. width: $max-width;
  74. height: 0;
  75. }
  76. &.tooltip-up,
  77. &.tooltip-down {
  78. left: 50%;
  79. > i {
  80. margin-left: -$border-side-width;
  81. }
  82. &.tooltip-align-center {
  83. > div {
  84. left: 50%;
  85. // calc will be reduced by cssnano
  86. margin-left: calc(-$max-width / 2);
  87. text-align: center;
  88. }
  89. }
  90. &.tooltip-align-start {
  91. > div {
  92. left: -10px;
  93. }
  94. }
  95. &.tooltip-align-end {
  96. > div {
  97. right: -10px;
  98. text-align: right;
  99. }
  100. }
  101. }
  102. &.tooltip-up {
  103. bottom: 100%;
  104. margin-bottom: $gap;
  105. > i {
  106. top: 100%;
  107. border-top: $border-base;
  108. border-left: $border-side;
  109. border-right: $border-side;
  110. }
  111. .tooltip-text {
  112. transform: translateY(-100%);
  113. }
  114. }
  115. &.tooltip-down {
  116. top: 100%;
  117. margin-top: $gap;
  118. > i {
  119. bottom: 100%;
  120. border-left: $border-side;
  121. border-right: $border-side;
  122. border-bottom: $border-base;
  123. }
  124. }
  125. &.tooltip-left,
  126. &.tooltip-right {
  127. top: 50%;
  128. > i,
  129. .tooltip-text {
  130. transform: translateY(-50%);
  131. }
  132. > i {
  133. border-top: $border-side;
  134. border-bottom: $border-side;
  135. }
  136. }
  137. &.tooltip-left {
  138. margin-right: 10px;
  139. right: 100%;
  140. > div {
  141. right: 100%;
  142. text-align: right;
  143. }
  144. > i {
  145. left: 100%;
  146. border-left: $border-base;
  147. }
  148. }
  149. &.tooltip-right {
  150. margin-left: 10px;
  151. left: 100%;
  152. > div {
  153. left: 100%;
  154. }
  155. > i {
  156. right: 100%;
  157. border-right: $border-base;
  158. }
  159. }
  160. }
  161. &-text {
  162. display: inline-block;
  163. padding: 8px;
  164. background: $bg-color;
  165. border-radius: 6px;
  166. text-align: left;
  167. }
  168. }
  169. </style>