gradio_creditspanel / src /frontend /shared /ScrollEffect.svelte
elismasilva's picture
Upload folder using huggingface_hub
919197a verified
<script lang="ts">
/**
* Props for the ScrollEffect component.
* @typedef {Object} Props
* @property {Array<{title: string, name: string}>} credits - List of credits with title and name.
* @property {number} speed - Animation speed in seconds.
* @property {number} base_font_size - Base font size in rem (default: 1.5).
* @property {string | null} background_color - Background color (default: black).
* @property {string | null} title_color - Title text color (default: white).
* @property {string | null} scroll_section_title_color - Section title color.
* @property {string | null} name_color - Name text color (default: white).
* @property {string | null} intro_title - Optional intro title.
* @property {string | null} intro_subtitle - Optional intro subtitle.
* @property {"stacked" | "two-column"} layout_style - Layout for credits.
* @property {boolean} title_uppercase - Transform title to uppercase.
* @property {boolean} name_uppercase - Transform name to uppercase.
* @property {boolean} section_title_uppercase - Transform section title to uppercase.
* @property {boolean} swap_font_sizes_on_two_column - Swap title/name font sizes.
* @property {{path: string | null, url: string | null, ...} | null} scroll_logo_path - Logo to display inside the scroll.
* @property {string} scroll_logo_height - Height of the scrolling logo.
*
*/
export let credits: Props['credits'];
export let speed: number;
export let base_font_size: number = 1.5;
export let background_color: string | null = null;
export let title_color: string | null = null;
export let scroll_section_title_color: string | null = null;
export let name_color: string | null = null;
export let intro_title: string | null = null;
export let intro_subtitle: string | null = null;
export let layout_style: "stacked" | "two-column" = "stacked";
export let title_uppercase: boolean = false;
export let name_uppercase: boolean = false;
export let section_title_uppercase: boolean = true;
export let swap_font_sizes_on_two_column: boolean = false;
export let scroll_logo_path: { url: string | null } | null = null;
export let scroll_logo_height: string = "120px";
// Flag to trigger animation reset
let reset = false;
// Combine intro and credits for display
$: display_items = (() => {
const items = [];
if (intro_title || intro_subtitle) {
items.push({
title: intro_title || '',
name: intro_subtitle || '',
is_intro: true
});
}
return [...items, ...credits.map(c => ({ ...c, is_intro: false }))];
})();
// Reactive styles for title and name
$: title_style = (is_intro: boolean) => `color: ${title_color || 'white'}; font-size: ${is_intro ? base_font_size * 1.5 : base_font_size}rem;`;
$: name_style = (is_intro: boolean) => `color: ${name_color || 'white'}; font-size: ${is_intro ? base_font_size * 0.9 : base_font_size * 0.8}rem;`;
$: section_title_style = `color: ${scroll_section_title_color || title_color || 'white'}; font-size: ${base_font_size * 1.2}rem;`;
// Reset animation on prop changes
function resetAnimation() {
reset = true;
setTimeout(() => (reset = false), 0);
}
// Trigger reset on prop changes
$: credits, speed, resetAnimation();
</script>
<div class="wrapper" style:--animation-duration="{speed}s" style:background={background_color || 'black'}>
{#if !reset}
<div class="credits-container">
{#if scroll_logo_path?.url}
<div class="scroll-logo-container" style:height={scroll_logo_height}>
<img src={scroll_logo_path.url} alt="Scrolling Logo" style:height={scroll_logo_height} />
</div>
{/if}
{#each display_items as item}
<!-- Render Section Title -->
{#if item.section_title}
<div class="section-title" style={section_title_style} class:uppercase={section_title_uppercase}>
{item.section_title}
</div>
<!-- Render Credit or Intro -->
{:else}
{#if layout_style === 'two-column' && !item.is_intro}
<!-- Two-Column Layout -->
<div class="credit-two-column">
<div class="title" style={swap_font_sizes_on_two_column ? name_style(false) : title_style(false)} class:uppercase={title_uppercase}>
{item.title}
</div>
<div class="name" style={swap_font_sizes_on_two_column ? title_style(false) : name_style(false)} class:uppercase={name_uppercase}>
{item.name}
</div>
</div>
{:else}
<!-- Stacked Layout (Default and for Intro) -->
<div class="credit" class:intro-block={item.is_intro}>
<h2 style={title_style(item.is_intro)} class:uppercase={title_uppercase && !item.is_intro}>{item.title}</h2>
{#if item.name}
<p style={name_style(item.is_intro)} class:uppercase={name_uppercase && !item.is_intro}>{item.name}</p>
{/if}
</div>
{/if}
{/if}
{/each}
</div>
{/if}
</div>
<style>
/* Main container for the scrolling effect */
.wrapper {
width: 100%;
height: 100%;
overflow: hidden;
position: relative;
font-family: sans-serif;
}
.scroll-logo-container {
text-align: center;
margin-bottom: 2rem; /* Space between logo and intro text */
}
.scroll-logo-container img {
display: block;
margin-left: auto;
margin-right: auto;
max-width: 80%;
object-fit: contain;
}
/* Animated container holding all credit items */
.credits-container {
position: absolute;
bottom: 0;
transform: translateY(100%);
width: 100%;
text-align: center;
animation: scroll var(--animation-duration) linear infinite;
padding: 0 2rem; /* Adds horizontal padding */
box-sizing: border-box;
}
/* Section Title Style */
.section-title {
margin-top: 4rem;
margin-bottom: 2.5rem;
font-weight: bold;
}
/* Stacked Layout */
.credit.intro-block {
margin-bottom: 5rem;
}
.credit {
margin-bottom: 2rem;
}
.credit h2, .credit p {
margin: 0.5rem 0;
font-family: sans-serif;
}
/* Two-Column Layout */
.credit-two-column {
display: flex;
justify-content: space-between;
align-items: baseline;
text-align: left;
margin: 0.8rem auto;
max-width: 80%; /* Limits width for better readability */
gap: 1rem;
}
.credit-two-column .title {
flex: 1;
text-align: right;
padding-right: 1rem;
}
.credit-two-column .name {
flex: 1;
text-align: left;
padding-left: 1rem;
}
/* Utility class for uppercase */
.uppercase {
text-transform: uppercase;
}
/* Scroll animation keyframes */
@keyframes scroll {
0% { transform: translateY(100%); }
100% { transform: translateY(-100%); }
}
</style>