Skip to content

Commit

Permalink
feat: add marquee
Browse files Browse the repository at this point in the history
  • Loading branch information
tunny17 committed Dec 4, 2024
1 parent 9a04a17 commit 8a1863e
Show file tree
Hide file tree
Showing 7 changed files with 196 additions and 89 deletions.
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>
36 changes: 36 additions & 0 deletions src/lib/pages/home/hero.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<script lang="ts">
import type { Repository } from '$lib/types/repository';
import Marquee from './marquee.svelte';
import MarqueeCard from './marquee-card.svelte';
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-5 mb-5 md:shadow-xl"
>
<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"
>
Open 10 source projects in Nigeria
</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>
30 changes: 30 additions & 0 deletions src/lib/pages/home/marquee-card.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<script lang="ts">
import { cn } from '$lib/utils';
export let author_avatar: string;
export let name: string;
export let author: string;
export let description: string;
</script>

<figure
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 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>
<blockquote class="mt-2 text-sm">{description}</blockquote>
</figure>
34 changes: 34 additions & 0 deletions src/lib/pages/home/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>
49 changes: 27 additions & 22 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 All @@ -17,12 +18,12 @@
totalItems: 250,
itemsPerPage: 10,
hasNextPage: false,
hasPrevPage: false,
hasPrevPage: false
},
sort: {
sortBy: 'stars',
order: 'desc',
},
order: 'desc'
}
};
let currentPage: number = 1;
let currentOrder: string = 'desc';
Expand Down Expand Up @@ -57,11 +58,11 @@
repositories = result.data.map((repo: Repository, index: number) => ({
...repo,
id: index + 1 + (page - 1) * 10,
id: index + 1 + (page - 1) * 10
}));
apiMetadata = {
pagination: result.pagination,
sort: result.sort,
sort: result.sort
};
} catch (err: any) {
console.error(err);
Expand Down Expand Up @@ -91,11 +92,11 @@
const result = await response.json();
repositories = result.data.map((repo: Repository, index: number) => ({
...repo,
id: index + 1,
id: index + 1
}));
apiMetadata = {
pagination: result.pagination,
sort: result.sort,
sort: result.sort
};
} catch (err: any) {
console.error(err);
Expand All @@ -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 transition-colors first:mt-0"
>
Open source projects in Nigeria
</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>
77 changes: 27 additions & 50 deletions src/lib/pages/home/table.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
import {
Render,
Subscribe,
createRender,
// createRender,
createTable,
createTable
} from 'svelte-headless-table';
import {
addHiddenColumns,
addPagination,
addSortBy,
addTableFilter,
addTableFilter
} from 'svelte-headless-table/plugins';
import ArrowUpDown from 'lucide-svelte/icons/arrow-up-down';
import ArrowRight from 'lucide-svelte/icons/chevron-right';
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 All @@ -48,44 +50,43 @@
sort: addSortBy({ disableMultiSort: true }),
page: addPagination(),
filter: addTableFilter({
fn: ({ filterValue, value }) => value.includes(filterValue),
fn: ({ filterValue, value }) => value.includes(filterValue)
}),
hide: addHiddenColumns(),
hide: addHiddenColumns()
});
const columns = table.createColumns([
table.column({
header: '#',
accessor: 'id',
accessor: 'id'
}),
table.column({
header: 'Name',
accessor: 'link',
}),
table.column({
header: '',
accessor: 'author_avatar',
cell: ({ value }) => value.toLowerCase(),
accessor: 'link'
}),
table.column({
header: 'Author',
accessor: 'author',
cell: ({ value }) => value.toLowerCase(),
accessor: (data) => data,
cell: ({ value }) => {
return createRender(AuthorDisplay, {
data: value
});
}
}),
table.column({
header: 'Stars',
accessor: 'stars',
cell: ({ value }) => {
return value;
},
}
}),
table.column({
header: 'Forks',
accessor: 'forks',
cell: ({ value }) => {
return value;
},
}),
}
})
// table.column({
// header: '',
// accessor: (data) => data,
Expand All @@ -95,15 +96,8 @@
// }),
]);
const {
headerRows,
pageRows,
tableAttrs,
tableBodyAttrs,
flatColumns,
pluginStates,
rows,
} = table.createViewModel(columns);
const { headerRows, pageRows, tableAttrs, tableBodyAttrs, flatColumns, pluginStates, rows } =
table.createViewModel(columns);
const { hiddenColumnIds } = pluginStates.hide;
const ids = flatColumns.map((c) => c.id);
Expand Down Expand Up @@ -172,16 +166,8 @@
<Subscribe rowAttrs={headerRow.attrs()}>
<Table.Row>
{#each headerRow.cells as cell (cell.id)}
<Subscribe
attrs={cell.attrs()}
let:attrs
props={cell.props()}
let:props
>
<Table.Head
{...attrs}
class={cn('[&:has([role=checkbox])]:pl-3')}
>
<Subscribe attrs={cell.attrs()} let:attrs props={cell.props()} let:props>
<Table.Head {...attrs} class={cn('[&:has([role=checkbox])]:pl-3')}>
{#if cell.id === 'stars' || cell.id === 'forks'}
<Button
variant="ghost"
Expand All @@ -190,11 +176,9 @@
>
<Render of={cell.render()} />
<ArrowUpDown
class="ml-2 h-4 w-4 {apiMetadata.sort.sortBy ===
cell.id &&
class="ml-2 h-4 w-4 {apiMetadata.sort.sortBy === cell.id &&
apiMetadata.sort.order === 'asc' &&
'text-green-500'} {apiMetadata.sort.sortBy ===
cell.id &&
'text-green-500'} {apiMetadata.sort.sortBy === cell.id &&
apiMetadata.sort.order === 'desc' &&
'text-red-500'}"
/>
Expand Down Expand Up @@ -223,18 +207,11 @@
class="text-right font-medium underline"
target="_blank"
>
<Render
of={extractLastSegment(cell.render() || '') ||
'Unknown'}
/>
<Render of={extractLastSegment(cell.render() || '') || 'Unknown'} />
</a>
{:else if cell.id === 'author_avatar'}
<div class="w-[30px]">
<img
src={`${cell.render()}`}
class="rounded-full"
alt=""
/>
<img src={`${cell.render()}`} class="rounded-full" alt="" />
</div>
{:else}
<Render of={cell.render()} />
Expand Down Expand Up @@ -284,8 +261,8 @@
variant="outline"
size="sm"
on:click={onLastPage}
disabled={apiMetadata.pagination.currentPage ===
apiMetadata.pagination.totalPages || isFetching}
disabled={apiMetadata.pagination.currentPage === apiMetadata.pagination.totalPages ||
isFetching}
>
Last page
</Button>
Expand Down
Loading

0 comments on commit 8a1863e

Please sign in to comment.