feat: website release v2 (#616)
* feat: upgrade to svelte 5 & tailwind v4 + add navigation menu to ui package * feat: website navigation with nav menu from shadcn * chore: refactor navigation menu storybook * fix: responsiveness bug * chore: remove tailwind config file * chore: - remove carbon icons from repo - add Geist font family * refactor website --------- Co-authored-by: Rotimi Best <[email protected]>
This commit is contained in:
co-authored by
Rotimi Best
parent
690cf147ff
commit
e6a3cf9332
@@ -0,0 +1,48 @@
|
||||
<script>
|
||||
import { Badge } from '@cio/ui/base/badge';
|
||||
import { formatDate } from '$lib/utils/format-date';
|
||||
|
||||
export let post;
|
||||
export let isRecommended = false;
|
||||
</script>
|
||||
|
||||
{#if !isRecommended}
|
||||
<div class="mb-5 flex md:flex-row flex-col md:items-center gap-2">
|
||||
<!-- Date -->
|
||||
<p class="text-sm text-slate-500">{formatDate(post.date)}</p>
|
||||
|
||||
<!-- Tags -->
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
{#each post.tags as tag}
|
||||
<Badge variant="outline">{tag}</Badge>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<a href="/blog/{post.slug}" class="group">
|
||||
<img
|
||||
loading="lazy"
|
||||
src={post.imageUrl}
|
||||
alt={post.title}
|
||||
class="w-70 h-48 object-cover rounded-md"
|
||||
/>
|
||||
<p
|
||||
class="font-bold text-lg py-2 {isRecommended &&
|
||||
'h-[60px]'} line-clamp-2 group-hover:text-slate-500"
|
||||
>
|
||||
{@html post.title}
|
||||
</p>
|
||||
|
||||
<p class="text-slate-500 pt-2 mb-4 line-clamp-3">{post.description}</p>
|
||||
</a>
|
||||
|
||||
<div class="flex items-center justify-start gap-4 my-2">
|
||||
<img loading="lazy" src={post.avatar} alt="avatar" class="w-10 h-10 rounded-full" />
|
||||
<span>
|
||||
<p class="font-semibold">{post.author}</p>
|
||||
<p class="text-slate-500">{post.role}</p>
|
||||
</span>
|
||||
</div>
|
||||
@@ -0,0 +1,64 @@
|
||||
<script>
|
||||
import { flexible, leftFist, rightFist, robotArm, thumbsUp } from '$lib/emojis';
|
||||
|
||||
export let id = '';
|
||||
export let rightToLeft = false;
|
||||
export let tagline = '';
|
||||
export let title = '';
|
||||
export let description = '';
|
||||
export let video = '';
|
||||
export let taglineIcon = '';
|
||||
</script>
|
||||
|
||||
<section {id} class="w-full py-32 border-b border-x-0 border-t-0 border-gray-200">
|
||||
<div
|
||||
class="w-4/5 mx-auto flex flex-col {rightToLeft
|
||||
? 'lg:flex-row-reverse'
|
||||
: 'lg:flex-row'} items-center justify-between gap-8 lg:gap-28"
|
||||
>
|
||||
<div class="w-[80vw] flex flex-col">
|
||||
<div class="my-2 lg:my-4 ml-1 flex gap-2 items-center">
|
||||
{#if taglineIcon === 'simplified'}
|
||||
<img width="27" height="27" loading="lazy" src={thumbsUp} alt="" class="w-7" />
|
||||
{:else if taglineIcon === 'flexible'}
|
||||
<img width="27" height="27" loading="lazy" src={flexible} alt="" class="w-7" />
|
||||
{:else if taglineIcon === 'collaboration'}
|
||||
<div class="flex items-center">
|
||||
<img width="24" height="24" loading="lazy" src={leftFist} alt="" class="w-6" />
|
||||
<img width="24" height="24" loading="lazy" src={rightFist} alt="" class="w-6" />
|
||||
</div>
|
||||
{:else if taglineIcon === 'productivity'}
|
||||
<img width="27" height="27" loading="lazy" src={robotArm} alt="" class="w-7" />
|
||||
{/if}
|
||||
<p class="font-medium text-base">{tagline}</p>
|
||||
</div>
|
||||
<h2 class="font-bold text-4xl mb-3 lg:mb-6">{title}</h2>
|
||||
<p class="leading-8 text-lg text-gray-500">
|
||||
{description}
|
||||
</p>
|
||||
{#if $$slots.more}
|
||||
<br />
|
||||
|
||||
<p class="leading-8 text-lg text-gray-500">
|
||||
<slot name="more" />
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="w-[80vw] md:w-[80vw] lg:w-full">
|
||||
<video
|
||||
width="100%"
|
||||
height="100%"
|
||||
class="w-full h-auto lg:max-h-[80%] rounded-md shadow-xl"
|
||||
autoplay
|
||||
loop
|
||||
muted
|
||||
defaultMuted
|
||||
playsinline
|
||||
preload="auto"
|
||||
>
|
||||
<source src={video} type="video/mp4" />
|
||||
<track kind="captions" />
|
||||
</video>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,106 @@
|
||||
<script lang="ts">
|
||||
import Section from './core-feature-section.svelte';
|
||||
import { PUBLIC_ENABLE_STATS } from '$env/static/public';
|
||||
</script>
|
||||
|
||||
<section class="w-full py-32 border-b border-x-0 border-t-0 border-gray-200">
|
||||
<div class="justify-center flex text-center flex-wrap gap-x-12 gap-y-16">
|
||||
<div class="w-full min-w-0" style="max-width: 1000px; flex: 1 1 550px;">
|
||||
<div class="mx-auto flex max-w-lg flex-col items-center gap-2">
|
||||
<div class="flex-none">
|
||||
<div class="">
|
||||
<img
|
||||
src="https://senjaio.b-cdn.net/public/avatar/406f29d4-5811-4f2e-90c1-e586fce3b3a7_me.JPEG?width=78&height=78&format=webp"
|
||||
alt="Pranav Singhal avatar"
|
||||
class="rounded-full"
|
||||
loading="lazy"
|
||||
referrerpolicy="no-referrer"
|
||||
style="width: 52px; height: 52px;"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-base leading-snug text-center">
|
||||
<span class="font-bold opacity-50 text-4xl">“</span>
|
||||
<span class="text-gray-800" style="font-size: 17px;"
|
||||
>ClassroomIO really helped me bootstrap my program. The dashboard is extremely
|
||||
intuitive. I could navigate most of it without any help / support. Coming from framer, I
|
||||
can honestly say that I am extremely greatful that I found ClassroomIO.</span
|
||||
> <span class="font-bold opacity-50 inline-block text-4xl">”</span>
|
||||
</div>
|
||||
<div class="mx-auto flex items-center gap-2 justify-center">
|
||||
<div
|
||||
class="flex max-w-[200px] flex-none flex-col overflow-hidden text-left"
|
||||
style="color: var(--clr-text);"
|
||||
>
|
||||
<div class="text-center text-sm font-medium opacity-90">
|
||||
Pranav Singhal <div class="block text-xs font-medium opacity-70 hover:opacity-50">
|
||||
Founder at <a href="https://www.dblocked.io/" target="_blank">DBlockEd</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<Section
|
||||
id="coursemanagement"
|
||||
tagline="Simplified"
|
||||
title="Course Management"
|
||||
description="ClassroomIO simplifies teaching tasks, boosts the educational experience, and is beneficial for both educators and students, providing a user-friendly platform for assessment, grading, attendance, and scorebook management."
|
||||
video="https://brand.cdn.clsrio.com/course-management.mp4"
|
||||
rightToLeft={true}
|
||||
/>
|
||||
<Section
|
||||
id="ai"
|
||||
tagline="Efficient"
|
||||
title="AI Support"
|
||||
description="Our platform integrates AI to simplify lesson outline generation, streamline lesson planning and spark creative ideas. With ClassroomIO, educators can focus on what matters most: teaching."
|
||||
rightToLeft={false}
|
||||
video="https://brand.cdn.clsrio.com/ai-lesson.mp4"
|
||||
/>
|
||||
<Section
|
||||
id="customization"
|
||||
tagline="Flexible"
|
||||
title="Dashboard Customization"
|
||||
description="ClassroomIO offers organizations the ability to tailor our LMS to their specific requirements. With our customizable features, you can create a personalized learning environment that aligns with your organization's goals"
|
||||
rightToLeft={true}
|
||||
video="https://brand.cdn.clsrio.com/lms-customization.mp4"
|
||||
/>
|
||||
<Section
|
||||
id="collaboration"
|
||||
tagline="Collaborative"
|
||||
title="Student and Teacher Community"
|
||||
description="Our platform includes a forum-like feature where students and teachers can ask and answer questions, creating a collaborative learning environment. This fosters engagement and knowledge sharing among the community"
|
||||
video="https://brand.cdn.clsrio.com/community.mp4"
|
||||
rightToLeft={false}
|
||||
/>
|
||||
|
||||
<!-- body section 5 -->
|
||||
{#if PUBLIC_ENABLE_STATS}
|
||||
<div
|
||||
class="flex justify-between flex-row flex-wrap lg:flex-nowrap items-center text-center px-[10%] py-[7%] border-b-[1px] gap-y-20 gap-x-20 mx-0 lg:mx-[12%]"
|
||||
>
|
||||
<div class="w-full">
|
||||
<h2
|
||||
class="w-full order-first text-3xl font-semibold tracking-tight text-gray-900 sm:text-5xl"
|
||||
>
|
||||
1 thousand
|
||||
</h2>
|
||||
<p class="text-base leading-7 text-gray-600">Feedback collected</p>
|
||||
</div>
|
||||
<div class="w-full">
|
||||
<h2 class="order-first text-3xl font-semibold tracking-tight text-gray-900 sm:text-5xl">
|
||||
5 thousand
|
||||
</h2>
|
||||
<p class="text-base leading-7 text-gray-600">Documents processed</p>
|
||||
</div>
|
||||
<div class="w-full">
|
||||
<h2 class="order-first text-3xl font-semibold tracking-tight text-gray-900 sm:text-5xl">
|
||||
1 million
|
||||
</h2>
|
||||
<p class="text-base leading-7 text-gray-600">Page views recorded</p>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -0,0 +1,13 @@
|
||||
<script lang="ts">
|
||||
export let src: string;
|
||||
export let alt: string;
|
||||
</script>
|
||||
|
||||
<figure>
|
||||
<img
|
||||
{src}
|
||||
{alt}
|
||||
loading="lazy"
|
||||
class="max-w-full w-full h-full md:min-h-[400px] object-cover my-2 rounded-lg"
|
||||
/>
|
||||
</figure>
|
||||
@@ -0,0 +1,40 @@
|
||||
<script>
|
||||
import { faqs } from '$lib/utils/faqs';
|
||||
import { PageSignupCTA } from '$lib/components';
|
||||
import * as Accordion from '@cio/ui/base/accordion';
|
||||
</script>
|
||||
|
||||
<div class="mb-20 mt-10 flex flex-col items-center justify-center">
|
||||
<header class="text-center">
|
||||
<h1 class="mt-2 text-xl md:text-4xl">
|
||||
Questions & Answers
|
||||
</h1>
|
||||
<p
|
||||
class="mt-4 text-sm md:text-lg font-normal tracking-normal ui:text-muted-foreground lg:px-[20%] lg:text-xl lg:tracking-wide"
|
||||
>
|
||||
Can't find the answer you're looking for?
|
||||
<a class="font-semibold text-blue-700" href="mailto:[email protected]" target="_blank"
|
||||
>Shoot us an email</a> and we'll get back to you ASAP.
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<div class="mt-[20%] lg:m-0 max-w-3xl w-full mx-auto px-2">
|
||||
<Accordion.Root type="single" class="w-full">
|
||||
{#each faqs as faq, index}
|
||||
<Accordion.Item value="faq-{index}">
|
||||
<Accordion.Trigger>{faq.question}</Accordion.Trigger>
|
||||
<Accordion.Content>
|
||||
{faq.answer}
|
||||
</Accordion.Content>
|
||||
</Accordion.Item>
|
||||
{/each}
|
||||
</Accordion.Root>
|
||||
</div>
|
||||
|
||||
<PageSignupCTA
|
||||
header="Your Custom Academy – Up & Running in Minutes!"
|
||||
subText="Try before you buy. No credit card required."
|
||||
btnLabel="Book a demo"
|
||||
link="classroomio/demo"
|
||||
/>
|
||||
</div>
|
||||
@@ -0,0 +1,144 @@
|
||||
<script>
|
||||
import { Button } from '@cio/ui/base/button';
|
||||
import Facebook from '@lucide/svelte/icons/facebook';
|
||||
import Youtube from '@lucide/svelte/icons/youtube';
|
||||
</script>
|
||||
|
||||
<div class="border-t-[1px] px-[2%] lg:px-[14%]">
|
||||
<div class="flex flex-col items-center justify-between py-[10%] pl-5 lg:flex-row lg:pl-0">
|
||||
<div class="w-full min-w-[200px] lg:w-3/12">
|
||||
<img width="32" height="32" loading="lazy" src="/logo-192.png" alt="classroomio logo" class="mb-5" />
|
||||
<p class="mb-5 mr-2 text-sm leading-7 tracking-wide text-gray-600 lg:text-base lg:leading-7">
|
||||
The Open Source Learning Management System for Companies
|
||||
<br />
|
||||
ClassroomIO is the easiest way to grow your teaching business.
|
||||
</p>
|
||||
<!-- <a
|
||||
href="https://www.producthunt.com/posts/classroomio?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-classroomio"
|
||||
target="_blank"
|
||||
><img
|
||||
loading="lazy"
|
||||
src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=425236&theme=light"
|
||||
alt="ClassroomIO - The Open Source Platform for Tech Bootcamps | Product Hunt"
|
||||
style="width: 250px; height: 54px;"
|
||||
width="250"
|
||||
height="54"
|
||||
/></a
|
||||
> -->
|
||||
<div class="mt-5 flex items-center gap-3 lg:mt-10 lg:gap-7">
|
||||
<Button href="https://www.facebook.com/classroomiohq" target="_blank" variant="ghost" aria-label="Facebook Link">
|
||||
<Facebook />
|
||||
</Button>
|
||||
<Button href="https://twitter.com/classroomio" target="_blank" variant="ghost" aria-label="Twitter Link">
|
||||
<img
|
||||
width="20"
|
||||
height="20"
|
||||
loading="lazy"
|
||||
src="/twitter.svg"
|
||||
alt=""
|
||||
/>
|
||||
</Button>
|
||||
<Button href="https://www.youtube.com/@ClassroomIO" target="_blank" variant="ghost" aria-label="Youtube Link">
|
||||
<Youtube />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav
|
||||
class="mt-16 flex w-full flex-col items-start justify-end gap-12 space-y-6 lg:mt-0 lg:w-3/4 lg:flex-row lg:space-y-0"
|
||||
>
|
||||
<div class="max-w-[120px]">
|
||||
<p class="mb-3 text-base font-semibold leading-6 text-gray-900 lg:mb-10 lg:text-base">Product</p>
|
||||
<ul class="space-y-2 lg:space-y-4">
|
||||
<li class="text-sm leading-6 tracking-wide text-gray-600 hover:text-gray-900 lg:text-base">
|
||||
<a href="/#coursemanagement"> Course Management </a>
|
||||
</li>
|
||||
<li class="text-sm leading-6 tracking-wide text-gray-600 hover:text-gray-900 lg:text-base">
|
||||
<a href="/#customization"> Customizations </a>
|
||||
</li>
|
||||
<li class="text-sm leading-6 tracking-wide text-gray-600 hover:text-gray-900 lg:text-base">
|
||||
<a href="/#collaboration"> Forum </a>
|
||||
</li>
|
||||
<li class="text-sm leading-6 tracking-wide text-gray-600 hover:text-gray-900 lg:text-base">
|
||||
<a href="/#ai"> AI Lesson Planner </a>
|
||||
</li>
|
||||
<li class="text-sm leading-6 tracking-wide text-gray-600 hover:text-gray-900 lg:text-base">
|
||||
<a href="/#student-dashboard"> Student Dashboard </a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="max-w-[120px]">
|
||||
<p class="mb-3 text-base font-semibold leading-6 text-gray-900 lg:mb-10 lg:text-base">Solutions</p>
|
||||
<ul class="space-y-2 lg:space-y-4">
|
||||
<li class="text-sm leading-6 tracking-wide text-gray-600 hover:text-gray-900 lg:text-base">
|
||||
<a href="/employee-training">Employee Training</a>
|
||||
</li>
|
||||
<li class="text-sm leading-6 tracking-wide text-gray-600 hover:text-gray-900 lg:text-base">
|
||||
<a href="/bootcamps">Bootcamps</a>
|
||||
</li>
|
||||
<li class="text-sm leading-6 tracking-wide text-gray-600 hover:text-gray-900 lg:text-base">
|
||||
<a href="/customer-education">Customer Education</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="max-w-[120px]">
|
||||
<p class="mb-3 text-base font-semibold leading-6 text-gray-900 lg:mb-10 lg:text-base">Resources</p>
|
||||
<ul class="space-y-2 lg:space-y-4">
|
||||
<li class="text-sm leading-6 tracking-wide text-gray-600 hover:text-gray-900 lg:text-base">
|
||||
<a href="/contact">Contact us</a>
|
||||
</li>
|
||||
<li class="text-sm leading-6 tracking-wide text-gray-600 hover:text-gray-900 lg:text-base">
|
||||
<a href="/teach">Teach with us</a>
|
||||
</li>
|
||||
<li class="text-sm leading-6 tracking-wide text-gray-600 hover:text-gray-900 lg:text-base">
|
||||
<a target="_blank" href="https://classroomio.com/docs/"> Help center </a>
|
||||
</li>
|
||||
<li class="text-sm leading-6 tracking-wide text-gray-600 hover:text-gray-900 lg:text-base">
|
||||
<a target="_blank" href="https://classroomio.com/docs/quickstart/signup"> Getting Started </a>
|
||||
</li>
|
||||
<li class="text-sm leading-6 tracking-wide text-gray-600 hover:text-gray-900 lg:text-base">
|
||||
<a href="/oss-friends"> OSS Friends </a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="max-w-[120px]">
|
||||
<p class="mb-3 text-base font-semibold leading-6 text-gray-900 lg:mb-10 lg:text-base">Company</p>
|
||||
<ul class="space-y-2 lg:space-y-4">
|
||||
<li class="text-sm leading-6 tracking-wide text-gray-600 hover:text-gray-900 lg:text-base">
|
||||
<a href="/roadmap"> Roadmap </a>
|
||||
</li>
|
||||
<li class="text-sm leading-6 tracking-wide text-gray-600 hover:text-gray-900 lg:text-base">
|
||||
<a href="mailto:[email protected]" target="_blank"> Support </a>
|
||||
</li>
|
||||
<li class="text-sm leading-6 tracking-wide text-gray-600 hover:text-gray-900 lg:text-base">
|
||||
<a href="https://app.enzuzo.com/policies/privacy/958fc978-5477-11ee-a03b-7b111830c594" target="_blank">
|
||||
Privacy policy
|
||||
</a>
|
||||
</li>
|
||||
<li class="text-sm leading-6 tracking-wide text-gray-600 hover:text-gray-900 lg:text-base">
|
||||
<a target="_blank" href="https://classroomio.com/docs/quickstart/signup"> Getting Started </a>
|
||||
</li>
|
||||
<li class="text-sm leading-6 tracking-wide text-gray-600 hover:text-gray-900 lg:text-base">
|
||||
<a href="https://app.enzuzo.com/policies/tos/958fc978-5477-11ee-a03b-7b111830c594" target="_blank">
|
||||
Terms of use
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
<footer
|
||||
class="border-t py-3 text-center text-xs font-light leading-5 text-gray-500 lg:text-left lg:text-base"
|
||||
>
|
||||
<p>All rights reserved.</p>
|
||||
<p class="flex items-center justify-center">
|
||||
ClassroomIO © {new Date().getFullYear()} by
|
||||
<a href="https://twitter.com/rotimi_best" target="_blank" class="mx-1 text-blue-700 underline">Rotimi Best</a>
|
||||
from
|
||||
<img loading="lazy" alt="Nigerian Flag" src="/ng.png" class="ml-2 h-3 w-3" />
|
||||
</p>
|
||||
</footer>
|
||||
</div>
|
||||
@@ -0,0 +1,227 @@
|
||||
<script lang="ts">
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
import { fly } from 'svelte/transition';
|
||||
import { sineInOut } from 'svelte/easing';
|
||||
import { PUBLIC_ENABLE_USERS_COMPANIES } from '$env/static/public';
|
||||
import { Button } from '@cio/ui/base/button';
|
||||
|
||||
const names = [
|
||||
{ label: 'Audience', color: '#3ADFEC' },
|
||||
{ label: 'Employees', color: '#BF0696' },
|
||||
{ label: 'Customers', color: '#0233BD' },
|
||||
{ label: 'Students', color: '#9747FF' }
|
||||
];
|
||||
let animate = false;
|
||||
let titleIndex = 0;
|
||||
let timeout: NodeJS.Timeout;
|
||||
|
||||
onMount(() => {
|
||||
setTimeout(() => {
|
||||
animate = true;
|
||||
}, 70);
|
||||
|
||||
timeout = setInterval(() => {
|
||||
const nextIndex = titleIndex + 1;
|
||||
titleIndex = names[nextIndex] ? nextIndex : 0;
|
||||
}, 3000);
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
clearTimeout(timeout);
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="hero-bg pt-18 relative h-full w-full border-b-2 bg-[#F5F8FE] text-center">
|
||||
<div class="w-full pt-24">
|
||||
<div class="mb-10 ml-[5%] flex w-full items-center justify-start lg:ml-0 lg:justify-center">
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer nofollow"
|
||||
href="/github"
|
||||
style="color: rgb(75, 85, 99);"
|
||||
class="rounded-full border-2 border-[#C2D2FF] bg-[#DCE5FF] px-4 py-1 text-sm font-medium text-[#4B5563] hover:underline"
|
||||
>We are <span class="ui:text-primary">100%</span> open source</a
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="absolute left-[5%] top-[10%] hidden w-[90%] justify-between lg:flex">
|
||||
{#if animate}
|
||||
<div
|
||||
class="relative rotate-12 transition-all hover:scale-110"
|
||||
transition:fly={{ y: 100, delay: 0, easing: sineInOut }}
|
||||
>
|
||||
<a
|
||||
href="/#collaboration"
|
||||
class="rounded-[4px] border-[1.5px] border-[#3ADFEC] bg-white px-6 py-2 text-lg font-bold text-[#3ADFEC]"
|
||||
>Collaboration</a
|
||||
>
|
||||
<svg
|
||||
class="absolute -bottom-2.5 -right-1"
|
||||
width="11"
|
||||
height="11"
|
||||
viewBox="0 0 11 11"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect width="10.9223" height="10.9223" fill="#3ADFEC" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="relative -rotate-12 transition-all hover:scale-110"
|
||||
transition:fly={{ x: 100, delay: 50, easing: sineInOut }}
|
||||
>
|
||||
<a
|
||||
href="/github"
|
||||
target="_blank"
|
||||
class="rounded-[4px] border-[1.5px] border-[#BF0696] bg-white px-6 py-2 text-lg font-bold text-[#BF0696]"
|
||||
>Open Source</a
|
||||
>
|
||||
<svg
|
||||
class="absolute -bottom-2.5 -right-1"
|
||||
width="11"
|
||||
height="11"
|
||||
viewBox="0 0 11 11"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect width="10.9223" height="10.9223" fill="#BF0696" />
|
||||
</svg>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="w-full">
|
||||
<div class="ml-6 text-left text-2xl font-semibold text-slate-900 lg:text-center lg:text-6xl">
|
||||
<span>Educate Your</span>
|
||||
<div class="mb-2 flex flex-wrap items-center justify-center lg:gap-3">
|
||||
<span
|
||||
class="relative mb-0 mt-1 inline-block h-[40px] w-full overflow-hidden md:mt-0 md:h-[50px] lg:-mb-4 lg:h-[75px] lg:w-[48%] lg:text-center"
|
||||
>
|
||||
{#key titleIndex}
|
||||
<span
|
||||
class="absolute left-0 right-[unset] w-full lg:left-[unset] lg:right-0"
|
||||
style="color: {names[titleIndex].color}"
|
||||
transition:fly={{ y: 100, delay: 0, easing: sineInOut }}
|
||||
>
|
||||
<span class="m-auto w-full text-center">
|
||||
{names[titleIndex].label}
|
||||
</span>
|
||||
</span>
|
||||
{/key}
|
||||
</span>
|
||||
</div>
|
||||
<span>from one Platform</span>
|
||||
</div>
|
||||
|
||||
<p class="mx-auto mt-10 px-4 ui:text-muted-foreground md:text-lg lg:mt-6 lg:w-[42%] lg:p-0">
|
||||
ClassroomIO is an open source learning management system for companies. We give you a suite
|
||||
of tools to help you achieve your training, onboarding and certification goals.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="absolute left-[5%] top-[30%] hidden w-[90%] justify-between lg:flex">
|
||||
{#if animate}
|
||||
<div
|
||||
class="relative -rotate-12 transition-all hover:scale-110"
|
||||
transition:fly={{ x: -100, delay: 100, easing: sineInOut }}
|
||||
>
|
||||
<a
|
||||
href="/#customization"
|
||||
class="rounded-[4px] border-[1.5px] border-[#0233BD] bg-white px-6 py-2 text-lg font-bold text-[#0233BD]"
|
||||
>
|
||||
Customizable LMS
|
||||
</a>
|
||||
|
||||
<svg
|
||||
class="absolute -bottom-2.5 -right-1"
|
||||
width="11"
|
||||
height="11"
|
||||
viewBox="0 0 11 11"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect width="10.9223" height="10.9223" fill="#0233BD" />
|
||||
</svg>
|
||||
</div>
|
||||
<div
|
||||
class="relative rotate-12 transition-all hover:scale-110"
|
||||
transition:fly={{ y: 100, delay: 150, easing: sineInOut }}
|
||||
>
|
||||
<a
|
||||
href="/#ai"
|
||||
class="rounded-[4px] border-[1.5px] border-[#9747FF] bg-white px-6 py-2 text-lg font-bold text-[#9747FF]"
|
||||
>AI Support</a
|
||||
>
|
||||
|
||||
<svg
|
||||
class="absolute -bottom-2.5 -right-1"
|
||||
width="11"
|
||||
height="11"
|
||||
viewBox="0 0 11 11"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect width="10.9223" height="10.9223" fill="#9747FF" />
|
||||
</svg>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="my-10 flex flex-col items-center justify-center gap-4 md:flex-row">
|
||||
<Button variant="outline" href="/demo" target="_blank" rel="noopener noreferrer nofollow">
|
||||
Book a demo
|
||||
</Button>
|
||||
<Button href="/signup" target="_blank" rel="noopener noreferrer nofollow">
|
||||
Sign Up for Free
|
||||
</Button>
|
||||
<!-- <a
|
||||
class="font-medium lg:font-semibold text-sm md:text-base w-11/12 md:w-fit border px-6 py-3 lg:px-10 lg:py-5 rounded-md"
|
||||
href="/github"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer nofollow"
|
||||
>
|
||||
View on Github
|
||||
</a> -->
|
||||
</div>
|
||||
|
||||
<!-- <div class="relative my-5 md:my-10">
|
||||
<img
|
||||
width="710"
|
||||
height="710"
|
||||
src="./cio-hero.webp"
|
||||
alt="hero section with dark vs light mode"
|
||||
class=""
|
||||
/>
|
||||
|
||||
</div> -->
|
||||
<div
|
||||
style="position: relative; padding-bottom: calc(50% + 42px);"
|
||||
class="mx-auto w-[85%] lg:w-[70%]"
|
||||
>
|
||||
<iframe
|
||||
title="ClassroomIO Live Demo"
|
||||
src="https://app.supademo.com/embed/cluw8chyy06nhq2s9m697a680"
|
||||
allow="clipboard-write"
|
||||
frameborder="0"
|
||||
webkitallowfullscreen="true"
|
||||
mozallowfullscreen="true"
|
||||
allowfullscreen
|
||||
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
{#if PUBLIC_ENABLE_USERS_COMPANIES}
|
||||
<div class="mb-[10%] px-[15%]">
|
||||
<h2 class="text-base font-semibold text-gray-900 lg:text-xl">Used at</h2>
|
||||
<div class="flex w-full flex-row flex-wrap items-center justify-between gap-5 py-[5%]">
|
||||
<img loading="lazy" src="/hero-1.svg" alt="" class="w-[30%] lg:w-[13%]" />
|
||||
<img loading="lazy" src="/hero-2.svg" alt="" class="w-[30%] lg:w-[13%]" />
|
||||
<img loading="lazy" src="/hero-3.svg" alt="" class="w-[30%] lg:w-[13%]" />
|
||||
<img loading="lazy" src="/hero-4.svg" alt="" class="w-[30%] lg:w-[13%]" />
|
||||
<img loading="lazy" src="/hero-5.svg" alt="" class="w-[30%] lg:w-[13%]" />
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,22 @@
|
||||
// UI Components - Named exports for easy importing
|
||||
export { default as BlogListItem } from './blog-list-item.svelte';
|
||||
export { default as CoreFeatureSection } from './core-feature-section.svelte';
|
||||
export { default as CoreFeatures } from './core-features.svelte';
|
||||
export { default as CustomImg } from './custom-img.svelte';
|
||||
export { default as Faq } from './faq.svelte';
|
||||
export { default as Footer } from './footer.svelte';
|
||||
export { default as Hero } from './hero.svelte';
|
||||
export { default as Modal } from './modal.svelte';
|
||||
export { default as MoreFeatures } from './more-features.svelte';
|
||||
export { default as Navigation } from './navigation.svelte';
|
||||
export { default as NotFound } from './not-found.svelte';
|
||||
export { default as PageHeader } from './page-header.svelte';
|
||||
export { default as PageSignupCTA } from './page-signup-cta.svelte';
|
||||
export { default as SenjaEmbed } from './senja-embed.svelte';
|
||||
export { default as StudentDashboard } from './student-dashboard.svelte';
|
||||
export { default as Success } from './success.svelte';
|
||||
export { default as Testimonial } from './testimonial.svelte';
|
||||
export { default as Timeline } from './timeline.svelte';
|
||||
export { default as ToolsHeader } from './tools-header.svelte';
|
||||
export { default as UploadWidget } from './upload-widget.svelte';
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<script>
|
||||
export let className = '';
|
||||
export let open = false;
|
||||
</script>
|
||||
|
||||
{#if open}
|
||||
<div class="relative flex items-center justify-center">
|
||||
<!-- black background -->
|
||||
<div class="fixed z-[3000] top-0 left-0 w-full h-full bg-black opacity-[0.7]"></div>
|
||||
<div
|
||||
class="fixed z-[3001] {className} w-full md:w-[30%] md:min-w-[500px] bg-white rounded-md mx-auto py-6 px-7"
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -0,0 +1,122 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { fly } from 'svelte/transition';
|
||||
import { folder, globe, team, transcription } from '$lib/emojis';
|
||||
import { tools } from '$lib/utils/constants/tools';
|
||||
|
||||
let selected = 0;
|
||||
let interval: NodeJS.Timer;
|
||||
|
||||
const moreFeatures = [
|
||||
{
|
||||
icon: globe,
|
||||
title: 'Customizable Landing Page',
|
||||
description:
|
||||
'A minimalistic landing page template out of the box to share your courses with the world',
|
||||
image: '/landing-page-builder.webp'
|
||||
},
|
||||
{
|
||||
icon: team,
|
||||
title: 'Team management',
|
||||
description:
|
||||
'Extend invitations and manage your teaching institution seamlessly through ClassroomIO.',
|
||||
image: '/team-management.png'
|
||||
},
|
||||
{
|
||||
icon: transcription,
|
||||
title: 'Auto Video Transcription',
|
||||
description:
|
||||
'AI automatically transcribes videos, making content searchable for seamless student access.',
|
||||
image: '/video-transcription.png'
|
||||
},
|
||||
{
|
||||
icon: folder,
|
||||
title: 'Downloadable Lesson PDF',
|
||||
description: 'Students can download lessons automatically for offline access.',
|
||||
image: '/download-pdf.png'
|
||||
}
|
||||
];
|
||||
|
||||
const freeTools = tools.filter((item) => item.showFeature);
|
||||
|
||||
onMount(() => {
|
||||
if (window.innerWidth > 768) {
|
||||
interval = setInterval(() => {
|
||||
selected = moreFeatures[selected + 1] ? selected + 1 : 0;
|
||||
}, 3000);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- More Features -->
|
||||
<section id="morefeatures" class="py-[10%] px-3 lg:px-0 bg-gray-50">
|
||||
<div class="mx-0 lg:mx-[12%]">
|
||||
<div class="w-full lg:w-4/5 mx-4 lg:mx-0 mb-14">
|
||||
<h2 class="mt-2 text-3xl font-bold font-display tracking-tight lg:text-4xl">
|
||||
There is More...
|
||||
</h2>
|
||||
<p class="mt-4 text-lg text-gray-500 w-[94%] lg:w-4/5">
|
||||
ClassroomIO is packed with useful features while we try to make it easy to use.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col-reverse lg:flex-row gap-3 md:gap-10" id="image-container">
|
||||
<div
|
||||
class="w-[95%] p-3 mt-5 overflow-auto lg:overflow-hidden lg:mt-0 lg:w-[45%] flex lg:block"
|
||||
>
|
||||
{#each moreFeatures as moreFeature, i}
|
||||
<button
|
||||
class="p-4 rounded-md {i === selected &&
|
||||
'selected'} mb-3 text-start min-w-[75vw] lg:min-w-[unset]"
|
||||
on:mouseenter={() => {
|
||||
selected = i;
|
||||
clearInterval(interval);
|
||||
}}
|
||||
>
|
||||
<div class="flex gap-1 items-center">
|
||||
<img
|
||||
loading="lazy"
|
||||
width="32"
|
||||
height="32"
|
||||
src={moreFeature.icon}
|
||||
alt=""
|
||||
class="w-8"
|
||||
/>
|
||||
<p class="text-lg font-semibold">
|
||||
{moreFeature.title}
|
||||
</p>
|
||||
</div>
|
||||
<p>{moreFeature.description}</p>
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<!-- Video -->
|
||||
<div class="h-full w-full p-3 lg:w-2/3 lg:p-0">
|
||||
{#key selected}
|
||||
<img
|
||||
width="100%"
|
||||
height="100%"
|
||||
loading="lazy"
|
||||
id="image"
|
||||
in:fly={{ y: 100, duration: 1000 }}
|
||||
class="w-full flex flex-col items-center"
|
||||
src={moreFeatures[selected].image}
|
||||
alt={moreFeatures[selected].title}
|
||||
/>
|
||||
{/key}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
#morefeatures .selected {
|
||||
background-image: linear-gradient(
|
||||
45deg,
|
||||
rgb(253, 239, 132),
|
||||
rgb(247, 198, 169),
|
||||
rgb(21, 186, 196)
|
||||
);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,379 @@
|
||||
<script lang="ts">
|
||||
import ChevronDown from '@lucide/svelte/icons/chevron-down';
|
||||
import Gamepad from '@lucide/svelte/icons/gamepad';
|
||||
import Hourglass from '@lucide/svelte/icons/hourglass';
|
||||
import LoaderCircle from '@lucide/svelte/icons/loader-circle';
|
||||
import LocateFixed from '@lucide/svelte/icons/locate-fixed';
|
||||
import Menu from '@lucide/svelte/icons/menu';
|
||||
import MessagesSquare from '@lucide/svelte/icons/messages-square';
|
||||
import MousePointerClick from '@lucide/svelte/icons/mouse-pointer-click';
|
||||
import Timer from '@lucide/svelte/icons/timer';
|
||||
import X from '@lucide/svelte/icons/x';
|
||||
import { page } from '$app/state';
|
||||
import { fly } from 'svelte/transition';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
import * as NavigationMenu from '@cio/ui/base/navigation-menu';
|
||||
import LibraryBigIcon from '@lucide/svelte/icons/library-big';
|
||||
|
||||
|
||||
export let stars: number;
|
||||
|
||||
let showDrawer = false;
|
||||
let showSolutions = false;
|
||||
let activeLink = '';
|
||||
|
||||
function handleShowDrawer() {
|
||||
showDrawer = !showDrawer;
|
||||
}
|
||||
|
||||
function handleShowSolutions() {
|
||||
showSolutions = !showSolutions;
|
||||
}
|
||||
|
||||
const solutions = [
|
||||
{
|
||||
key: 'employee-training',
|
||||
title: 'Employee Training',
|
||||
subtitle: 'Keep your team in sync.'
|
||||
},
|
||||
{
|
||||
key: 'bootcamps',
|
||||
title: 'Bootcamps',
|
||||
subtitle: 'Drive student satisfaction.'
|
||||
},
|
||||
{
|
||||
key: 'customer-education',
|
||||
title: 'Customer Education',
|
||||
subtitle: 'Teach customers your product.'
|
||||
}
|
||||
];
|
||||
|
||||
const freeTools = [
|
||||
{
|
||||
key: 'progress',
|
||||
title: 'Progress Tracker',
|
||||
subtitle: 'Monitor learning journeys.'
|
||||
},
|
||||
{
|
||||
key: 'pomodoro',
|
||||
title: 'Pomodoro Timer',
|
||||
subtitle: 'Boost focus and productivity.'
|
||||
},
|
||||
{
|
||||
key: 'name-picker',
|
||||
title: 'Name Picker',
|
||||
subtitle: 'Randomly select names.'
|
||||
},
|
||||
{
|
||||
key: 'stopwatch',
|
||||
title: 'Activity Stopwatch',
|
||||
subtitle: 'Track time accurately.'
|
||||
},
|
||||
{
|
||||
key: 'tic-tac-toe',
|
||||
title: 'Tic Tac Toe',
|
||||
subtitle: 'Play the classic game.'
|
||||
}
|
||||
];
|
||||
|
||||
type ListItemProps = HTMLAttributes<HTMLAnchorElement> & {
|
||||
title: string;
|
||||
href: string;
|
||||
subtitle: string;
|
||||
key: string;
|
||||
};
|
||||
|
||||
$: activeLink = page.url.pathname;
|
||||
$: activeHash = page.url.hash;
|
||||
$: isSolutionsActive = solutions.some((s) => activeHash.includes(s.key));
|
||||
</script>
|
||||
|
||||
{#snippet list_item({ title, subtitle, href, key, class: className, ...restProps }: ListItemProps)}
|
||||
<li>
|
||||
<NavigationMenu.Link>
|
||||
{#snippet child()}
|
||||
<a
|
||||
{href}
|
||||
class="flex w-full flex-row items-center rounded-lg p-2 no-underline transition-colors duration-200 hover:bg-gray-100 focus:bg-gray-100 focus:outline-none {className} [&_svg]:stroke-blue-600"
|
||||
{...restProps}
|
||||
>
|
||||
<div class="shrink-0">
|
||||
{#if key === 'employee-training'}
|
||||
<LibraryBigIcon size={24} />
|
||||
{:else if key === 'bootcamps'}
|
||||
<LocateFixed size={24} />
|
||||
{:else if key === 'customer-education'}
|
||||
<MessagesSquare size={24} />
|
||||
{:else if key === 'progress'}
|
||||
<LoaderCircle size={24} />
|
||||
{:else if key === 'pomodoro'}
|
||||
<Hourglass size={24} />
|
||||
{:else if key === 'name-picker'}
|
||||
<MousePointerClick size={24} />
|
||||
{:else if key === 'stopwatch'}
|
||||
<Timer size={24} />
|
||||
{:else if key === 'tic-tac-toe'}
|
||||
<Gamepad size={24} />
|
||||
{/if}
|
||||
</div>
|
||||
<div class="ml-3 text-start">
|
||||
<p class="text-sm">
|
||||
{title}
|
||||
</p>
|
||||
<p class="mt-1 text-xs ui:text-muted-foreground">
|
||||
{subtitle}
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
{/snippet}
|
||||
</NavigationMenu.Link>
|
||||
</li>
|
||||
{/snippet}
|
||||
|
||||
<section class="z-50 fixed top-0 w-full bg-white border-b">
|
||||
<div class="mx-auto flex w-full items-center justify-between gap-20 py-1 lg:w-[90%] lg:px-0 px-4">
|
||||
<a href="/" class="w-[10%]">
|
||||
<div class="flex w-full items-center">
|
||||
<img loading="lazy" width="28" height="28" src="/logo-512.png" alt="classroomio logo" class="w-6 md:w-7" />
|
||||
<h1 class="ml-2 text-xs font-medium md:text-base">ClassroomIO</h1>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<section class="hidden lg:block">
|
||||
<NavigationMenu.Root class="rounded-lg bg-white p-1">
|
||||
<NavigationMenu.List class="flex w-full items-center justify-center gap-1">
|
||||
<NavigationMenu.Item>
|
||||
<NavigationMenu.Trigger
|
||||
class="flex cursor-pointer items-center rounded-md px-4 py-2 text-sm font-medium text-gray-800 transition-all duration-200 hover:bg-gray-100 data-[state=open]:bg-gray-100"
|
||||
>
|
||||
<a href="/" class="no-underline"> Solutions </a>
|
||||
</NavigationMenu.Trigger>
|
||||
<NavigationMenu.Content>
|
||||
<ul class="grid w-[560px] grid-cols-2 gap-2 p-2">
|
||||
{#each solutions as solution}
|
||||
{@render list_item({
|
||||
href: `/${solution.key}`,
|
||||
title: solution.title,
|
||||
subtitle: solution.subtitle,
|
||||
key: solution.key
|
||||
})}
|
||||
{/each}
|
||||
</ul>
|
||||
</NavigationMenu.Content>
|
||||
</NavigationMenu.Item>
|
||||
|
||||
<NavigationMenu.Item>
|
||||
<NavigationMenu.Trigger
|
||||
class="flex cursor-pointer items-center rounded-md px-4 py-2 text-sm font-medium text-gray-800 transition-all duration-200 hover:bg-gray-100 data-[state=open]:bg-gray-100"
|
||||
>
|
||||
<a href="/tools" class="no-underline"> Free Tools </a>
|
||||
</NavigationMenu.Trigger>
|
||||
<NavigationMenu.Content>
|
||||
<ul class="grid w-[560px] grid-cols-2 gap-2 p-2">
|
||||
{#each freeTools as tool}
|
||||
{@render list_item({
|
||||
href: `/tools/${tool.key}`,
|
||||
title: tool.title,
|
||||
subtitle: tool.subtitle,
|
||||
key: tool.key
|
||||
})}
|
||||
{/each}
|
||||
</ul>
|
||||
</NavigationMenu.Content>
|
||||
</NavigationMenu.Item>
|
||||
|
||||
<NavigationMenu.Item>
|
||||
<NavigationMenu.Link>
|
||||
{#snippet child()}
|
||||
<a
|
||||
href="/blog"
|
||||
class="cursor-pointer rounded-md px-4 py-2 text-sm font-medium text-gray-800 no-underline transition-all duration-200 hover:bg-gray-100 {activeLink.startsWith(
|
||||
'/blog'
|
||||
)
|
||||
? 'bg-gray-100'
|
||||
: ''}"
|
||||
>
|
||||
Blog
|
||||
</a>
|
||||
{/snippet}
|
||||
</NavigationMenu.Link>
|
||||
</NavigationMenu.Item>
|
||||
|
||||
<NavigationMenu.Item>
|
||||
<NavigationMenu.Link>
|
||||
{#snippet child()}
|
||||
<a
|
||||
href="/pricing"
|
||||
class="cursor-pointer rounded-md px-4 py-2 text-sm font-medium text-gray-800 no-underline transition-all duration-200 hover:bg-gray-100 {activeLink.startsWith(
|
||||
'/pricing'
|
||||
)
|
||||
? 'bg-gray-100'
|
||||
: ''}"
|
||||
>
|
||||
Pricing
|
||||
</a>
|
||||
{/snippet}
|
||||
</NavigationMenu.Link>
|
||||
</NavigationMenu.Item>
|
||||
</NavigationMenu.List>
|
||||
</NavigationMenu.Root>
|
||||
</section>
|
||||
|
||||
<div class="hidden flex-row items-center justify-between gap-3 md:hidden lg:flex">
|
||||
<a href="/discord" target="_blank" class="flex items-center transition-opacity duration-200 hover:opacity-80">
|
||||
<img loading="lazy" alt="discord logo" src="/discord-blue.png" class="h-5 w-6 cursor-pointer" />
|
||||
</a>
|
||||
<div class="flex items-center">
|
||||
<a
|
||||
href="/github"
|
||||
target="_blank"
|
||||
class="group flex items-center gap-1.5 rounded-md p-2 transition-all duration-200 ease-in-out hover:bg-gray-100"
|
||||
>
|
||||
<img
|
||||
loading="lazy"
|
||||
alt="github logo"
|
||||
src="/github-mark.png"
|
||||
class="h-5 w-5 cursor-pointer transition-transform duration-200 group-hover:scale-110"
|
||||
/>
|
||||
<span
|
||||
class="text-sm font-medium leading-none text-gray-600 transition-colors duration-200 group-hover:text-black"
|
||||
>
|
||||
{stars}
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
<a
|
||||
class="text-sm font-medium transition-opacity duration-200 after:ml-2 after:content-['→'] hover:opacity-80"
|
||||
href="https://app.classroomio.com"
|
||||
>
|
||||
Dashboard
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<button type="button" aria-label="Hamburger Menu" class="block md:block lg:hidden" on:click={handleShowSolutions}>
|
||||
<Menu size={24} />
|
||||
</button>
|
||||
|
||||
{#if showSolutions}
|
||||
<div
|
||||
in:fly={{ x: 20, duration: 700 }}
|
||||
out:fly={{ x: 20, duration: 400 }}
|
||||
class="absolute right-0 top-0 h-screen w-[60%] border-2 bg-white px-3 pb-2 pt-3 sm:block md:w-[40%] md:p-7 lg:hidden"
|
||||
>
|
||||
<div class="mb-5 flex justify-between py-2">
|
||||
<img loading="lazy" width="20" height="20" src="/logo-512.png" alt="classroomio logo" class="w-[15%]" />
|
||||
<button class="mr-5" on:click={handleShowSolutions}>
|
||||
<X size={24} />
|
||||
</button>
|
||||
</div>
|
||||
<nav>
|
||||
<ul class="flex w-full flex-col items-center justify-between lg:flex-row">
|
||||
<li class="w-full cursor-pointer text-sm font-semibold text-gray-800 md:text-lg">
|
||||
<button
|
||||
class="flex w-full items-center justify-between rounded-lg px-4 py-3 transition-all duration-200 hover:bg-gray-100"
|
||||
on:click={handleShowDrawer}
|
||||
class:active={isSolutionsActive}
|
||||
>
|
||||
Our Superpowers <ChevronDown />
|
||||
</button>
|
||||
{#if showDrawer}
|
||||
<div in:fly={{ y: -20, duration: 700 }} out:fly={{ y: 20, duration: 400 }}>
|
||||
{#each solutions as solution}
|
||||
<a
|
||||
href="/{solution.key}"
|
||||
on:click={() => {
|
||||
handleShowSolutions();
|
||||
}}
|
||||
>
|
||||
<p
|
||||
class="rounded-lg py-2.5 pl-5 text-xs font-normal text-gray-700 transition-colors duration-200 hover:bg-gray-100"
|
||||
>
|
||||
{solution.title}
|
||||
</p>
|
||||
</a>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</li>
|
||||
<a
|
||||
class="w-full cursor-pointer rounded-xl px-4 py-3 text-sm font-semibold text-gray-800 transition-all duration-200 hover:bg-gray-100 md:text-lg"
|
||||
on:click={handleShowSolutions}
|
||||
href="/tools"
|
||||
>
|
||||
<li>Free Tools</li>
|
||||
</a>
|
||||
<a
|
||||
class="w-full cursor-pointer rounded-md px-4 py-3 text-sm font-semibold text-gray-800 transition-all duration-200 hover:bg-gray-100 md:text-lg"
|
||||
on:click={() => {
|
||||
handleShowSolutions();
|
||||
}}
|
||||
class:active={activeLink.startsWith('/blog')}
|
||||
href="/blog"
|
||||
>
|
||||
<li>Blog</li>
|
||||
</a>
|
||||
<a
|
||||
class="w-full cursor-pointer rounded-xl px-4 py-3 text-sm font-semibold text-gray-800 transition-all duration-200 hover:bg-gray-100 md:text-lg"
|
||||
on:click={() => {
|
||||
handleShowSolutions();
|
||||
}}
|
||||
href="/pricing"
|
||||
class:active={activeLink.startsWith('/pricing')}
|
||||
>
|
||||
<li>Pricing</li>
|
||||
</a>
|
||||
<a
|
||||
class="w-full cursor-pointer rounded-md px-4 py-3 text-sm font-semibold text-gray-800 transition-all duration-200 hover:bg-gray-100 md:text-lg"
|
||||
on:click={() => {
|
||||
handleShowSolutions();
|
||||
}}
|
||||
class:active={activeHash.includes('morefeatures')}
|
||||
href="/#morefeatures"
|
||||
>
|
||||
<li>More features</li>
|
||||
</a>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="mt-5 flex flex-col items-start gap-y-2 border-t pt-5">
|
||||
<a
|
||||
href="/discord"
|
||||
target="_blank"
|
||||
class="flex w-full items-center rounded-md px-4 py-4 text-left text-sm transition-all duration-200 hover:bg-gray-100 md:text-lg"
|
||||
>
|
||||
<img loading="lazy" alt="discord logo" src="/discord-blue.png" class="mr-2 h-5 w-6 cursor-pointer" />
|
||||
<span>Discord</span>
|
||||
</a>
|
||||
<a
|
||||
href="/github"
|
||||
target="_blank"
|
||||
class="group flex w-full items-center rounded-md px-4 py-4 text-left text-sm transition-all duration-200 hover:bg-gray-100 md:text-lg"
|
||||
>
|
||||
<img
|
||||
loading="lazy"
|
||||
alt="github logo"
|
||||
src="/github-mark.png"
|
||||
class="h-5 w-5 cursor-pointer transition-transform duration-200 group-hover:scale-110"
|
||||
/>
|
||||
<span class="ml-3 transition-colors duration-200 group-hover:text-black">Github</span>
|
||||
<span class="ml-1 text-sm font-medium text-gray-600 transition-colors duration-200 group-hover:text-black"
|
||||
>({stars})</span
|
||||
>
|
||||
</a>
|
||||
<a
|
||||
class="w-full rounded-md px-4 py-4 text-left text-sm font-semibold transition-all duration-200 after:ml-2 after:content-['→'] hover:bg-gray-100 md:text-lg"
|
||||
href="https://app.classroomio.com"
|
||||
>
|
||||
Dashboard
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.active {
|
||||
background-color: #f3f4f6;
|
||||
border-radius: 6px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,33 @@
|
||||
<script>
|
||||
import { goto } from '$app/navigation';
|
||||
import { Empty } from '@cio/ui/custom/empty';
|
||||
import SearchXIcon from '@lucide/svelte/icons/search-x';
|
||||
import { Button } from '@cio/ui/base/button';
|
||||
|
||||
export let isOrg = false;
|
||||
export let className = '';
|
||||
|
||||
function handleClick() {
|
||||
if (!isOrg) {
|
||||
return goto('/');
|
||||
}
|
||||
|
||||
return goto('https://classroomio.com');
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="{className} min-h-[80vh] w-screen flex items-center justify-center">
|
||||
|
||||
<Empty
|
||||
title={isOrg ? 'Organization doesn\'t exist!' : 'Page not found'}
|
||||
description="The page you are looking for doesn't exist or has been moved. Please go back to the homepage."
|
||||
icon={SearchXIcon}
|
||||
variant="page"
|
||||
>
|
||||
<Button
|
||||
onclick={handleClick}
|
||||
>
|
||||
Go Home
|
||||
</Button>
|
||||
</Empty>
|
||||
</div>
|
||||
@@ -0,0 +1,7 @@
|
||||
<script>
|
||||
export let className = '';
|
||||
</script>
|
||||
|
||||
<header class="hero-bg w-full border-b border-slate-100 pb-16 pt-32 lg:min-h-[20rem] {className}">
|
||||
<slot />
|
||||
</header>
|
||||
@@ -0,0 +1,60 @@
|
||||
<script lang="ts">
|
||||
import { Button } from '@cio/ui/base/button';
|
||||
|
||||
interface Props {
|
||||
header?: string;
|
||||
subText?: string;
|
||||
btnLabel?: string;
|
||||
link?: string;
|
||||
demo?: boolean;
|
||||
}
|
||||
|
||||
let { header = '', subText = '', btnLabel = '', link = '', demo = true }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="floating grad relative mx-auto my-5 flex h-[61vh] w-full flex-col items-center justify-center px-6 py-12 text-center shadow-2xl lg:h-[50vh] lg:w-[70%] lg:rounded-3xl max-w-4xl space-y-8"
|
||||
>
|
||||
<div>
|
||||
<h3
|
||||
class="font-display mt-3 text-xl font-semibold tracking-tight text-white lg:mt-2 lg:text-4xl max-w-2xl"
|
||||
>
|
||||
{header}
|
||||
</h3>
|
||||
<p class="mt-6 text-xl text-gray-300 lg:text-lg">
|
||||
{subText}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{#if demo}
|
||||
<Button
|
||||
variant="ghost"
|
||||
data-cal-config="'layout':'month_view'"
|
||||
data-cal-link="classroomio/demo"
|
||||
class="bg-white!"
|
||||
>
|
||||
{btnLabel}
|
||||
</Button>
|
||||
{:else}
|
||||
<Button
|
||||
href={link}
|
||||
variant="link"
|
||||
target="_blank"
|
||||
class="ui:bg-secondary ui:text-secondary-foreground"
|
||||
rel="noopener noreferrer nofollow"
|
||||
>
|
||||
{btnLabel}
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.grad {
|
||||
/* background: rgb(2, 51, 189);
|
||||
background: radial-gradient(circle at 50% 100%, rgba(2, 51, 189, 1) 1%, rgb(4, 2, 56) 100%); */
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
background-image: url('https://brand.cdn.clsrio.com/cta-bg.png');
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,12 @@
|
||||
<script lang="ts">
|
||||
import { embedSenjaWidget } from '@cio/utils/senja';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
export let id = '';
|
||||
|
||||
onMount(() => {
|
||||
embedSenjaWidget(id);
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="senja-embed" data-id={id} data-lazyload="false" data-spinner="false"></div>
|
||||
@@ -0,0 +1,34 @@
|
||||
<script>
|
||||
import { Badge } from '@cio/ui/base/badge';
|
||||
</script>
|
||||
|
||||
<section id="student-dashboard" class="text-center text-white py-[10%] px-3 lg:px-0 bg-black">
|
||||
<Badge class="py-2! px-4! underline text-sm!">yourorg.classroomio.com</Badge>
|
||||
<h1
|
||||
class="mx-auto text-3xl md:text-4xl lg:text-6xl font-normal leading-[1.5] flex flex-col items-center gap-4"
|
||||
>
|
||||
Your Student Dashboard
|
||||
</h1>
|
||||
|
||||
<p
|
||||
class="mx-auto mt-10 lg:mt-6 px-4 lg:p-0 text-base tracking-wide leading-6 text-gray-400 lg:w-2/4"
|
||||
>
|
||||
Once you create an account, you get a dedicated dashboard where your students can access all
|
||||
their courses, assignments, and more.
|
||||
</p>
|
||||
|
||||
<div class="relative my-5 md:my-10">
|
||||
<video
|
||||
class="floating w-[85%] lg:w-[70%] mx-auto rounded-lg shadow-lg"
|
||||
autoplay
|
||||
loop
|
||||
muted
|
||||
defaultMuted
|
||||
playsinline
|
||||
preload="auto"
|
||||
>
|
||||
<source src="https://video.cdn.clsrio.com/student-dashboard.mp4" type="video/mp4" />
|
||||
<track kind="captions" />
|
||||
</video>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,17 @@
|
||||
<script>
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
import { Button } from '@cio/ui/base/button';
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="relative overflow-hidden mt-10 flex space-y-3 flex-col text-center items-center border border-[#D9E0F5] justify-center w-full rounded-md min-h-[300px] p-4 bg-[#F5F8FE]"
|
||||
>
|
||||
<div class="absolute w-20 h-20 bg-[#0233BD] -top-14 -left-9 rotate-[50deg]" />
|
||||
<h1 class="font-bold text-3xl">Your message has been sent 🎉</h1>
|
||||
<p class="w-[70%] font-normal text-sm">
|
||||
We'll get back to you as soon as possible. In the meantime, Explore and enjoy features on our
|
||||
website
|
||||
</p>
|
||||
<Button class="px-10 md:px-20" onclick={() => goto('/')}>Go to Home</Button>
|
||||
</div>
|
||||
@@ -0,0 +1,29 @@
|
||||
<script>
|
||||
import { SenjaEmbed } from '$lib/components';
|
||||
import { Button } from '@cio/ui/base/button';
|
||||
</script>
|
||||
|
||||
<section id="testimonial" class="flex flex-col items-center py-[5%] px-3 lg:px-0 space-y-2">
|
||||
<h1
|
||||
class="mx-auto text-3xl md:text-4xl lg:text-5xl font-normal leading-normal flex flex-col items-center gap-4 my-0"
|
||||
>
|
||||
Hear from Happy ClassroomIO Users
|
||||
</h1>
|
||||
|
||||
<p
|
||||
class="mx-auto text-center px-4 lg:p-0 text-base tracking-wide leading-6 ui:text-muted-foreground lg:w-2/4"
|
||||
>
|
||||
See what excites them about building and managing bootcamps with ClassroomIO.
|
||||
</p>
|
||||
<Button
|
||||
href="/signup"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer nofollow"
|
||||
>
|
||||
Sign Up for Free
|
||||
</Button>
|
||||
|
||||
<div class="relative my-5 md:my-10 w-[85%] lg:w-[70%]">
|
||||
<SenjaEmbed id="3e847d7a-13d3-483e-8a71-5b35273dcc6c" />
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,32 @@
|
||||
<script lang="ts">
|
||||
export let items: {
|
||||
title: string;
|
||||
desc: string;
|
||||
}[] = [];
|
||||
</script>
|
||||
|
||||
<div class="relative w-fit flex justify-center space-x-8 md:space-x-10">
|
||||
<div
|
||||
class="w-[3px] md:w-[2px] bg-blue-600 mt-10 before:bg-gradient-to-t before:from-white before:to-transparent before:w-[4px] before:h-[9rem] before:absolute before:bottom-0"
|
||||
/>
|
||||
<div class="space-y-8">
|
||||
{#each items as card, index}
|
||||
<div class="md:w-[35rem] w-full border-2 rounded-lg px-4 py-8 space-y-4 bg-white">
|
||||
<div class="flex items-center">
|
||||
<div
|
||||
class={`z-50 absolute -left-3 ${
|
||||
index > 0 &&
|
||||
'before:bg-gradient-to-t before:from-white before:to-transparent before:w-[4px] before:h-[9rem] before:absolute before:-top-36'
|
||||
} flex items-center justify-center w-7 h-7 bg-blue-100 rounded-full`}
|
||||
>
|
||||
<div class="w-4 h-4 bg-blue-800 rounded-full z-50" />
|
||||
</div>
|
||||
<h1 class="text-2xl font-bold text-blue-800">{card.title}</h1>
|
||||
</div>
|
||||
<p class="text-base text-gray-500">
|
||||
{card.desc}
|
||||
</p>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,7 @@
|
||||
<script>
|
||||
export let className = '';
|
||||
</script>
|
||||
|
||||
<header class="tools-hero-bg py-24 text-center {className} border-b border-slate-100 bg-white">
|
||||
<slot />
|
||||
</header>
|
||||
@@ -0,0 +1,74 @@
|
||||
<script lang="ts">
|
||||
import Copy from '@lucide/svelte/icons/copy';
|
||||
import Trash2 from '@lucide/svelte/icons/trash-2';
|
||||
|
||||
export let imageURL = '';
|
||||
export let label = '';
|
||||
export let isRequired = false;
|
||||
export let labelClassName = '';
|
||||
let isUploading = false;
|
||||
let fileInput: HTMLInputElement;
|
||||
|
||||
const onFileSelected = () => {
|
||||
const file = fileInput?.files?.[0];
|
||||
const sizeInkb = file?.size! / 1024;
|
||||
if (sizeInkb > 500) {
|
||||
return;
|
||||
}
|
||||
if (file) {
|
||||
let reader = new FileReader();
|
||||
reader.readAsDataURL(file);
|
||||
reader.onloadend = () => {
|
||||
imageURL = reader.result as string;
|
||||
};
|
||||
}
|
||||
};
|
||||
const deleteImage = () => {
|
||||
imageURL = '';
|
||||
if (fileInput) {
|
||||
fileInput.value = '';
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div>
|
||||
{#if label}
|
||||
<p class="flex w-full items-center justify-between text-left dark:text-white {labelClassName}">
|
||||
<span>
|
||||
{label}
|
||||
{#if isRequired}
|
||||
<span class="text-red-700">*</span>
|
||||
{/if}
|
||||
</span>
|
||||
|
||||
{#if imageURL}
|
||||
<span title="clear image" on:click={deleteImage}>
|
||||
<Trash2 class="fill-red-500 " />
|
||||
</span>
|
||||
{/if}
|
||||
</p>
|
||||
{/if}
|
||||
<div
|
||||
class="flex min-h-[200px] w-full items-center justify-center rounded-md border p-4"
|
||||
on:click={() => fileInput.click()}
|
||||
>
|
||||
<input
|
||||
type="file"
|
||||
style="display: none;"
|
||||
bind:this={fileInput}
|
||||
on:change={onFileSelected}
|
||||
disabled={isUploading}
|
||||
required={isRequired}
|
||||
/>
|
||||
{#if imageURL}
|
||||
<img src={imageURL} alt="selected file" class="mt-4 h-auto w-[30%]" />
|
||||
{:else}
|
||||
<div class="space-y-4">
|
||||
<Copy size={24} class="mx-auto" />
|
||||
<p class="my-2 text-center text-sm text-gray-500">Max file size: 10MB, accepted: jpeg, jpg, png, gif</p>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user