mirror of
https://github.com/lscambo13/ElegantFin.git
synced 2025-09-18 12:40:16 +00:00
1040 lines
36 KiB
HTML
1040 lines
36 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>ElegantFin Theme for Jellyfin</title>
|
||
<style>
|
||
body {
|
||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||
line-height: 1.6;
|
||
max-width: 1080px;
|
||
margin: 0 auto;
|
||
padding: 20px;
|
||
color: #333;
|
||
}
|
||
|
||
h1 {
|
||
color: #2c3e50;
|
||
border-bottom: 3px solid #3498db;
|
||
padding-bottom: 10px;
|
||
}
|
||
|
||
h2 {
|
||
color: #34495e;
|
||
border-bottom: 2px solid #ecf0f1;
|
||
padding-bottom: 5px;
|
||
}
|
||
|
||
h3 {
|
||
color: #2c3e50;
|
||
}
|
||
|
||
h4 {
|
||
color: #7f8c8d;
|
||
}
|
||
|
||
hr {
|
||
border: none;
|
||
height: 2px;
|
||
background: linear-gradient(to right, #3498db, #e74c3c);
|
||
margin: 30px 0;
|
||
}
|
||
|
||
code {
|
||
background-color: #f8f9fa;
|
||
padding: 2px 4px;
|
||
border-radius: 3px;
|
||
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
||
}
|
||
|
||
pre {
|
||
background-color: #f8f9fa;
|
||
padding: 15px;
|
||
border-radius: 5px;
|
||
overflow-x: auto;
|
||
border-left: 4px solid #3498db;
|
||
}
|
||
|
||
table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
margin: 20px 0;
|
||
}
|
||
|
||
th,
|
||
td {
|
||
padding: 12px;
|
||
text-align: center;
|
||
border: 1px solid #ddd;
|
||
}
|
||
|
||
th {
|
||
background-color: #f2f2f2;
|
||
font-weight: bold;
|
||
}
|
||
|
||
img {
|
||
max-width: 100%;
|
||
height: auto;
|
||
border-radius: 8px;
|
||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.banner img {
|
||
width: 100%;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
details {
|
||
margin: 15px 0;
|
||
border: 1px solid #ddd;
|
||
border-radius: 5px;
|
||
padding: 10px;
|
||
}
|
||
|
||
summary {
|
||
cursor: pointer;
|
||
font-weight: bold;
|
||
padding: 10px;
|
||
background-color: #f8f9fa;
|
||
border-radius: 3px;
|
||
margin: -10px -10px 10px -10px;
|
||
}
|
||
|
||
summary:hover {
|
||
background-color: #e9ecef;
|
||
}
|
||
|
||
ul {
|
||
padding-left: 20px;
|
||
}
|
||
|
||
li {
|
||
margin: 5px 0;
|
||
}
|
||
|
||
a {
|
||
color: #3498db;
|
||
text-decoration: none;
|
||
}
|
||
|
||
a:hover {
|
||
text-decoration: underline;
|
||
}
|
||
|
||
.key-features {
|
||
background-color: #f8f9fa;
|
||
padding: 20px;
|
||
border-radius: 8px;
|
||
border-left: 4px solid #27ae60;
|
||
}
|
||
|
||
.installation-box {
|
||
background-color: #fff3cd;
|
||
border: 1px solid #ffeaa7;
|
||
border-radius: 5px;
|
||
padding: 15px;
|
||
margin: 15px 0;
|
||
}
|
||
|
||
.video-container {
|
||
text-align: center;
|
||
margin: 20px 0;
|
||
}
|
||
|
||
/* Carousel Styles */
|
||
.carousel-container {
|
||
position: relative;
|
||
max-width: 100%;
|
||
margin: 20px 0;
|
||
background: #f8f9fa;
|
||
border-radius: 12px;
|
||
overflow: hidden;
|
||
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.carousel-tabs {
|
||
display: flex;
|
||
background: #fff;
|
||
border-bottom: 2px solid #e9ecef;
|
||
}
|
||
|
||
.carousel-tab {
|
||
flex: 1;
|
||
padding: 15px 20px;
|
||
background: #f8f9fa;
|
||
border: none;
|
||
cursor: pointer;
|
||
font-weight: 600;
|
||
color: #6c757d;
|
||
transition: all 0.3s ease;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.carousel-tab.active {
|
||
background: #3498db;
|
||
color: white;
|
||
}
|
||
|
||
.carousel-tab:hover:not(.active) {
|
||
background: #e9ecef;
|
||
color: #495057;
|
||
}
|
||
|
||
.carousel-content {
|
||
position: relative;
|
||
min-height: 400px;
|
||
max-height: 80vh;
|
||
}
|
||
|
||
.carousel-section {
|
||
display: none;
|
||
padding: 20px;
|
||
}
|
||
|
||
.carousel-section.active {
|
||
display: block;
|
||
}
|
||
|
||
.carousel-wrapper {
|
||
position: relative;
|
||
overflow: hidden;
|
||
border-radius: 8px;
|
||
}
|
||
|
||
.carousel-track {
|
||
display: flex;
|
||
transition: transform 0.5s ease-in-out;
|
||
}
|
||
|
||
.carousel-slide {
|
||
min-width: 100%;
|
||
flex-shrink: 0;
|
||
text-align: center;
|
||
}
|
||
|
||
.carousel-slide img {
|
||
/* width: 30%; */
|
||
max-height: 55vh;
|
||
max-width: 800px;
|
||
/* height: fit-content; */
|
||
border-radius: 8px;
|
||
}
|
||
|
||
.slide-title {
|
||
margin-top: 15px;
|
||
font-weight: bold;
|
||
color: #2c3e50;
|
||
font-size: 18px;
|
||
}
|
||
|
||
.carousel-controls {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
gap: 20px;
|
||
margin-top: 20px;
|
||
padding: 0 20px;
|
||
}
|
||
|
||
.carousel-btn {
|
||
background: #3498db;
|
||
color: white;
|
||
border: none;
|
||
padding: 12px 16px;
|
||
border-radius: 50%;
|
||
cursor: pointer;
|
||
font-size: 16px;
|
||
transition: all 0.3s ease;
|
||
box-shadow: 0 2px 8px rgba(52, 152, 219, 0.3);
|
||
}
|
||
|
||
.carousel-btn:hover {
|
||
background: #2980b9;
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 4px 12px rgba(52, 152, 219, 0.4);
|
||
}
|
||
|
||
.carousel-btn:disabled {
|
||
background: #bdc3c7;
|
||
cursor: not-allowed;
|
||
transform: none;
|
||
box-shadow: none;
|
||
}
|
||
|
||
.carousel-counter {
|
||
background: rgba(52, 152, 219, 0.1);
|
||
padding: 8px 16px;
|
||
border-radius: 20px;
|
||
color: #2c3e50;
|
||
font-weight: 600;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.carousel-indicators {
|
||
display: flex;
|
||
justify-content: center;
|
||
gap: 8px;
|
||
margin-top: 15px;
|
||
padding: 0 20px 20px;
|
||
}
|
||
|
||
.carousel-dot {
|
||
width: 10px;
|
||
height: 10px;
|
||
border-radius: 50%;
|
||
background: #bdc3c7;
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.carousel-dot.active {
|
||
background: #3498db;
|
||
transform: scale(1.2);
|
||
}
|
||
|
||
.carousel-dot:hover {
|
||
background: #7f8c8d;
|
||
}
|
||
|
||
/* Responsive adjustments */
|
||
@media (max-width: 768px) {
|
||
.carousel-tabs {
|
||
flex-direction: column;
|
||
}
|
||
|
||
.carousel-tab {
|
||
text-align: center;
|
||
}
|
||
|
||
.carousel-controls {
|
||
flex-wrap: wrap;
|
||
gap: 15px;
|
||
}
|
||
|
||
.carousel-btn {
|
||
padding: 10px 14px;
|
||
font-size: 14px;
|
||
}
|
||
}
|
||
</style>
|
||
</head>
|
||
|
||
<body>
|
||
<!-- Banner Image -->
|
||
<div class="banner">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Theme/assets/img/banner.png?raw=true"
|
||
alt="ElegantFin Theme for Jellyfin - Banner">
|
||
</div>
|
||
|
||
<!-- <h1>⭐ ElegantFin Theme</h1> -->
|
||
<p>ElegantFin is a Jellyfin theme inspired from Jellyseerr to improve the overall look and experience with various
|
||
fixes
|
||
to the UI/UX. It gives Jellyfin a fresh, modern look, and it aims to work on mobile, desktop, and TV, with just
|
||
one import.</p>
|
||
|
||
<h4><strong>Author:</strong> <a href="https://github.com/lscambo13">lscambo13</a></h4>
|
||
|
||
<hr>
|
||
|
||
<h3>✨ Key Features</h3>
|
||
<div class="key-features">
|
||
<ul>
|
||
<li>modern layouts and color tones</li>
|
||
<li>new and improved animations on most elements</li>
|
||
<li>rounded corners and even spacing everywhere</li>
|
||
<li>stylish borders, hover effects and shadows</li>
|
||
<li>neat layout that puts important stuff up front</li>
|
||
<li>reduced unnecessary clutter</li>
|
||
<li>various fixes to improve the user experience</li>
|
||
<li>same clean design across phone, desktop, and TV</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<hr>
|
||
|
||
<h3>🖼️ Theme Showcase</h3>
|
||
<p>Captured on ElegantFin v25.08.02</p>
|
||
|
||
<div class="carousel-container">
|
||
<div class="carousel-tabs">
|
||
<button class="carousel-tab active" onclick="switchTab(0)">💻 Desktop</button>
|
||
<button class="carousel-tab" onclick="switchTab(1)">📱 Mobile</button>
|
||
<button class="carousel-tab" onclick="switchTab(2)">📺 TV View</button>
|
||
</div>
|
||
|
||
<div class="carousel-content">
|
||
<!-- Desktop Section -->
|
||
<div class="carousel-section active" id="section-0">
|
||
<div class="carousel-wrapper">
|
||
<div class="carousel-track" id="track-0">
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/desktop/21.%20Login%20Page.png?raw=true"
|
||
alt="Login Page Desktop">
|
||
<div class="slide-title">Login Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/desktop/1.%20Homepage.png?raw=true"
|
||
alt="Homepage Desktop">
|
||
<div class="slide-title">Homepage</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/desktop/2.%20Movies%20Library.png?raw=true"
|
||
alt="Movies Library Desktop">
|
||
<div class="slide-title">Movies Library</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/desktop/4.%20Movie%20Page.png?raw=true"
|
||
alt="Movie Page Desktop">
|
||
<div class="slide-title">Movie Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/desktop/12.%20Movie%20Details.png?raw=true"
|
||
alt="Movie Details Desktop">
|
||
<div class="slide-title">Movie Details</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/desktop/11.%20TV%20Show%20Page.png?raw=true"
|
||
alt="TV Show Page Desktop">
|
||
<div class="slide-title">TV Show Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/desktop/18.%20TV%20Episode%20Page.png?raw=true"
|
||
alt="TV Episode Page Desktop">
|
||
<div class="slide-title">TV Episode Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/desktop/16.%20TV%20Show%20Seasons.png?raw=true"
|
||
alt="TV Show Seasons Desktop">
|
||
<div class="slide-title">TV Show Seasons</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/desktop/9.%20Web%20Player.png?raw=true"
|
||
alt="Web Player Desktop">
|
||
<div class="slide-title">Web Player</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/desktop/17.%20Cast%20Page.png?raw=true"
|
||
alt="Cast Page Desktop">
|
||
<div class="slide-title">Cast Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/desktop/14.%20Artist%20Page.png?raw=true"
|
||
alt="Artist Page Desktop">
|
||
<div class="slide-title">Artist Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/desktop/15.%20Music%20Player.png?raw=true"
|
||
alt="Music Player Desktop">
|
||
<div class="slide-title">Music Player</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/desktop/13.%20Book%20Page.png?raw=true"
|
||
alt="Book Page Desktop">
|
||
<div class="slide-title">Book Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/desktop/3.%20Sidebar.png?raw=true"
|
||
alt="Sidebar Desktop">
|
||
<div class="slide-title">Sidebar</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/desktop/5.%20Extra%20Dialog.png?raw=true"
|
||
alt="Extra Dialog Desktop">
|
||
<div class="slide-title">Extra Dialog</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/desktop/6.%20Settings%20Page.png?raw=true"
|
||
alt="Settings Page Desktop">
|
||
<div class="slide-title">Settings Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/desktop/19.%20Live%20TV%20Page.png?raw=true"
|
||
alt="Live TV Page Desktop">
|
||
<div class="slide-title">Live TV Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/desktop/20.%20Live%20TV%20Guide.png?raw=true"
|
||
alt="Live TV Guide Desktop">
|
||
<div class="slide-title">Live TV Guide</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="carousel-controls">
|
||
<button class="carousel-btn" onclick="prevSlide(0)" id="prev-0">❮</button>
|
||
<div class="carousel-counter" id="counter-0">1 / 18</div>
|
||
<button class="carousel-btn" onclick="nextSlide(0)" id="next-0">❯</button>
|
||
</div>
|
||
<div class="carousel-indicators" id="indicators-0"></div>
|
||
</div>
|
||
|
||
<!-- Mobile Section -->
|
||
<div class="carousel-section" id="section-1">
|
||
<div class="carousel-wrapper">
|
||
<div class="carousel-track" id="track-1">
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/mobile/21.%20Login%20Page.png?raw=true"
|
||
alt="Login Page Mobile">
|
||
<div class="slide-title">Login Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/mobile/1.%20Homepage.png?raw=true"
|
||
alt="Homepage Mobile">
|
||
<div class="slide-title">Homepage</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/mobile/2.%20Movies%20Library.png?raw=true"
|
||
alt="Movies Library Mobile">
|
||
<div class="slide-title">Movies Library</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/mobile/4.%20Movie%20Page.png?raw=true"
|
||
alt="Movie Page Mobile">
|
||
<div class="slide-title">Movie Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/mobile/12.%20Movie%20Details.png?raw=true"
|
||
alt="Movie Details Mobile">
|
||
<div class="slide-title">Movie Details</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/mobile/11.%20TV%20Show%20Page.png?raw=true"
|
||
alt="TV Show Page Mobile">
|
||
<div class="slide-title">TV Show Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/mobile/18.%20TV%20Episode%20Page.png?raw=true"
|
||
alt="TV Episode Page Mobile">
|
||
<div class="slide-title">TV Episode Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/mobile/16.%20TV%20Show%20Seasons.png?raw=true"
|
||
alt="TV Show Seasons Mobile">
|
||
<div class="slide-title">TV Show Seasons</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/mobile/9.%20Web%20Player.png?raw=true"
|
||
alt="Web Player Mobile">
|
||
<div class="slide-title">Web Player</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/mobile/17.%20Cast%20Page.png?raw=true"
|
||
alt="Cast Page Mobile">
|
||
<div class="slide-title">Cast Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/mobile/14.%20Artist%20Page.png?raw=true"
|
||
alt="Artist Page Mobile">
|
||
<div class="slide-title">Artist Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/mobile/15.%20Music%20Player.png?raw=true"
|
||
alt="Music Player Mobile">
|
||
<div class="slide-title">Music Player</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/mobile/13.%20Book%20Page.png?raw=true"
|
||
alt="Book Page Mobile">
|
||
<div class="slide-title">Book Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/mobile/3.%20Sidebar.png?raw=true"
|
||
alt="Sidebar Mobile">
|
||
<div class="slide-title">Sidebar</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/mobile/5.%20Extra%20Dialog.png?raw=true"
|
||
alt="Extra Dialog Mobile">
|
||
<div class="slide-title">Extra Dialog</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/mobile/6.%20Settings%20Page.png?raw=true"
|
||
alt="Settings Page Mobile">
|
||
<div class="slide-title">Settings Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/mobile/19.%20Live%20TV%20Page.png?raw=true"
|
||
alt="Live TV Page Mobile">
|
||
<div class="slide-title">Live TV Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/mobile/20.%20Live%20TV%20Guide.png?raw=true"
|
||
alt="Live TV Guide Mobile">
|
||
<div class="slide-title">Live TV Guide</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="carousel-controls">
|
||
<button class="carousel-btn" onclick="prevSlide(1)" id="prev-1">❮</button>
|
||
<div class="carousel-counter" id="counter-1">1 / 18</div>
|
||
<button class="carousel-btn" onclick="nextSlide(1)" id="next-1">❯</button>
|
||
</div>
|
||
<div class="carousel-indicators" id="indicators-1"></div>
|
||
</div>
|
||
|
||
<!-- TV Section -->
|
||
<div class="carousel-section" id="section-2">
|
||
<div class="carousel-wrapper">
|
||
<div class="carousel-track" id="track-2">
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/tv/21.%20Login%20Page.png?raw=true"
|
||
alt="Login Page TV">
|
||
<div class="slide-title">Login Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/tv/1.%20Homepage.png?raw=true"
|
||
alt="Homepage TV">
|
||
<div class="slide-title">Homepage</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/tv/2.%20Movies%20Library.png?raw=true"
|
||
alt="Movies Library TV">
|
||
<div class="slide-title">Movies Library</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/tv/4.%20Movie%20Page.png?raw=true"
|
||
alt="Movie Page TV">
|
||
<div class="slide-title">Movie Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/tv/5.%20Extra%20Dialog.png?raw=true"
|
||
alt="Extra Dialog TV">
|
||
<div class="slide-title">Extra Dialog</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/tv/6.%20Settings%20Page.png?raw=true"
|
||
alt="Settings Page TV">
|
||
<div class="slide-title">Settings Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/tv/9.%20Web%20Player.png?raw=true"
|
||
alt="Web Player TV">
|
||
<div class="slide-title">Web Player</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/tv/11.%20TV%20Show%20Page.png?raw=true"
|
||
alt="TV Show Page TV">
|
||
<div class="slide-title">TV Show Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/tv/12.%20Movie%20Details.png?raw=true"
|
||
alt="Movie Details TV">
|
||
<div class="slide-title">Movie Details</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/tv/13.%20Book%20Page.png?raw=true"
|
||
alt="Book Page TV">
|
||
<div class="slide-title">Book Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/tv/14.%20Artist%20Page.png?raw=true"
|
||
alt="Artist Page TV">
|
||
<div class="slide-title">Artist Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/tv/15.%20Music%20Player.png?raw=true"
|
||
alt="Music Player TV">
|
||
<div class="slide-title">Music Player</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/tv/16.%20TV%20Show%20Seasons.png?raw=true"
|
||
alt="TV Show Seasons TV">
|
||
<div class="slide-title">TV Show Seasons</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/tv/17.%20Cast%20Page.png?raw=true"
|
||
alt="Cast Page TV">
|
||
<div class="slide-title">Cast Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/tv/18.%20TV%20Episode%20Page.png?raw=true"
|
||
alt="TV Episode Page TV">
|
||
<div class="slide-title">TV Episode Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/tv/19.%20Live%20TV%20Page.png?raw=true"
|
||
alt="Live TV Page TV">
|
||
<div class="slide-title">Live TV Page</div>
|
||
</div>
|
||
<div class="carousel-slide">
|
||
<img src="https://github.com/lscambo13/ElegantFin/blob/main/Previews/previews-v25.08.02/raw/tv/20.%20Live%20TV%20Guide.png?raw=true"
|
||
alt="Live TV Guide TV">
|
||
<div class="slide-title">Live TV Guide</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="carousel-controls">
|
||
<button class="carousel-btn" onclick="prevSlide(2)" id="prev-2">❮</button>
|
||
<div class="carousel-counter" id="counter-2">1 / 18</div>
|
||
<button class="carousel-btn" onclick="nextSlide(2)" id="next-2">❯</button>
|
||
</div>
|
||
<div class="carousel-indicators" id="indicators-2"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="video-container">
|
||
<video controls width="100%" style="max-width: 800px;">
|
||
<source
|
||
src="https://github.com/lscambo13/ElegantFin/raw/refs/heads/main/Previews/previews-v25.08.02/raw/mobile/ElegantFin%20Theme%20Video%20Demo.mp4?raw=true"
|
||
type="video/mp4">
|
||
Your browser does not support the video tag.
|
||
</video>
|
||
</div>
|
||
|
||
<hr>
|
||
|
||
<h3>👇 How to install/setup this theme?</h3>
|
||
|
||
<div class="installation-box">
|
||
<p><strong>Paste the following in Custom CSS code box:</strong></p>
|
||
<pre><code>@import url("https://cdn.jsdelivr.net/gh/lscambo13/ElegantFin@main/Theme/ElegantFin-jellyfin-theme-build-latest-minified.css");</code></pre>
|
||
</div>
|
||
|
||
<details>
|
||
<summary><i>Detailed steps for server-side implementation</i></summary>
|
||
<ol>
|
||
<li>Open Dashboard from Administration tab in Settings.</li>
|
||
<li>Select General tab from the side bar.</li>
|
||
<li>Scroll down to find Custom CSS code box under Branding section.</li>
|
||
<li>Paste the custom css in Custom CSS code box.</li>
|
||
<li>Click save</li>
|
||
</ol>
|
||
</details>
|
||
|
||
<details>
|
||
<summary><i>Detailed steps for client-side implementation</i></summary>
|
||
<ol>
|
||
<li>Open Display tab in Settings.</li>
|
||
<li>Scroll down to find Custom CSS code box.</li>
|
||
<li>Paste the custom css in Custom CSS code box.</li>
|
||
<li>Click save.</li>
|
||
</ol>
|
||
</details>
|
||
|
||
<hr>
|
||
<!--
|
||
<h3>🧩 How to customise this theme?</h3>
|
||
|
||
<details>
|
||
<summary><i>1. Custom media covers for user media libraries</i></summary>
|
||
<ul>
|
||
<li><a
|
||
href="https://github.com/lscambo13/ElegantFin/blob/main/custom-media-covers.md#%EF%B8%8F-presets-modify-these-styles-according-to-your-own-liking">Previews</a>
|
||
</li>
|
||
<li>Read more about this experimental add-on <a
|
||
href="https://github.com/lscambo13/ElegantFin/blob/main/custom-media-covers.md">here</a></li>
|
||
</ul>
|
||
</details>
|
||
|
||
<details>
|
||
<summary><i>2. Custom background image for the login page</i></summary>
|
||
<ul>
|
||
<li><a
|
||
href="https://user-images.githubusercontent.com/16425113/129554147-6ac7ba51-43e7-4c8e-ba77-e646a3ef6b12.jpg">Preview</a>
|
||
</li>
|
||
<li>To enable the background wallpaper on the login screen, first tick the 'Enable the splash screen' option
|
||
in your Jellyfin Dashboard below the Custom CSS Box.</li>
|
||
<li>Second, copy and paste the following code at the end in Custom CSS box but don't save yet.
|
||
<pre><code>:root{
|
||
--loginPageBgUrl: url("<YOUR-JELLYFIN-SERVER-ADDRESS>/Branding/Splashscreen?format=webp&foregroundLayer=1&quality=33&width=3840&height=2160&blur=2");
|
||
}</code></pre>
|
||
</li>
|
||
<li>Third, replace <code><YOUR-JELLYFIN-SERVER-ADDRESS></code> with your Jellyfin server address, for
|
||
example, <code>http://192.168.0.1:8097</code>.</li>
|
||
<li>Don't forget the correct http or https in your domain.</li>
|
||
<li>You can also modify the parameters, for example blur size or the resolution, according to your liking.
|
||
</li>
|
||
<li>Once done, save and refresh your apps and webpages.</li>
|
||
</ul>
|
||
</details>
|
||
|
||
<details>
|
||
<summary><i>3. Enable extra overlay buttons on cards on desktop</i></summary>
|
||
<ul>
|
||
<li>To enable 'Mark Played' and 'Add to Favorites' buttons that show up at the bottom right corner of cards
|
||
while hovering, copy and paste the following code at the end in Custom CSS box, click save and finally
|
||
refresh your app/webpage.
|
||
<pre><code>:root{
|
||
--extraCardButtonsVisibility: block;
|
||
}</code></pre>
|
||
</li>
|
||
<li>To hide them again, simply remove this code block or replace <code>block</code> with <code>none</code>.
|
||
</li>
|
||
</ul>
|
||
</details>
|
||
|
||
<details>
|
||
<summary><i>4. Place the overlay play button at the center of cards on desktop</i></summary>
|
||
<ul>
|
||
<li>To bring the mini play button to the center of cards, copy and paste the following code at the end in
|
||
Custom CSS box, click save and finally refresh your app/webpage.
|
||
<pre><code>:root{
|
||
--overlayPlayButtonPosition: 50%;
|
||
}</code></pre>
|
||
</li>
|
||
<li>To undo this change, simply remove this code block or replace <code>50%</code> with <code>2.8em</code>.
|
||
</li>
|
||
</ul>
|
||
</details>
|
||
|
||
<details>
|
||
<summary><i>5. Disable the card hover effect on desktop</i></summary>
|
||
<ul>
|
||
<li>To disable the reflection on cards that shows when hovering over them on desktop, copy and paste the
|
||
following code at the end in Custom CSS box, click save and finally refresh your app/webpage.
|
||
<pre><code>:root{
|
||
--cardHoverEffect: none;
|
||
}</code></pre>
|
||
</li>
|
||
<li>To undo this change, simply remove this code block or replace <code>none</code> with <code>""</code>.
|
||
</li>
|
||
</ul>
|
||
</details>
|
||
|
||
<details>
|
||
<summary><i>6. Enable labels below library cards</i></summary>
|
||
<ul>
|
||
<li>To enable text labels under the media library cards, copy and paste the following code at the end in
|
||
Custom CSS box, click save and finally refresh your app/webpage.
|
||
<pre><code>:root{
|
||
--libraryLabelVisibility: block;
|
||
}</code></pre>
|
||
</li>
|
||
<li>To undo this change, simply remove this code block or replace <code>block</code> with <code>none</code>.
|
||
</li>
|
||
</ul>
|
||
</details>
|
||
|
||
<details>
|
||
<summary><i>7. Enable support for the Media Bar plugin</i></summary>
|
||
<ul>
|
||
<li>ElegantFin does not support any plugins by default, so to to add external support for <a
|
||
href="https://github.com/IAmParadox27/jellyfin-plugin-media-bar/">this plugin</a>, copy and paste
|
||
the following code at the end in Custom CSS box, click save and finally refresh your app/webpage.
|
||
<pre><code>@import url("https://cdn.jsdelivr.net/gh/lscambo13/ElegantFin@main/Theme/assets/add-ons/media-bar-plugin-support-latest-min.css");</code></pre>
|
||
</li>
|
||
<li>To undo this change, simply remove this code block.</li>
|
||
</ul>
|
||
</details>
|
||
|
||
<hr> -->
|
||
|
||
<h3>🆗 Tested on</h3>
|
||
<ul>
|
||
<li>Jellyfin Server v10.10.6</li>
|
||
<li>Jellyfin Android App v2.6.2</li>
|
||
</ul>
|
||
|
||
<hr>
|
||
<!--
|
||
<h3>🛠️ Troubleshooting</h3>
|
||
|
||
<details>
|
||
<summary>1️⃣ - <i>How do I check if I am using the latest version of ElegantFin?</i></summary>
|
||
<ul>
|
||
<li>To make sure that you are using the latest version of ElegantFin, check the version number at the bottom
|
||
in the Dashboard screen.</li>
|
||
<li>It should be something like ElegantFin v25.07.XX</li>
|
||
</ul>
|
||
</details>
|
||
|
||
<details>
|
||
<summary>2️⃣ - <i>I see that a newer version is available, but I have not received it yet. Why?</i></summary>
|
||
<ul>
|
||
<li>If Dashboard footer shows an old version, it means that your app is still using an old cache.</li>
|
||
<li>Once that cache is updated, the new version will be loaded.</li>
|
||
<li>To get the latest version, you will need to clear cache. There are multiple ways to do it.</li>
|
||
<li>On web version, force a hard refresh of the page using CTRL + F5.</li>
|
||
<li>On apps, try signing out and back in again. OR in case of Jellyfin Media Player on windows, you might
|
||
need to delete the cache folder. That should definitely pull the latest version.</li>
|
||
</ul>
|
||
</details>
|
||
|
||
<details>
|
||
<summary>3️⃣ - <i>Why do I notice visual bugs and inconsistencies on Jellyfin Media Player?</i></summary>
|
||
<ul>
|
||
<li>As of version 1.12.0, JMP is based on Qt 5.x which uses a very outdated web engine, so it does not
|
||
support many new CSS features. Once a new version based on Qt 6.x is released, most issues should
|
||
automatically be resolved. Until then, JMP is unsupported and I recommend using the web app instead.
|
||
</li>
|
||
</ul>
|
||
</details>
|
||
|
||
<details>
|
||
<summary>4️⃣ - <i>Does it work on the AndroidTV version of the Jellyfin app?</i></summary>
|
||
<ul>
|
||
<li>As of version 0.18.11, the official Jellyfin app on the AndroidTVs does not support css themes, but the
|
||
Android mobile phone app supports them. The WebOS version of the app seems to be based on the mobile
|
||
phone version, so it supports the theme just fine.</li>
|
||
</ul>
|
||
</details>
|
||
|
||
<details>
|
||
<summary>5️⃣ - <i>All the icons on my LG TV seem to be broken. How to fix them?</i></summary>
|
||
<ul>
|
||
<li>It seems that modern Material Icons which this theme uses are <a
|
||
href="https://github.com/lscambo13/ElegantFin/issues/39">not compatible on some WebOS TVs</a>. There
|
||
is a <a
|
||
href="https://www.reddit.com/r/youtubetv/comments/e27go3/chinese_symbols_instead_of_icons_on_lg_tv/">huge
|
||
similar thread</a> about this.</li>
|
||
<li>This bug can be fixed by using the older icons, so I have implemented the following workaround to bring
|
||
back older, supported icons.</li>
|
||
<li>Simply add the following code at the end in Custom CSS box and save, then refresh your apps and
|
||
webpages:
|
||
<pre><code>:root{
|
||
--iconPack: 'Material Icons';
|
||
}</code></pre>
|
||
</li>
|
||
</ul>
|
||
</details>
|
||
|
||
<details>
|
||
<summary>6️⃣ - <i>How do I report bugs/issues?</i></summary>
|
||
<ul>
|
||
<li>First check <a href="https://github.com/lscambo13/ElegantFin/issues?q=">here</a> whether a similar issue
|
||
has been reported already. If it exists, upvote and comment there to let me know.</li>
|
||
<li>Alternatively, create a new issue <a
|
||
href="https://github.com/lscambo13/ElegantFin/issues/new/choose">here</a>.</li>
|
||
</ul>
|
||
</details>
|
||
|
||
<details>
|
||
<summary>7️⃣ - <i>When can I expect another update?</i></summary>
|
||
<ul>
|
||
<li>🤷</li>
|
||
</ul>
|
||
</details>
|
||
|
||
<hr> -->
|
||
|
||
<h3>📌 Contributing</h3>
|
||
<p>Please read the <a href="./CONTRIBUTING.md">Contributor Guidelines</a> before opening pull requests.</p>
|
||
|
||
<h3>🙏 Feedback Appreciated</h3>
|
||
<p>Please use the right template when creating an <a
|
||
href="https://github.com/lscambo13/ElegantFin/issues/new/choose">issue</a> to <a
|
||
href="https://github.com/lscambo13/ElegantFin/issues/new?template=bug_report.md">report bugs</a> or <a
|
||
href="https://github.com/lscambo13/ElegantFin/issues/new?template=feature_request.md">provide
|
||
suggestions</a>.</p>
|
||
|
||
<script>
|
||
const carousels = [
|
||
{ currentSlide: 0, totalSlides: 16 },
|
||
{ currentSlide: 0, totalSlides: 8 }
|
||
];
|
||
|
||
function initializeCarousels() {
|
||
// Initialize indicators for both carousels
|
||
for (let carouselIndex = 0; carouselIndex < carousels.length; carouselIndex++) {
|
||
const indicatorsContainer = document.getElementById(`indicators-${carouselIndex}`);
|
||
indicatorsContainer.innerHTML = '';
|
||
|
||
for (let i = 0; i < carousels[carouselIndex].totalSlides; i++) {
|
||
const dot = document.createElement('div');
|
||
dot.className = `carousel-dot ${i === 0 ? 'active' : ''}`;
|
||
dot.onclick = () => goToSlide(carouselIndex, i);
|
||
indicatorsContainer.appendChild(dot);
|
||
}
|
||
}
|
||
updateCarousel(0);
|
||
updateCarousel(1);
|
||
}
|
||
|
||
function switchTab(tabIndex) {
|
||
// Update tab buttons
|
||
const tabs = document.querySelectorAll('.carousel-tab');
|
||
tabs.forEach((tab, index) => {
|
||
tab.classList.toggle('active', index === tabIndex);
|
||
});
|
||
|
||
// Update sections
|
||
const sections = document.querySelectorAll('.carousel-section');
|
||
sections.forEach((section, index) => {
|
||
section.classList.toggle('active', index === tabIndex);
|
||
});
|
||
}
|
||
|
||
function updateCarousel(carouselIndex) {
|
||
const track = document.getElementById(`track-${carouselIndex}`);
|
||
const counter = document.getElementById(`counter-${carouselIndex}`);
|
||
const prevBtn = document.getElementById(`prev-${carouselIndex}`);
|
||
const nextBtn = document.getElementById(`next-${carouselIndex}`);
|
||
const indicators = document.querySelectorAll(`#indicators-${carouselIndex} .carousel-dot`);
|
||
|
||
const currentSlide = carousels[carouselIndex].currentSlide;
|
||
const totalSlides = carousels[carouselIndex].totalSlides;
|
||
|
||
// Update track position
|
||
track.style.transform = `translateX(-${currentSlide * 100}%)`;
|
||
|
||
// Update counter
|
||
counter.textContent = `${currentSlide + 1} / ${totalSlides}`;
|
||
|
||
// Update button states
|
||
prevBtn.disabled = currentSlide === 0;
|
||
nextBtn.disabled = currentSlide === totalSlides - 1;
|
||
|
||
// Update indicators
|
||
indicators.forEach((dot, index) => {
|
||
dot.classList.toggle('active', index === currentSlide);
|
||
});
|
||
}
|
||
|
||
function nextSlide(carouselIndex) {
|
||
if (carousels[carouselIndex].currentSlide < carousels[carouselIndex].totalSlides - 1) {
|
||
carousels[carouselIndex].currentSlide++;
|
||
updateCarousel(carouselIndex);
|
||
}
|
||
}
|
||
|
||
function prevSlide(carouselIndex) {
|
||
if (carousels[carouselIndex].currentSlide > 0) {
|
||
carousels[carouselIndex].currentSlide--;
|
||
updateCarousel(carouselIndex);
|
||
}
|
||
}
|
||
|
||
function goToSlide(carouselIndex, slideIndex) {
|
||
carousels[carouselIndex].currentSlide = slideIndex;
|
||
updateCarousel(carouselIndex);
|
||
}
|
||
|
||
// Keyboard navigation
|
||
document.addEventListener('keydown', function (e) {
|
||
const activeSection = document.querySelector('.carousel-section.active');
|
||
const carouselIndex = activeSection ? parseInt(activeSection.id.split('-')[1]) : 0;
|
||
|
||
if (e.key === 'ArrowLeft') {
|
||
e.preventDefault();
|
||
prevSlide(carouselIndex);
|
||
} else if (e.key === 'ArrowRight') {
|
||
e.preventDefault();
|
||
nextSlide(carouselIndex);
|
||
}
|
||
});
|
||
|
||
// Auto-advance carousel (optional - uncomment to enable)
|
||
/*
|
||
setInterval(() => {
|
||
const activeSection = document.querySelector('.carousel-section.active');
|
||
const carouselIndex = activeSection ? parseInt(activeSection.id.split('-')[1]) : 0;
|
||
|
||
if (carousels[carouselIndex].currentSlide < carousels[carouselIndex].totalSlides - 1) {
|
||
nextSlide(carouselIndex);
|
||
} else {
|
||
carousels[carouselIndex].currentSlide = 0;
|
||
updateCarousel(carouselIndex);
|
||
}
|
||
}, 5000);
|
||
*/
|
||
|
||
// Initialize when page loads
|
||
document.addEventListener('DOMContentLoaded', initializeCarousels);
|
||
</script>
|
||
|
||
</body>
|
||
|
||
</html> |