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

feat: Redesign start page #30

Merged
merged 11 commits into from
Jan 8, 2024
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,4 @@ jobs:
- run: "export AUTH_ORIGIN=http://localhost:3000 && export AUTH_SECRET=test123 && cd my-sidebase-app && npm run build && timeout 30 npm run preview || ( [[ $? -eq 124 ]] && echo \"app started and did not exit within first 30 seconds, thats good\" )"

# start dev-app and curl from it
- run: "cd my-sidebase-app && timeout 30 npm run dev & (sleep 10 && curl --fail localhost:3000) || ( [[ $? -eq 124 ]] && echo \"app started and did not exit within first 30 seconds, thats good\" )"
- run: "cd my-sidebase-app && timeout 30 npm run dev & (sleep 20 && curl --fail localhost:3000) || ( [[ $? -eq 124 ]] && echo \"app started and did not exit within first 30 seconds, thats good\" )"
Copy link
Member Author

@zoey-kaiser zoey-kaiser Oct 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Due to moving all the demos to the start page, I had to increase the sleep timer here to ensure all the data could load, before the curl was performed.

Note: This did happen sometimes before, where the curl was run before the page had finished starting up. See https://github.com/sidebase/create-sidebase/actions/runs/6500004358/job/17654497392?pr=30 where we pushed #29 to main.

251 changes: 159 additions & 92 deletions src/steps/2.addModules/generateIndexVue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,46 @@ const getModulesSnippet = (selectedModules: Modules[], key: "html" | "css" | "js
}
export const generateIndexVue = (selectedModules: Modules[]) => {
const html = getModulesSnippet(selectedModules, "html")
const css = getModulesSnippet(selectedModules, "css")
const js = getModulesSnippet(selectedModules, "js")

return `<template>
<div class="main-container">
<div class="heading">
<h1 class="heading__title">
Welcome to your new <span class="gradient__text">sidebase</span> app!
</h1>
<p class="heading__credits">
Read our documentation <a href="https://sidebase.io/sidebase/welcome" target="_blank">here</a>.
${selectedModules.length > 0 ? "Get started in no time with the following amazing modules:" : "Add some of our amazing modules <a href='https://sidebase.io' target='_blank'>here</a>."}
</p>
<div class="wrapper">
<div class="margins" style="padding-top: 3rem; ">
<div class="content">
<h1 class="heading">
Welcome to your new <span class="gradient__text">sidebase</span> app!
</h1>
<p class="description">
Read our documentation <a class="hover-underline-animation" href="https://sidebase.io/sidebase/welcome" target="_blank">here</a>.
${selectedModules.length > 0 ? "Get started in no time with the following amazing modules:" : "Add some of our amazing modules <a href='https://sidebase.io' target='_blank'>here</a>."}
</p>
</div>

<div class="modules_grid">${html}
</div>
</div>
<div class="cards">${html}

<div class="margins footer">
<div style="color: #D1D5DB">
Developed with love by
<NuxtLink href="https://sidestream.tech" target="_blank" class="hover-underline-animation">
Sidestream
</NuxtLink>
</div>
<div class="social">
<NuxtLink href="https://discord.gg/VzABbVsqAc" target="_blank" class="hover-underline-animation">
Discord
</NuxtLink>
<NuxtLink href="https://twitter.com/sidebase_io" target="_blank" class="hover-underline-animation">
Twitter
</NuxtLink>
<NuxtLink href="https://github.com/sidebase" target="_blank" class="hover-underline-animation">
Github
</NuxtLink>
</div>
</div>
</div>
</template>
${js && `
<script>
${js}
</script>\n`}
<style scoped>
<style>
* {
margin: 0;
padding: 0;
Expand All @@ -42,116 +59,166 @@ ${js}
color: #484848;
}

.main-container {
max-width: 45vw;
margin: auto;
padding-top: 60px;
}

/* HEADING */

.heading {
text-align: center;
/* Layout */
.wrapper {
display: flex;
flex-direction: column;
justify-content: space-between;
width: 100%;
min-height: 100vh;
color: #ffffff;
background-color: #0E0E10;
}
.margins {
padding-left: 1rem;
padding-right: 1rem;

.heading__title {
font-weight: 600;
font-size: 40px;
@media (min-width: 1024px) {
padding-left: 5rem;
padding-right: 5rem;
}
}

.gradient__text {
background: linear-gradient(to right, #7bceb6 10%, #12a87b 40%, #0FCF97 60%, #7bceb6 90%);
background-size: 200% auto;
color: #000;
background-clip: text;
text-fill-color: transparent;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
animation: shine 1s linear infinite;
/* Heading */
.content {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.content .heading {
font-size: 2.4rem;
line-height: 2.25rem;
font-weight: 700;

@keyframes shine {
to {
background-position: 200% center;
@media (min-width: 1280px) {
font-size: 3rem;
line-height: 1;
}
}

.heading__credits {
color: #888888;
font-size: 25px;
transition: all 0.5s;
}
.content .description {
font-size: 1.125rem;
line-height: 1.75rem;
color: #9CA3AF;

.heading__credits a {
text-decoration: underline;
@media (min-width: 1280px) {
font-size: 1.25rem;
line-height: 1.75rem;
}
}

/* CARDS */
.cards {
/* Modules */
.modules_grid {
display: grid;
gap: 20px;
grid-template-columns: repeat(2, minmax(0, 1fr));
margin-top: 30px;
}
margin-top: 2.5rem;
gap: 2rem;

@media (min-width: 768px) {
grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 1280px) {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
}
.card {
padding: 20px;
width: 100%;
min-height: 200px;
display: grid;
grid-template-rows: 20px 50px 1fr 50px;
position: relative;
padding: 30px;
border-radius: 10px;
box-shadow: 0px 6px 10px rgba(0, 0, 0, 0.25);
transition: all 0.2s;
cursor: default;
transition: 0.5s;
box-shadow: inset 5px 5px 5px rgba(0, 0, 0, 0.2),
inset -5px -5px 15px rgba(255, 255, 255, 0.1),
5px 5px 15px rgba(0, 0, 0, 0.3), -5px -5px 15px rgba(255, 255, 255, 0.1);
}

.card:hover {
box-shadow: 0px 6px 10px rgba(0, 0, 0, 0.4);
transform: scale(1.01);
.card .layout {
display: flex;
flex-direction: column;
gap: 2rem;
justify-content: space-between;
height: 100%;
}

.card__link {
position: relative;
text-decoration: underline;
color: rgba(255, 255, 255, 0.9);
.card .layout .group {
display: flex;
flex-direction: column;
gap: 0.75rem;
}

.card__title {
font-weight: 400;
color: #ffffff;
font-size: 30px;
.card .layout .heading {
font-size: 1.5rem;
line-height: 2rem;
font-weight: 700;
}

.card__body {
grid-row: 2/4;
.card .layout .description {
color: #D1D5DB;
}

.card__body p {
color: #ffffff;
.card .layout .group .actions {
display: flex;
gap: 0.5rem;
}

.card__action {
grid-row: 5/6;
align-self: center;
/* Footer */
.footer {
display: flex;
gap: 20px
padding-top: 1rem;
padding-bottom: 1rem;
margin-top: 2.5rem;
justify-content: space-between;
align-items: center;
border-top-width: 1px;
border-color: #1F2937;
width: 100%;
}

/* RESPONSIVE */
.footer .social {
display: flex;
gap: 1.25rem;
align-items: center;
}

@media (max-width: 1600px) {
.main-container {
max-width: 100vw;
padding: 50px;
}
/* Special */
.gradient__text {
background: linear-gradient(to right, #7bceb6 10%, #12a87b 40%, #0FCF97 60%, #7bceb6 90%);
background-size: 200% auto;
color: #000;
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
animation: shine 1s linear infinite;
}

.cards {
justify-content: center;
grid-template-columns: repeat(1, minmax(0, 1fr));
@keyframes shine {
to {
background-position: 200% center;
}
}
${css}
.hover-underline-animation {
display: inline-block;
position: relative;
color: #5BF3C7;
text-decoration: none;
}

.hover-underline-animation::after {
content: '';
position: absolute;
width: 100%;
transform: scaleX(0);
height: 2px;
bottom: 0;
left: 0;
background-color: #5BF3C7;
transform-origin: bottom right;
transition: transform 0.25s ease-out;
}

.hover-underline-animation:hover::after {
transform: scaleX(1);
transform-origin: bottom left;
}
</style>
`
}
86 changes: 86 additions & 0 deletions src/steps/2.addModules/generateModuleComponents.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
export function generateModuleHTMLComponent (
title: string,
description: string,
documentationLink: string,
demo: string,
actions: string
): {html: string} {
const html = `<div class="layout">
<div class="group">
<h1 class="heading">
${title}
</h1>
<p class="description">
${description}
</p>
</div>
<div class="group">
${demo}
<div class="actions">
<WelcomeButtonLink href="${documentationLink}" :blank="true">
Documentation
</WelcomeButtonLink>
${actions}
</div>
</div>
</div>`
return {
html,
}
}

export function generateModuleHTMLSnippet (componentName: string) {
const html = ` <div class="card">
<${componentName} />
</div>`
return {
html,
}
}

export const buttonLink = `<script setup lang="ts">
defineProps({
blank: {
type: Boolean,
required: false,
default: false
},
href: {
type: String,
default: ''
},
})
</script>

<template>
<NuxtLink class="ButtonLink" :to="href" :target="blank ? '_blank' : undefined">
<slot />
</NuxtLink>
</template>

<style scoped>
.ButtonLink {
position: relative;
padding: 5px 15px;
color: white;
background-image: linear-gradient(160deg, #059669, #059669);
border-radius: 0.3rem;
cursor: pointer;
user-select: none;
transition: box-shadow 0.6s;
}
.ButtonLink:hover {
box-shadow: 0 0 60px 2px #059669, 0.5rem 0.5rem 30px #059669;
}
.ButtonLink:after {
content: '';
position: absolute;
top: 2px;
right: 2px;
bottom: 2px;
left: 2px;
border-radius: 0.75rem;
pointer-events: none;
}
</style>
`
Loading