Banner.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. <template>
  2. <LayoutContainer v-intersect="onIntersect">
  3. <v-row>
  4. <v-col cols="12">
  5. <div class="banner-container">
  6. <img
  7. :src="imageSrc"
  8. :alt="imageAlt"
  9. :class="['cover-image', reverseImage ? 'reverse' : '']"
  10. />
  11. <div v-if="logoSrc" class="details-square">
  12. <v-row>
  13. <div class="content-row">
  14. <img
  15. v-if="iconSrc !== null"
  16. :src="iconSrc"
  17. alt="Icône instruments de musique"
  18. class="custom-icon"
  19. />
  20. <p class="description">
  21. {{ squareText }}
  22. </p>
  23. </div>
  24. </v-row>
  25. </div>
  26. <div
  27. v-if="logoSrc"
  28. :class="'logo-square' + (logoAltTheme ? ' alt-theme' : '')"
  29. >
  30. <img :src="logoSrc" :alt="logoAlt" />
  31. </div>
  32. <div class="image-text mt-12">
  33. <slot name="watermark" />
  34. </div>
  35. </div>
  36. </v-col>
  37. </v-row>
  38. </LayoutContainer>
  39. </template>
  40. <script setup lang="ts">
  41. import type { PropType } from 'vue'
  42. import { useLayoutStore } from '~/stores/layoutStore'
  43. defineProps({
  44. imageSrc: {
  45. type: String,
  46. required: true,
  47. },
  48. imageAlt: {
  49. type: String,
  50. default: '',
  51. },
  52. squareText: {
  53. type: String,
  54. default:
  55. "École de musique, d'art, de danse, de cirque, conservatoires et MJC",
  56. },
  57. logoSrc: {
  58. type: String as PropType<string | null>,
  59. required: false,
  60. default: null,
  61. },
  62. logoAlt: {
  63. type: String,
  64. required: false,
  65. default: '',
  66. },
  67. logoAltTheme: {
  68. type: Boolean,
  69. default: false,
  70. },
  71. iconSrc: {
  72. type: String as PropType<string | null>,
  73. required: false,
  74. default: null,
  75. },
  76. reverseImage: {
  77. type: Boolean,
  78. default: false,
  79. },
  80. })
  81. const layoutStore = useLayoutStore()
  82. const onIntersect = (isIntersecting: boolean) => {
  83. layoutStore.setIsBannerVisible(isIntersecting)
  84. }
  85. </script>
  86. <style scoped lang="scss">
  87. .banner-container {
  88. position: relative;
  89. overflow: hidden;
  90. min-height: 400px;
  91. max-height: 400px;
  92. .image-text {
  93. position: absolute;
  94. top: 40px;
  95. left: 20px;
  96. color: white;
  97. font-size: 3rem;
  98. width: 30rem;
  99. font-style: italic;
  100. font-weight: 300;
  101. line-height: 40px;
  102. }
  103. @media (max-width: 600px) {
  104. min-height: 0;
  105. }
  106. }
  107. .cover-image {
  108. width: 100%;
  109. min-height: 400px;
  110. max-height: 400px;
  111. object-fit: cover;
  112. object-position: center var(--banner-center-image);
  113. transition: transform 0.2s;
  114. margin: 0 auto;
  115. @media (max-width: 600px) {
  116. min-height: 235px;
  117. }
  118. }
  119. .reverse {
  120. transform: scaleX(-1);
  121. }
  122. .custom-icon {
  123. width: 3rem;
  124. height: 3rem;
  125. margin-top: 0.5rem;
  126. }
  127. .details-square {
  128. position: absolute;
  129. bottom: 0;
  130. right: 0;
  131. width: 13rem;
  132. height: 10rem;
  133. background: var(--secondary-color);
  134. @media (max-width: 600px) {
  135. width: 50%;
  136. }
  137. }
  138. .logo-square {
  139. position: absolute;
  140. bottom: 0;
  141. right: 13rem;
  142. width: 13rem;
  143. height: 10rem;
  144. img {
  145. width: 100%;
  146. margin-top: 2.5rem;
  147. }
  148. @media (max-width: 600px) {
  149. right: 50%;
  150. width: 50%;
  151. }
  152. }
  153. .logo-square:not(.alt-theme) {
  154. background: var(--primary-color);
  155. }
  156. .description {
  157. color: var(--on-secondary-color);
  158. font-weight: 300;
  159. font-size: 0.8rem;
  160. text-align: center;
  161. display: flex;
  162. align-items: center;
  163. margin: 0.5rem 2rem 1rem;
  164. }
  165. .content-row {
  166. margin-top: 2rem;
  167. display: flex;
  168. flex-direction: column;
  169. justify-content: space-around;
  170. align-items: center;
  171. height: 100%;
  172. }
  173. .icon {
  174. margin-left: 2rem;
  175. margin-right: 2rem;
  176. }
  177. </style>