Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding EDU Home page template #614

Merged
merged 5 commits into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions packages/vue/src/components/SearchInput/SearchInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ interface SearchInputProps {
placeholder?: string
autoFocus?: boolean
defaultColors?: boolean
withButton?: boolean
}

// define props
Expand All @@ -16,10 +17,11 @@ const props = withDefaults(defineProps<SearchInputProps>(), {
underlinedInputValue: undefined,
placeholder: '',
autoFocus: false,
defaultColors: true
defaultColors: true,
withButton: false
})

const emit = defineEmits(['input', 'esc'])
const emit = defineEmits(['input', 'esc', 'submit'])

const model = defineModel()
const isFocused = ref(false)
Expand Down Expand Up @@ -67,20 +69,29 @@ onMounted(() => {
<input
ref="searchQueryRef"
v-model="model"
class="pl-14 focus:ring-2 relative z-10 w-full pr-5 text-lg bg-transparent border-0"
class="pl-14 h-full focus:ring-2 relative z-10 w-full px-5 text-sm md:text-base lg:text-lg bg-transparent border-0"
:class="{
'text-gray-dark': defaultColors,
'py-1': underlinedInput,
'py-4': !underlinedInput
'py-3.5 lg:py-5': !underlinedInput
}"
type="search"
aria-label="Query"
:placeholder="placeholder"
@keydown.esc="emit('esc')"
@keydown.enter="emit('submit')"
@input="emit('input', $event.target)"
@focus="isFocused = true"
@blur="isFocused = false"
/>
<button
v-if="withButton"
class="z-10 cursor-pointer bg-action p-4 lg:p-5 border border-white"
aria-label="Search resources"
@click="emit('submit')"
>
<IconSearch class="relative z-10 text-xl sm:text-2xl lg:text-3xl text-white" />
</button>
</div>
</template>
<style lang="scss" scoped>
Expand Down
99 changes: 99 additions & 0 deletions packages/vue/src/templates/edu/PageEduHome/PageEduHome.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { BlockLinkCardCarouselData } from './../../../components/BlockLinkCarousel/BlockLinkCarousel.stories.js'
import { EventsBlockLinkCarouselData } from './../../../components/BlockLinkCarousel/BlockLinkCarousel.stories'
import { AboutTheAuthorData } from './../../../components/AboutTheAuthor/AboutTheAuthor.stories'
import { BlockImageData } from './../../../components/BlockImage/BlockImage.stories'
import { BlockVideoData } from './../../../components/BlockVideo/BlockVideo.stories'
import { BlockVideoEmbedData } from './../../../components/BlockVideoEmbed/BlockVideoEmbed.stories'
import { BlockImageComparisonData } from './../../../components/BlockImageComparison/BlockImageComparison.stories'
import PageEduHome from './PageEduHome.vue'

export default {
title: 'Templates/EDU/PageEduHome',
component: PageEduHome,
tags: ['!autodocs'],
parameters: {
html: {
root: '#storyDecorator'
},
layout: 'fullscreen'
},
excludeStories: /.*Data$/
}

// stories
export const BaseStory = {
name: 'PageEduHome',
args: {
data: {
__typename: 'EDUHomePage',
title: 'EDU Homepage',
slug: 'edu-home',
url: '/',
lastPublishedAt: '2024-08-22T02:33:13.507206+00:00',
thumbnailImage: {
alt: '',
original: 'https://picsum.photos/512/288'
},
heroImage: {
// beach
src: {
url: 'https://picsum.photos/id/973/1800/1200',
width: 1800,
height: 1200
},
// lake
srcSet:
'https://picsum.photos/id/865/768/548 768w, https://picsum.photos/id/865/1024/684 1024w, https://picsum.photos/id/865/1440/770 1440w, https://picsum.photos/id/865/1800/963 1800w',
// jungle
screenMd: {
url: 'https://picsum.photos/id/921/800/640'
},
// desert
screenSm: {
url: 'https://picsum.photos/id/247/640/900'
},
alt: 'Robotics detail page hero image'
},
heroText: 'Discover a universe of activities & resources',
hotTopics: [
{
page: {
title: 'Psyche Asteroid',
url: '/topic/'
}
},
{
page: {
title: 'Mars Rovers',
url: '/topic/'
}
},
{
page: {
title: 'Webb Space Telescope',
url: '/topic/'
}
},
{
page: {
title: 'NASA Pi Day',
url: '/topic/'
}
}
],
body: [
{
blockType: 'HeadingBlock',
heading: 'EDU Home',
level: 'h2',
size: 'h2'
},
{
blockType: 'RichTextBlock',
value:
'<p>Lorem ipsum <a href="/missions/test-mission/">dolor</a> sit amet, consectetur adipiscing elit. Quisque vitae justo quis justo malesuada molestie. Cras sed tincidunt dui.</p><p>Integer imperdiet blandit neque vitae euismod. Nulla aliquet lacus nibh, vel tincidunt urna efficitur non. In et eros vitae ex posuere maximus quis eget urna. Suspendisse fringilla posuere velit sit amet posuere. Morbi malesuada bibendum vehicula. Donec faucibus ut erat ut mattis. Suspendisse ornare, quam at placerat cursus, dolor mi lacinia nunc, eget maximus augue nulla in dolor.</p>\n'
}
]
}
}
}
154 changes: 154 additions & 0 deletions packages/vue/src/templates/edu/PageEduHome/PageEduHome.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
<script setup lang="ts">
import { computed, reactive, ref } from 'vue'
import { useRouter } from 'vue-router'
import type { ImageObject, PageObject } from '../../../interfaces'
import SearchInput from './../../../components/SearchInput/SearchInput.vue'
import BlockStreamfield from './../../../components/BlockStreamfield/BlockStreamfield.vue'
import BaseLink from './../../../components/BaseLink/BaseLink.vue'

const router = useRouter()

interface PageEduHomeObject extends PageObject {
heroImage: ImageObject
heroText: string
hotTopics: {
page: PageObject
}[]
}

interface PageEduHomeProps {
data: PageEduHomeObject
}

// define props
const props = withDefaults(defineProps<PageEduHomeProps>(), {
data: undefined
})

const { data } = reactive(props)

const searchQuery = ref(undefined)
const image = computed(() => {
return data?.heroImage
})

const submitSearch = () => {
router.push({ path: '/edu/resources/', query: { query: searchQuery.value } })
}
</script>
<template>
<div
v-if="data"
class="PageEduHome ThemeVariantLight -nav-offset"
>
<div class="EduHero max-w-screen-3xl relative mx-auto">
<div class="absolute inset-0 z-10 bg-black">
<picture v-if="image?.src">
<source
media="(min-width: 768px)"
:srcset="image.srcSet"
/>
<source
media="(min-width: 420px)"
:srcset="image.screenMd?.url"
/>
<source :srcset="image.screenSm?.url" />
<img
class="md:object-right object-cover object-bottom w-full h-full"
:src="image.src.url"
:width="image.src.width"
:height="image.src.height"
:alt="image.alt"
/>
</picture>
</div>
<div class="content-wrapper lg:flex lg:items-center relative z-20 w-full h-full">
<div
class="bg-gradient-to-b lg:bg-gradient-to-l from-transparent-w25 lg:from-transparent-w50 to-transparent-black-50 lg:to-transparent-black-50 absolute inset-0"
></div>
<div class="text-contrast relative w-full text-white">
<div class="lg:py-0 pb-10 container pt-8 mx-auto">
<div class="lg:px-10 2xl:px-0 pt-30 lg:pt-16 lg:pb-18 px-4">
<h1
v-if="data.heroText"
class="lg:w-3/4 xl:w-3/4 xl:text-10xl lg:text-9xl text-7xl lg:tracking-tightest lg:leading-tighter mb-5 font-bold leading-tight"
>
{{ data.heroText }}
</h1>
<div class="md:w-4/5 lg:w-2/3 xl:w-1/2 w-full">
<SearchInput
v-model="searchQuery"
class="bg-white border-none"
placeholder="Search the K-12 resource library"
with-button
@submit="submitSearch()"
/>
</div>
<div
v-if="data.hotTopics?.length"
class="md:flex flex-row mt-10"
>
<h2
class="text-subtitle mt-1 text-white font-semibold whitespace-nowrap mr-5 mb-3 md:mb-0 lg:mr-8"
>
Hot Topics
</h2>
<ul class="flex flex-row flex-wrap">
<li
v-for="(topic, index) in data.hotTopics"
:key="index"
class="mr-2 mb-2"
>
<BaseLink
variant="none"
:to="`/edu/resources?query=${topic.page?.title}`"
link-class="text-gray-dark whitespace-nowrap text-sm bg-[#99D1DF] font-extrabold rounded-full inline-block px-3 py-1 text-contrast-none hover:bg-action hover:text-white"
>
{{ topic.page?.title }}
</BaseLink>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>

<div
v-if="data.body?.length"
class="my-10 lg:my-18"
>
<BlockStreamfield
v-if="data.body?.length"
:data="data.body"
/>
</div>
</div>
</template>
<style lang="scss">
.PageEduHome {
.EduHero {
.content-wrapper {
@screen lg {
min-height: 548px; // maintains 1440x770 aspect ratio
}

@screen xl {
min-height: 684px; // maintains 1440x770 aspect ratio
}

@screen 2xl {
min-height: 770px; // 1440x770
}

@screen 3xl {
min-height: 963px; // maintains 1440x770 aspect ratio
}
input::placeholder {
@apply font-medium text-gray-dark opacity-80;
}
}
}
}
</style>