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: add marquee #5

Merged
merged 3 commits into from
Dec 4, 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
1 change: 1 addition & 0 deletions deno.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"tasks": {
"dev": "deno run fe:dev & deno run be:dev",
"fe:dev": "deno run -A --node-modules-dir npm:vite",
"fe:build": "deno run -A --node-modules-dir npm:vite build",
"fe:preview": "deno run -A --node-modules-dir npm:vite preview",
Expand Down
8 changes: 8 additions & 0 deletions src/lib/assets/star.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/lib/components/marquee/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Root from './marquee.svelte';
import MarqueeCard from './marquee-card.svelte';

export { Root, Root as Marquee, MarqueeCard };
47 changes: 47 additions & 0 deletions src/lib/components/marquee/marquee-card.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<script lang="ts">
import { cn } from '$lib/utils';
import starIcon from '$lib/assets/star.svg';

export let author_avatar: string;
export let name: string;
export let author: string;
export let description: string;
export let stars: number;
export let link: string;
</script>

<a
href={link}
target="_blank"
class={cn(
'relative w-72 cursor-pointer overflow-hidden rounded-2xl border p-4',
// light styles
'border-gray-950/[.1] bg-gray-950/[.01] hover:bg-gray-950/[.05]',
// dark styles
'dark:border-gray-50/[.1] dark:bg-gray-50/[.10] dark:hover:bg-gray-50/[.15]'
)}
>
<div class="flex flex-row justify-between items-center">
<div class="flex flex-row items-center gap-2">
<img
class="rounded-full"
width="32"
height="32"
alt=""
src={author_avatar}
/>
<div class="flex flex-col">
<!-- svelte-ignore a11y-structure -->
<figcaption class="text-sm font-medium dark:text-white">
{name}
</figcaption>
<p class="text-xs font-medium dark:text-white/40">{author}</p>
</div>
</div>
<div class="flex items-center gap-2">
<img src={starIcon} alt="" class="w-5 text-white fill-white" />
<p class="text-xs">{stars}</p>
</div>
</div>
<blockquote class="mt-2 text-sm line-clamp-3">{description}</blockquote>
</a>
34 changes: 34 additions & 0 deletions src/lib/components/marquee/marquee.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<script lang="ts">
import { cn } from '$lib/utils';
export let pauseOnHover: boolean = false;
export let vertical: boolean = false;
export let repeat: number = 4;
export let reverse: boolean = false;

let className: any = '';
export { className as class };
</script>

<div
class={cn(
'group flex overflow-hidden p-2 [--duration:2s] [--gap:1rem] [gap:var(--gap)]',
{
'flex-row': !vertical,
'flex-col': vertical,
},
className
)}
>
{#each { length: repeat } as _, i (i)}
<div
class={cn('flex shrink-0 justify-around [gap:var(--gap)]', {
'animate-marquee flex-row': !vertical,
'animate-marquee-vertical flex-col': vertical,
'group-hover:[animation-play-state:paused]': pauseOnHover,
'[animation-direction:reverse]': reverse,
})}
>
<slot>Default</slot>
</div>
{/each}
</div>
15 changes: 15 additions & 0 deletions src/lib/pages/home/author-display.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<script>
export let data = {
author: '',
author_link: '',
author_avatar: ''
};
</script>

<div class="flex items-center gap-3">
<a href={`${data.author_link}`}>
<img src={data.author_avatar} alt="" class="w-7 rounded-full" />
</a>

<a href={`${data.author_link}`}> {data.author}</a>
</div>
37 changes: 37 additions & 0 deletions src/lib/pages/home/hero.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<script lang="ts">
import type { Repository } from '$lib/types/repository';
import { Marquee, MarqueeCard } from '$lib/components/marquee';
import { BorderBeam } from '$lib/components/border-beam';

export let data: Repository[] = [];

let firstRow = data.slice(0, data.length / 2);
let secondRow = data.slice(data.length / 2);
</script>

<div
class="relative flex h-full w-full flex-col items-center justify-center overflow-hidden rounded-lg border bg-background py-2 mb-5"
>
<BorderBeam size={300} duration={12} />
<h2
class="mt-5 scroll-m-20 border-b pb-4 md:text-3xl text-center font-semibold tracking-tight transition-colors first:mt-0"
>
The Odogwu's
</h2>
<Marquee pauseOnHover class="[--duration:20s]">
{#each firstRow as item}
<MarqueeCard {...item} />
{/each}
</Marquee>
<Marquee reverse pauseOnHover class="[--duration:20s]">
{#each secondRow as item}
<MarqueeCard {...item} />
{/each}
</Marquee>
<div
class="pointer-events-none absolute inset-y-0 left-0 w-1/3 bg-gradient-to-r from-white dark:from-background"
></div>
<div
class="pointer-events-none absolute inset-y-0 right-0 w-1/3 bg-gradient-to-l from-white dark:from-background"
></div>
</div>
35 changes: 20 additions & 15 deletions src/lib/pages/home/page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import detectUrlChange from 'detect-url-change';

import Table from './table.svelte';
import Hero from './hero.svelte';

let repositories: Repository[] = [];
let apiMetadata: ApiMetadata = {
Expand Down Expand Up @@ -118,7 +119,7 @@
>
<Sidebar />

<div class="py-6 lg:gap-10 w-full max-w-2xl mx-auto">
<div class="py-6 lg:gap-10 w-full max-w-4xl mx-auto">
{#if isFetching && !isMounted}
<div class="rounded-md border w-full">
<div class="flex flex-col gap-4 p-4">
Expand All @@ -132,21 +133,25 @@
</div>
{:else}
<div>
<h2
class="mt-5 scroll-m-20 border-b pb-4 text-3xl font-semibold tracking-tight transition-colors first:mt-0"
>
Open source projects in Nigeria
</h2>
<Hero data={repositories} />

<div>
<h2
class="mt-5 scroll-m-20 border-b pb-4 text-3xl font-semibold tracking-tight text-center transition-colors first:mt-0"
>
All Projects
</h2>
</div>
{#key gettingFreshData}
<Table
data={repositories}
{apiMetadata}
bind:searchValue
isFetching={gettingFreshData}
onSearch={searchRepositories}
/>
{/key}
</div>
{#key gettingFreshData}
<Table
data={repositories}
{apiMetadata}
bind:searchValue
isFetching={gettingFreshData}
onSearch={searchRepositories}
/>
{/key}
{/if}
</div>
</div>
17 changes: 8 additions & 9 deletions src/lib/pages/home/table.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import {
Render,
Subscribe,
createRender,
// createRender,
createTable,
} from 'svelte-headless-table';
Expand All @@ -24,6 +25,7 @@
import * as Table from '$lib/components/table';
import { Button } from '$lib/components/button';
import { BorderBeam } from '$lib/components/border-beam';
import AuthorDisplay from './author-display.svelte';

export let data: Repository[] = [];
export let apiMetadata: ApiMetadata;
Expand Down Expand Up @@ -62,15 +64,14 @@
header: 'Name',
accessor: 'link',
}),
table.column({
header: '',
accessor: 'author_avatar',
cell: ({ value }) => value.toLowerCase(),
}),
table.column({
header: 'Author',
accessor: 'author',
cell: ({ value }) => value.toLowerCase(),
accessor: (data) => data,
cell: ({ value }) => {
return createRender(AuthorDisplay, {
data: value,
});
},
}),
table.column({
header: 'Stars',
Expand Down Expand Up @@ -109,8 +110,6 @@
const ids = flatColumns.map((c) => c.id);
let hideForId = Object.fromEntries(ids.map((id) => [id, true]));

const { filterValue } = pluginStates.filter;

function goToPage(page: number) {
const url = new URL(window.location.href);
url.searchParams.set('page', page.toString());
Expand Down
44 changes: 27 additions & 17 deletions tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ const config = {
center: true,
padding: '2rem',
screens: {
'2xl': '1400px',
},
'2xl': '1400px'
}
},
extend: {
colors: {
Expand All @@ -22,54 +22,64 @@ const config = {
foreground: 'hsl(var(--foreground) / <alpha-value>)',
primary: {
DEFAULT: 'hsl(var(--primary) / <alpha-value>)',
foreground: 'hsl(var(--primary-foreground) / <alpha-value>)',
foreground: 'hsl(var(--primary-foreground) / <alpha-value>)'
},
secondary: {
DEFAULT: 'hsl(var(--secondary) / <alpha-value>)',
foreground: 'hsl(var(--secondary-foreground) / <alpha-value>)',
foreground: 'hsl(var(--secondary-foreground) / <alpha-value>)'
},
destructive: {
DEFAULT: 'hsl(var(--destructive) / <alpha-value>)',
foreground: 'hsl(var(--destructive-foreground) / <alpha-value>)',
foreground: 'hsl(var(--destructive-foreground) / <alpha-value>)'
},
muted: {
DEFAULT: 'hsl(var(--muted) / <alpha-value>)',
foreground: 'hsl(var(--muted-foreground) / <alpha-value>)',
foreground: 'hsl(var(--muted-foreground) / <alpha-value>)'
},
accent: {
DEFAULT: 'hsl(var(--accent) / <alpha-value>)',
foreground: 'hsl(var(--accent-foreground) / <alpha-value>)',
foreground: 'hsl(var(--accent-foreground) / <alpha-value>)'
},
popover: {
DEFAULT: 'hsl(var(--popover) / <alpha-value>)',
foreground: 'hsl(var(--popover-foreground) / <alpha-value>)',
foreground: 'hsl(var(--popover-foreground) / <alpha-value>)'
},
card: {
DEFAULT: 'hsl(var(--card) / <alpha-value>)',
foreground: 'hsl(var(--card-foreground) / <alpha-value>)',
},
foreground: 'hsl(var(--card-foreground) / <alpha-value>)'
}
},
borderRadius: {
lg: 'var(--radius)',
md: 'calc(var(--radius) - 2px)',
sm: 'calc(var(--radius) - 4px)',
sm: 'calc(var(--radius) - 4px)'
},
fontFamily: {
sans: ['Inter', ...fontFamily.sans],
sans: ['Inter', ...fontFamily.sans]
},

animation: {
'border-beam': 'border-beam calc(var(--duration)*1s) infinite linear',
marquee: 'marquee var(--duration) linear infinite',
'marquee-vertical': 'marquee-vertical var(--duration) linear infinite'
},
keyframes: {
'border-beam': {
'100%': {
'offset-distance': '100%',
},
'offset-distance': '100%'
}
},
},
},
},
marquee: {
from: { transform: 'translateX(0)' },
to: { transform: 'translateX(calc(-100% - var(--gap)))' }
},
'marquee-vertical': {
from: { transform: 'translateY(0)' },
to: { transform: 'translateY(calc(-100% - var(--gap)))' }
}
}
}
}
};

export default config;
Loading