tabset.vue 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. <template lang="pug">
  2. .tabset.elevation-2
  3. ul.tabset-tabs(ref='tabs')
  4. slot(name='tabs')
  5. .tabset-content(ref='content')
  6. slot(name='content')
  7. </template>
  8. <script>
  9. export default {
  10. data() {
  11. return {
  12. currentTab: 0
  13. }
  14. },
  15. watch: {
  16. currentTab (newValue, oldValue) {
  17. this.setActiveTab()
  18. }
  19. },
  20. methods: {
  21. setActiveTab () {
  22. this.$refs.tabs.childNodes.forEach((node, idx) => {
  23. if (idx === this.currentTab) {
  24. node.className = 'is-active'
  25. } else {
  26. node.className = ''
  27. }
  28. })
  29. this.$refs.content.childNodes.forEach((node, idx) => {
  30. if (idx === this.currentTab) {
  31. node.className = 'tabset-panel is-active'
  32. } else {
  33. node.className = 'tabset-panel'
  34. }
  35. })
  36. }
  37. },
  38. mounted () {
  39. // Handle scroll to header on load within hidden tab content
  40. if (window.location.hash && window.location.hash.length > 1) {
  41. const headerId = decodeURIComponent(window.location.hash)
  42. let foundIdx = -1
  43. this.$refs.content.childNodes.forEach((node, idx) => {
  44. if (node.querySelector(headerId)) {
  45. foundIdx = idx
  46. }
  47. })
  48. if (foundIdx >= 0) {
  49. this.currentTab = foundIdx
  50. }
  51. }
  52. this.setActiveTab()
  53. this.$refs.tabs.childNodes.forEach((node, idx) => {
  54. node.addEventListener('click', ev => {
  55. this.currentTab = [].indexOf.call(ev.target.parentNode.children, ev.target)
  56. })
  57. })
  58. }
  59. }
  60. </script>
  61. <style lang="scss">
  62. .tabset {
  63. border-radius: 5px;
  64. margin-top: 10px;
  65. @at-root .theme--dark & {
  66. background-color: #292929;
  67. }
  68. > .tabset-tabs {
  69. padding-left: 0;
  70. margin: 0;
  71. display: flex;
  72. align-items: stretch;
  73. background: linear-gradient(to bottom, #FFF, #FAFAFA);
  74. box-shadow: inset 0 -1px 0 0 #DDD;
  75. border-radius: 5px 5px 0 0;
  76. overflow: auto;
  77. @at-root .theme--dark & {
  78. background: linear-gradient(to bottom, #424242, #333);
  79. box-shadow: inset 0 -1px 0 0 #555;
  80. }
  81. > li {
  82. display: block;
  83. padding: 16px;
  84. margin-top: 0;
  85. cursor: pointer;
  86. transition: color 1s ease;
  87. border-right: 1px solid #FFF;
  88. font-size: 14px;
  89. font-weight: 500;
  90. margin-bottom: 1px;
  91. user-select: none;
  92. @at-root .theme--dark & {
  93. border-right-color: #555;
  94. }
  95. &.is-active {
  96. background-color: #FFF;
  97. margin-bottom: 0;
  98. padding-bottom: 17px;
  99. color: mc('blue', '700');
  100. @at-root .theme--dark & {
  101. background-color: #292929;
  102. color: mc('blue', '300');
  103. }
  104. }
  105. &:last-child {
  106. border-right: none;
  107. &.is-active {
  108. border-right: 1px solid #EEE;
  109. @at-root .theme--dark & {
  110. border-right-color: #555;
  111. }
  112. }
  113. }
  114. &:hover {
  115. background-color: rgba(#CCC, .1);
  116. @at-root .theme--dark & {
  117. background-color: rgba(#222, .25);
  118. }
  119. &.is-active {
  120. background-color: #FFF;
  121. @at-root .theme--dark & {
  122. background-color: #292929;
  123. }
  124. }
  125. }
  126. & + li {
  127. border-left: 1px solid #EEE;
  128. @at-root .theme--dark & {
  129. border-left-color: #222;
  130. }
  131. }
  132. }
  133. }
  134. > .tabset-content {
  135. .tabset-panel {
  136. padding: 2px 16px 16px;
  137. display: none;
  138. &.is-active {
  139. display: block;
  140. }
  141. }
  142. }
  143. }
  144. </style>