Update CONTRIBUTING.md for clarity and consistency in theme development guidelines

This commit is contained in:
CodeDevMLH
2026-02-17 14:10:19 +01:00
parent 81facbdb00
commit 1ddaab325e

View File

@@ -45,7 +45,7 @@ The orchestrator file `seasonals.js` manages theme loading at runtime. It reads
## Standard Theme File Structure
Here is the complete file layout for a theme called `mytheme`:
Here is a complete file layout for a theme called `mytheme`:
```
Jellyfin.Plugin.Seasonals/
@@ -65,7 +65,7 @@ Jellyfin.Plugin.Seasonals/
Every theme JS file follows a **consistent skeleton**. Use this as your starting template:
```javascript
// ── 1. Read Configuration ──────────────────────────────────────────
// 1. Read Configuration
const config = window.SeasonalsPluginConfig?.MyTheme || {};
const enabled = config.EnableMyTheme !== undefined ? config.EnableMyTheme : true;
@@ -74,8 +74,8 @@ const elementCount = config.ElementCount || 25;
let msgPrinted = false;
// ── 2. Toggle Function ────────────────────────────────────────────
// Hides the effect when a video player, trailer, dashboard, or user menu is active.
// 2. Toggle Function
// Hides the effect when a video player, trailer (in full width mode), dashboard, or user menu is active.
function toggleMyTheme() {
const container = document.querySelector('.mytheme-container');
if (!container) return;
@@ -100,7 +100,7 @@ function toggleMyTheme() {
}
}
// ── 3. MutationObserver ────────────────────────────────────────────
// 3. MutationObserver
// Watches the DOM for changes so the effect can auto-hide/show.
const observer = new MutationObserver(toggleMyTheme);
observer.observe(document.body, {
@@ -109,7 +109,7 @@ observer.observe(document.body, {
attributes: true
});
// ── 4. Element Creation ────────────────────────────────────────────
// 4. Element Creation
// Create and append your animated elements to the container.
function createElements() {
const container = document.querySelector('.mytheme-container') || document.createElement('div');
@@ -140,7 +140,7 @@ function createElements() {
}
}
// ── 5. Initialization ─────────────────────────────────────────────
// 5. Initialization
function initializeMyTheme() {
if (!enabled) return;
createElements();
@@ -153,9 +153,9 @@ initializeMyTheme();
### Key Rules
- **Always** read config from `window.SeasonalsPluginConfig?.{ThemeName}`.
- **Always** implement the toggle function with the same selectors (`.videoPlayerContainer`, `.youtubePlayerContainer`, `.dashboardDocument`, `#app-user-menu`).
- **Always** implement the toggle function with the same selectors (`.videoPlayerContainer`, `.youtubePlayerContainer`, `.dashboardDocument`, `#app-user-menu`, just use the above template).
- **Always** use `aria-hidden="true"` on the container for accessibility.
- **Always** call your `initialize` function at the end of the file.
- Call your `initialize` function at the end of the file.
- For **canvas-based** themes (like `snowfall.js`), use a `<canvas>` element with `requestAnimationFrame` instead of CSS animations. Make sure to clean up with `cancelAnimationFrame` when hidden.
---
@@ -165,7 +165,7 @@ initializeMyTheme();
Every theme CSS file follows this structure:
```css
/* ── Container ──────────────────────────────────────────────────── */
/* Container */
/* Full-screen overlay, transparent, non-interactive */
.mytheme-container {
display: block;
@@ -179,7 +179,7 @@ Every theme CSS file follows this structure:
z-index: 10;
}
/* ── Animated Element ───────────────────────────────────────────── */
/* Animated Element */
.mytheme-element {
position: fixed;
z-index: 15;
@@ -193,7 +193,7 @@ Every theme CSS file follows this structure:
animation-iteration-count: infinite, infinite;
}
/* ── Keyframes ──────────────────────────────────────────────────── */
/* Keyframes */
@keyframes mytheme-fall {
0% { top: -10%; }
100% { top: 100%; }
@@ -204,7 +204,7 @@ Every theme CSS file follows this structure:
50% { transform: translateX(80px); }
}
/* ── Staggered Delays for Base Elements ─────────────────────────── */
/* Staggered Delays for Base Elements */
/* Spread the initial 12 elements across the screen */
.mytheme-element:nth-of-type(1) { left: 10%; animation-delay: 1s, 1s; }
.mytheme-element:nth-of-type(2) { left: 20%; animation-delay: 6s, 0.5s; }
@@ -214,9 +214,9 @@ Every theme CSS file follows this structure:
### Key Rules
- **Container** must be `position: fixed`, full-screen, with `pointer-events: none` and `z-index: 10`.
- **Elements** should use `position: fixed` with `z-index: 15`.
- Use **two animations** (primary movement + secondary effect) for natural-looking motion.
- **Container** must be `position: fixed`, full-screen, with `pointer-events: none` and at least `z-index: 10`.
- **Elements** should use `position: fixed` with at least `z-index: 15`.
- Use **animations** (eg. primary movement + secondary effect for natural-looking motion).
- Include **`nth-of-type` rules** for the initial set of base elements to stagger them.
- Include **webkit prefixes** (`-webkit-animation-*`, `@-webkit-keyframes`) for broader compatibility (see existing themes for examples).
@@ -224,7 +224,7 @@ Every theme CSS file follows this structure:
## Image Assets (Optional)
If your theme uses image sprites (e.g., leaves, ghosts, eggs):
If your theme uses images (e.g., leaves, ghosts, eggs):
1. Create a folder: `Jellyfin.Plugin.Seasonals/Web/{themeName}_images/`
2. Place your assets inside (PNG recommended, keep files small)
@@ -232,11 +232,6 @@ If your theme uses image sprites (e.g., leaves, ghosts, eggs):
```javascript
img.src = '../Seasonals/Resources/mytheme_images/sprite1.png';
```
4. For local testing, you can reference them directly:
```javascript
img.src = './mytheme_images/sprite1.png';
```
---
## Registering Your Theme
@@ -264,7 +259,7 @@ const ThemeConfigs = {
> [!NOTE]
> The backend registration is handled by the plugin maintainers. You do **not** need to modify C# files for your theme submission. Just focus on the JS/CSS/images.
>
> However, if you'd like to include full backend integration, add your theme to the enum/configuration in `Configuration/PluginConfiguration.cs`.
> However, if you'd like to include full backend integration, add your theme to the enum/configuration in `Configuration/PluginConfiguration.cs` and the selectors in `configPage.html`.
---
@@ -275,19 +270,18 @@ You can test your theme without a Jellyfin server by using the included test sit
### Steps
1. Navigate to the `Jellyfin.Plugin.Seasonals/Web/` directory
2. Open `test-site-new.html` in your browser (just double-click the file)
2. Open `test-site.html` in your browser (just double-click the file) or vscode or what ever you use...
3. Use the **theme selector dropdown** to pick an existing theme or select **"Custom (Local Files)"** to test your own
4. When "Custom" is selected, enter your theme's JS and CSS filenames (e.g., `mytheme.js` and `mytheme.css`)
4. When "Custom" is selected, enter your theme's JS and CSS filenames (e.g., `mytheme.js` and `mytheme.css` (must be in the same folder as `test-site.html` for this to work))
5. Click **"Load Theme"** to apply. Click **"Clear & Reload"** to reset and try again
### What to Verify
- ✅ The effect is visible on the dark background
- ✅ The animation runs smoothly without jank
- ✅ The effect is visible on the background
- ✅ The animation runs smoothly
- ✅ Elements are spread across the full viewport
- ✅ The mock header is **not blocked** by the effect (thanks to `pointer-events: none`)
- ✅ Performance is acceptable (check DevTools → Performance tab)
- ✅ No console errors appear (check DevTools → Console)
- ✅ No theme related console errors appear (check DevTools → Console)
---
@@ -299,8 +293,8 @@ You can test your theme without a Jellyfin server by using the included test sit
- [ ] Created `{themeName}.css` following the [CSS pattern](#css-file-pattern)
- [ ] (If applicable) Created `{themeName}_images/` with optimized assets
- [ ] Added theme to `ThemeConfigs` in `seasonals.js`
- [ ] Tested locally with `test-site-new.html`
- [ ] No console errors
- [ ] Tested locally with `test-site.html`
- [ ] No theme related console errors
- [ ] Effect has `pointer-events: none` (doesn't block the UI)
- [ ] Effect hides during video/trailer playback (toggle function implemented)
- [ ] (Optional) Included a screenshot or short recording of the effect to the readme
@@ -312,13 +306,8 @@ You can test your theme without a Jellyfin server by using the included test sit
**Description:** Brief description of the theme and what occasion/season it's for.
**Files Added:**
- `{themeName}.js`
- `{themeName}.css`
- `{themeName}_images/` (if applicable)
**Screenshot / Recording:**
[Attach a screenshot or GIF here]
[Attach a screenshot or GIF showcasing the theme in action]
**Testing:**
- Tested locally with test-site-new.html ✅