index.vue 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. <template><NuxtLayout name="default">
  2. <main id="main" class="container mx-auto max-w-screen-xl md:px-12 sm:px-0 px-0" aria-label="Home page">
  3. <h3 class="sm:text-5xl text-3xl text-center -mt-6 sm:-mt-16 font-display">
  4. I do things.
  5. </h3>
  6. <div class="grid sm:grid-cols-2 gap-6 mx-auto sm:py-8 py-6 col">
  7. <div class="aspect-w-16 aspect-h-9 shadow-lg">
  8. <a href="https://edugames.andreafranceschini.org/">
  9. <video autoplay loop muted class="rounded" aria-hidden="true">
  10. <source src="/images/gneg.mp4" type="video/mp4" />
  11. Your browser does not support the video tag.
  12. </video>
  13. <span class="sr-only">Read more about the EduGames project</span>
  14. </a>
  15. </div>
  16. <div class="aspect-w-16 aspect-h-9 shadow-lg">
  17. <a href="https://edugames.andreafranceschini.org/cash-or-card"><figure aria-hidden="true">
  18. <picture>
  19. <source srcset="/images/cash_or_card-2x.webp" type="image/webp" />
  20. <source srcset="/images/cash_or_card.jpg 1x, /images/cash_or_card-2x.jpg 2x" type="image/jpeg" />
  21. <img class="rounded" srcset="/images/cash_or_card.jpg" alt="Cash or Card? title screen" />
  22. </picture>
  23. </figure><span class="sr-only">Play the game "Cash or Card?"</span></a>
  24. </div>
  25. <!-- <div class="aspect-w-16 aspect-h-9 shadow-lg hidden sm:block">
  26. <iframe ref="video" lang="en" loading="lazy" data-src="https://www.youtube-nocookie.com/embed/AszBiqrvAaU" title="How to make your computer go BOOP" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
  27. </div> -->
  28. </div>
  29. <h3 class="sm:text-4xl text-3xl pb-8 text-center">
  30. <span class="scroll-down sm:hidden">
  31. <ScrollDownSVG />
  32. </span>
  33. What can I do for you?
  34. <span class="scroll-down sm:hidden">
  35. <ScrollDownSVG />
  36. </span>
  37. </h3>
  38. <nav id="home_bars" aria-label="Secondary menu" class="flex flex-row sm:max-w-screen-lg mx-auto">
  39. <ul class="contents">
  40. <li class="contents"><a href="/research" class="research flex-1"><span>Research</span></a></li>
  41. <li class="contents"><a href="/development" class="development flex-1"><span>Development</span></a></li>
  42. <li class="contents"><a href="/writing" class="writing flex-1"><span>Technical Writing</span></a></li>
  43. <li class="contents"><a href="/contact" class="other flex-1"><span>Something else</span></a></li>
  44. </ul>
  45. </nav>
  46. </main>
  47. </NuxtLayout></template>
  48. <style lang="pcss">
  49. @reference '../assets/css/main.css';
  50. @keyframes floating {
  51. 0% { transform: translate(0, -5px); }
  52. 50% { transform: translate(0, 0px); }
  53. 100% { transform: translate(0, -5px); }
  54. }
  55. .scroll-down {
  56. svg {
  57. width: 25px;
  58. height: 25px;
  59. display: inline;
  60. animation-name: floating;
  61. animation-duration: 2s;
  62. animation-iteration-count: infinite;
  63. animation-timing-function: ease-in-out;
  64. opacity: 50%;
  65. }
  66. }
  67. @media (prefers-reduced-motion: reduce) {
  68. .scroll-down svg { animation: none !important; }
  69. video[autoplay] { animation: none !important; }
  70. }
  71. html.no-webp {
  72. #home_bars a {
  73. &.research {
  74. background-image: url(../images/home-research-2x.png);
  75. }
  76. &.development {
  77. background-image: url(../images/home-development-2x.png);
  78. }
  79. &.writing {
  80. background-image: url(../images/home-writing-2x.png);
  81. }
  82. &.other {
  83. background-image: url(../images/home-contact-2x.png);
  84. }
  85. }
  86. }
  87. #home_bars a:focus-visible {
  88. outline: 3px solid #000;
  89. outline-offset: 4px;
  90. }
  91. #home_bars {
  92. a {
  93. width: 25%;
  94. height: 250px;
  95. padding: 0;
  96. margin: 0;
  97. position: relative;
  98. background: grey;
  99. text-shadow: 0px 0px 4px black;
  100. &.research {
  101. background-image: url(../images/home-research-2x.webp);
  102. background-position: 100% 100%;
  103. background-size: cover;
  104. }
  105. &.development {
  106. background-image: url(../images/home-development-2x.webp);
  107. background-position: 100% 100%;
  108. background-size: cover;
  109. }
  110. &.writing {
  111. background-image: url(../images/home-writing-2x.webp);
  112. background-position: 100% 100%;
  113. background-size: cover;
  114. }
  115. &.other {
  116. background-image: url(../images/home-contact-2x.webp);
  117. background-position: 100% 100%;
  118. background-size: cover;
  119. }
  120. span {
  121. position: absolute;
  122. color: #fff;
  123. font-family: Oswald,sans-serif;
  124. font-size: 30px;
  125. white-space: nowrap;
  126. transform-origin: bottom left;
  127. transform: rotate(-90deg);
  128. display: block;
  129. bottom: 0.5em;
  130. left: 1.6667em;
  131. overflow: visible;
  132. }
  133. }
  134. }
  135. </style>
  136. <script lang="ts" setup>
  137. definePageMeta({
  138. layout: false
  139. });
  140. const title = "Hello, I'm Andrea Franceschini, PhD";
  141. const keywords = "music, learning, tabletop, research, the open university, university of cambridge, isaac physics, reactable";
  142. useState('pageClasses', () => ['index', 'page']);
  143. useState('headline', () => "Hello");
  144. useState('tagline', () => "I'm Andrea");
  145. useHead({
  146. title,
  147. meta: [
  148. { property: 'keywords', content: keywords },
  149. { property: 'DC.Title', content: title },
  150. { property: 'twitter:title', content: title },
  151. { property: 'og:title', content: title },
  152. ]
  153. });
  154. onMounted(() => {
  155. const m = window.matchMedia('(prefers-reduced-motion: reduce)');
  156. if (m.matches) {
  157. document.querySelectorAll<HTMLVideoElement>('video[autoplay]').forEach(v => {
  158. v.pause();
  159. v.removeAttribute('autoplay');
  160. v.removeAttribute('loop');
  161. });
  162. }
  163. });
  164. // const video = ref<HTMLIFrameElement>();
  165. // onMounted(() => {
  166. // const src = video.value?.dataset['src'];
  167. // video.value?.setAttribute('src', src || '');
  168. // });
  169. </script>