Skip to content

Commit

Permalink
feat: add marquee (#5)
Browse files Browse the repository at this point in the history
* feat: add marquee

* feat: ui changes

* feat: add top 10 in marques

---------

Co-authored-by: Rotimi Best <[email protected]>
  • Loading branch information
tunny17 and rotimi-best authored Dec 4, 2024
1 parent f9914b2 commit 4d80d95
Show file tree
Hide file tree
Showing 10 changed files with 201 additions and 41 deletions.
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;

0 comments on commit 4d80d95

Please sign in to comment.