# Theme Creation Guide **Published version:** [docs.betterseqta.org/theme-creation/](https://docs.betterseqta.org/theme-creation/) This guide covers everything you need to know about creating custom themes for BetterSEQTA+. ## Table of Contents 1. [Overview](#overview) 2. [Theme Structure](#theme-structure) 3. [CSS Variables](#css-variables) 4. [CSS Selectors & Classes](#css-selectors--classes) 5. [Custom Images](#custom-images) 6. [Theme Settings](#theme-settings) 7. [Best Practices](#best-practices) 8. [Examples](#examples) ## Overview Themes in BetterSEQTA+ allow you to completely customize the appearance of SEQTA Learn. A theme consists of: - **Custom CSS**: CSS rules that override default styles - **Custom Images**: Images that can be referenced via CSS variables - **Theme Metadata**: Name, description, default color, etc. - **Theme Settings**: Options like forcing dark/light mode Themes are applied by injecting CSS into the SEQTA page and setting CSS custom properties (variables) on the document root. ## CSS Variables BetterSEQTA+ provides a comprehensive set of CSS variables that you can use in your themes. These variables automatically adapt to light/dark mode and user preferences. ### Core Background Variables | Variable | Light Mode | Dark Mode | Description | |----------|------------|-----------|-------------| | `--background-primary` | `#ffffff` | `#232323` | Main background color | | `--background-secondary` | `#e5e7eb` | `#1a1a1a` | Secondary background color | | `--theme-primary` | `#ffffff` | `#232323` | Primary theme color (same as background-primary) | | `--theme-secondary` | `#e5e7eb` | `#1a1a1a` | Secondary theme color (same as background-secondary) | | `--text-primary` | `black` | `white` | Primary text color | | `--text-color` | `black` | `white` | Text color (alias for text-primary) | ### BetterSEQTA+ Specific Variables | Variable | Description | Notes | |----------|-------------|-------| | `--better-main` | User's selected accent color | Dynamically set based on color picker | | `--better-sub` | Dark navy color | Always `#161616` | | `--better-pale` | Lightened version of accent color | Only available in light mode | | `--better-light` | Lighter version of accent color | Calculated based on brightness | | `--better-alert-highlight` | Alert/highlight color | `#c61851` | | `--betterseqta-logo` | Logo URL | Changes based on dark/light mode | | `--auto-background` | Auto background color | Falls back to `--better-pale` or `--background-secondary` | | `--navy` | Navy color | `#1a1a1a` | | `--theme-fg-parts` | Theme foreground parts | `white` | ### Subject/Item Color Variables | Variable | Description | |----------|-------------| | `--item-colour` | Subject/item color | Set dynamically per subject/item | | `--colour` | Generic color variable | Used in various contexts | | `--person-colour` | Person/avatar color | `var(--better-light)` for staff | ### Transparency Effects When transparency effects are enabled, background variables become semi-transparent: | Variable | Light Mode (Transparent) | Dark Mode (Transparent) | |----------|--------------------------|-------------------------| | `--background-primary` | `rgba(255, 255, 255, 0.6)` | `rgba(35, 35, 35, 0.6)` | | `--background-secondary` | `rgba(229, 231, 235, 0.6)` | `rgba(26, 26, 26, 0.6)` | ### Using CSS Variables You can use these variables in your custom CSS: ```css /* Example: Style a custom element */ .my-custom-element { background: var(--background-primary); color: var(--text-primary); border: 1px solid var(--better-main); } /* Example: Create a gradient */ .gradient-box { background: linear-gradient( to bottom, var(--better-main), var(--background-secondary) ); } ``` ## CSS Selectors & Classes BetterSEQTA+ uses specific CSS selectors and classes that you can target in your themes. Here are the most important ones: ### Main Layout Elements | Selector | Description | |----------|-------------| | `#container` | Main container element | | `#content` | Content area | | `#main` | Main content wrapper | | `#title` | Top title bar | | `#menu` | Sidebar menu | ### Dark Mode The `dark` class is added to `html` when dark mode is active: ```css /* Target dark mode specifically */ html.dark #main { background: var(--background-primary); } /* Target light mode */ html:not(.dark) #main { background: var(--background-primary); } ``` ### Transparency Effects When transparency effects are enabled, the `transparencyEffects` class is added to `html`: ```css html.transparencyEffects .notice { backdrop-filter: blur(80px); } ``` ### Common SEQTA Classes | Class/Selector | Description | |----------------|-------------| | `.notice` | Notice cards | | `.day` | Day containers in timetable | | `.dashboard` | Dashboard sections | | `.dashlet` | Dashboard widgets | | `.document` | Document elements | | `.quickbar` | Quick action bar | | `.calendar` | Calendar elements | | `.message` | Message elements | | `.thread` | Forum threads | | `.shortcut` | Shortcut buttons | | `.upcoming-assessment` | Upcoming assessments | | `.entry.class` | Timetable entries | ### BetterSEQTA+ Specific Classes | Class | Description | |-------|-------------| | `.addedButton` | BetterSEQTA+ added buttons | | `.tooltip` | Tooltip elements | | `.notice-unified-content` | Unified notice content | | `.home-container` | Home page container | | `.timetable-container` | Timetable container | | `.notices-container` | Notices container | ### Attribute Selectors SEQTA uses data attributes that you can target: ```css /* Target specific data types */ [data-type="student"] .header { color: var(--text-primary); } /* Target specific labels */ [data-label="inbox"] { /* Styles */ } ``` ### CSS Modules SEQTA uses CSS modules with hashed class names. You can target them using attribute selectors: ```css /* Target CSS module classes */ [class*="MessageList__MessageList___"] { background: var(--background-primary); } [class*="BasicPanel__BasicPanel___"] { border-radius: 16px; } ``` ## Custom Images Themes can include custom images that are made available as CSS variables. ### Adding Images 1. Upload an image in the theme creator 2. Set a CSS variable name (e.g., `custom-background`) 3. The image will be available as `var(--custom-background)` ### Using Image Variables ```css /* Use as background */ .my-element { background-image: var(--custom-background); background-size: cover; background-position: center; } /* Use in content */ .my-icon::before { content: ''; background-image: var(--custom-icon); width: 24px; height: 24px; } ``` ### Image Variable Format Images are stored as `url()` values: ```css /* The variable contains: url(blob:...) */ --custom-background: url(blob:chrome-extension://...); ``` ## Theme Settings ### Force Dark/Light Mode You can force a theme to always use dark or light mode: ```typescript forceDark: true // Force dark mode forceDark: false // Force light mode forceDark: undefined // Use user's preference (default) ``` When `forceDark` is set, users cannot toggle dark/light mode while the theme is active. ### Default Color Set a default accent color for your theme: ```typescript defaultColour: "rgba(0, 123, 255, 1)" // Blue defaultColour: "#ff6b6b" // Red (hex format) ``` ### Allow Color Changes Control whether users can change the accent color: ```typescript CanChangeColour: true // Users can change color CanChangeColour: false // Color is locked ``` ## Best Practices ### 1. Use CSS Variables Always use CSS variables instead of hardcoded colors: ```css /* Good */ .my-element { background: var(--background-primary); color: var(--text-primary); } /* Bad */ .my-element { background: #ffffff; color: #000000; } ``` ### 2. Support Both Light and Dark Modes Unless your theme forces a specific mode, ensure it works in both: ```css /* Use variables that adapt automatically */ .my-element { background: var(--background-primary); color: var(--text-primary); } /* Or explicitly handle both modes */ html.dark .my-element { background: #1a1a1a; } html:not(.dark) .my-element { background: #ffffff; } ``` ### 3. Use !important Sparingly Only use `!important` when necessary to override SEQTA's default styles: ```css /* Good - necessary override */ #title { background: var(--background-primary) !important; } /* Bad - unnecessary */ .my-element { color: var(--text-primary) !important; } ``` ### 4. Test Responsive Design SEQTA is responsive. Test your theme at different screen sizes: ```css /* Example: Mobile-specific styles */ @media (max-width: 900px) { #menu { transform: translate(-270px); } } ``` ### 5. Use Semantic Selectors Prefer semantic selectors over fragile ones: ```css /* Good - stable selector */ #main > .dashboard > section { border-radius: 16px; } /* Caution - CSS module classes may change */ [class*="Dashboard__Dashboard___"] { border-radius: 16px; } ``` ### 6. Optimize Images Keep image file sizes reasonable: - Use appropriate formats (PNG for transparency, JPG for photos) - Compress images before uploading - Consider using CSS for simple graphics instead of images ### 7. Document Your Theme Include comments in your CSS explaining complex styles: ```css /* * Custom gradient background for dashboard * Uses the user's accent color for a cohesive look */ #main > .dashboard { background: linear-gradient( 135deg, var(--better-main), var(--background-secondary) ); } ``` ## Examples ### Example 1: Simple Color Theme ```css /* Change accent color throughout */ :root { --better-main: #ff6b6b; } /* Style the menu */ #menu { background: var(--background-primary); border-right: 3px solid var(--better-main); } /* Style buttons */ .uiButton { background: var(--better-main); color: var(--text-color); border-radius: 8px; } ``` ### Example 2: Custom Background Image ```css /* Use a custom background image */ body { background-image: var(--custom-background); background-size: cover; background-attachment: fixed; } /* Add overlay for readability */ #main::before { content: ''; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.3); z-index: -1; } ``` ### Example 3: Rounded Corners Theme ```css /* Make everything more rounded */ #main > .dashboard > section, .dashlet, .notice, .document { border-radius: 20px !important; } /* Round buttons */ .uiButton { border-radius: 25px !important; } ``` ### Example 4: Minimal Theme ```css /* Remove shadows and borders */ #main > .dashboard > section, .dashlet, .notice { box-shadow: none !important; border: 1px solid var(--background-secondary) !important; } /* Simplify colors */ #menu { background: var(--background-primary) !important; } /* Remove gradients */ .day { background: var(--background-primary) !important; } ``` ### Example 5: High Contrast Theme ```css /* Increase contrast */ :root { --background-primary: #000000; --background-secondary: #1a1a1a; --text-primary: #ffffff; } html:not(.dark) { --background-primary: #ffffff; --background-secondary: #f0f0f0; --text-primary: #000000; } /* Add borders for clarity */ .dashlet, .notice, .document { border: 2px solid var(--better-main) !important; } ``` ## Advanced Techniques ### CSS Custom Properties Override You can override CSS variables in your theme: ```css /* Override a variable */ :root { --better-main: #your-color; } /* Override conditionally */ html.dark { --background-primary: #your-dark-color; } ``` ### Animations Add smooth transitions: ```css /* Smooth color transitions */ #menu li { transition: background-color 0.3s ease; } /* Hover effects */ .dashlet:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); transition: all 0.3s ease; } ``` ### Pseudo-elements Use pseudo-elements for decorative elements: ```css /* Add decorative border */ .notice::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; background: var(--better-main); } ``` ## Troubleshooting ### Theme Not Applying 1. Check browser console for CSS errors 2. Verify CSS syntax is correct 3. Ensure selectors are specific enough 4. Check if `!important` is needed ### Colors Not Changing 1. Verify you're using CSS variables 2. Check if `forceDark` is overriding your styles 3. Ensure variables are set on `:root` or `html` ### Images Not Showing 1. Verify image variable name matches CSS 2. Check image format is supported 3. Ensure image size is reasonable 4. Verify `url()` wrapper in CSS ### Dark Mode Issues 1. Test with `forceDark: true` and `forceDark: false` 2. Check if transparency effects are interfering 3. Verify `html.dark` selector is correct ## Resources - **Theme Creator**: Access via BetterSEQTA+ settings - **CSS Variables Reference**: See [CSS Variables](#css-variables) section above - **SEQTA DOM Structure**: Inspect SEQTA pages in browser DevTools - **BetterSEQTA+ Source**: Check `src/css/injected.scss` for default styles ## Contributing Themes If you create a great theme, consider sharing it: 1. Export your theme (Share button in theme creator) 2. Submit to the BetterSEQTA+ theme store 3. Or share on GitHub/Discord --- **Note**: This documentation is based on BetterSEQTA+ v3.4.13. Some details may change in future versions.