Add custom theming (#2081)

Adds support for user-created custom themes. Custom theme interface is
tucked into the global settings in a non-invasive manner to avoid major
design changes. Builds on the theme structure established by the dark
theme update.

<img width="1486" height="953" alt="image"
src="https://github.com/user-attachments/assets/716bcfc7-af74-41dc-b14a-cfc2f2d2caa9"
/>

<img width="1486" height="956" alt="image"
src="https://github.com/user-attachments/assets/a00f9620-0b1d-4f67-b010-e94dda5dc212"
/>



Here's a few examples of what teams could do, using a few color schemes
from local teams. Imagine the possibilities!

<img width="1485" height="951" alt="image"
src="https://github.com/user-attachments/assets/c3da37b8-f6be-4152-81e0-533297f517fc"
/>

<img width="1483" height="951" alt="image"
src="https://github.com/user-attachments/assets/0d453f7a-cf6f-4c27-97db-603b54c1f73e"
/>

<img width="1485" height="952" alt="image"
src="https://github.com/user-attachments/assets/bf8c7770-e60d-4875-9580-ed7e54e089f4"
/>

<img width="1484" height="952" alt="image"
src="https://github.com/user-attachments/assets/326d89e6-dd6e-4e05-a9fa-c9fc6f880847"
/>

<img width="1482" height="951" alt="image"
src="https://github.com/user-attachments/assets/eb5a2a5d-c103-482c-a62a-5ccd5ba21cc5"
/>

<img width="1482" height="950" alt="image"
src="https://github.com/user-attachments/assets/4831ca56-f322-4345-97af-8963ae8539b1"
/>



Looking for high contrast? Just moments away:
<img width="1484" height="949" alt="image"
src="https://github.com/user-attachments/assets/7ffc65c6-7000-4566-b4f0-c8247f75fb3d"
/>
This commit is contained in:
Devon Doyle
2025-09-07 00:33:37 -04:00
committed by GitHub
parent 3300b90823
commit b43d0dde20
9 changed files with 397 additions and 38 deletions

View File

@@ -0,0 +1,205 @@
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 100 100"
preserveAspectRatio="xMidYMid"
width="200"
height="200"
style="shape-rendering: auto; display: block; background: rgba(0, 100, 146, 0)"
xmlns:xlink="http://www.w3.org/1999/xlink"
>
<g>
<g transform="translate(80,50)">
<g transform="rotate(0)">
<circle class="loader-circle" fill-opacity="1" fill="#ffd943" r="6" cy="0" cx="0">
<animateTransform
repeatCount="indefinite"
dur="0.9345794392523364s"
keyTimes="0;1"
values="1.5 1.5;1 1"
begin="-0.8177570093457943s"
type="scale"
attributeName="transform"
></animateTransform>
<animate
begin="-0.8177570093457943s"
values="1;0"
repeatCount="indefinite"
dur="0.9345794392523364s"
keyTimes="0;1"
attributeName="fill-opacity"
></animate>
</circle>
</g>
</g>
<g transform="translate(71.21320343559643,71.21320343559643)">
<g transform="rotate(45)">
<circle class="loader-circle" fill-opacity="0.875" fill="#ffd943" r="6" cy="0" cx="0">
<animateTransform
repeatCount="indefinite"
dur="0.9345794392523364s"
keyTimes="0;1"
values="1.5 1.5;1 1"
begin="-0.7009345794392523s"
type="scale"
attributeName="transform"
></animateTransform>
<animate
begin="-0.7009345794392523s"
values="1;0"
repeatCount="indefinite"
dur="0.9345794392523364s"
keyTimes="0;1"
attributeName="fill-opacity"
></animate>
</circle>
</g>
</g>
<g transform="translate(50,80)">
<g transform="rotate(90)">
<circle class="loader-circle" fill-opacity="0.75" fill="#ffd943" r="6" cy="0" cx="0">
<animateTransform
repeatCount="indefinite"
dur="0.9345794392523364s"
keyTimes="0;1"
values="1.5 1.5;1 1"
begin="-0.5841121495327103s"
type="scale"
attributeName="transform"
></animateTransform>
<animate
begin="-0.5841121495327103s"
values="1;0"
repeatCount="indefinite"
dur="0.9345794392523364s"
keyTimes="0;1"
attributeName="fill-opacity"
></animate>
</circle>
</g>
</g>
<g transform="translate(28.786796564403577,71.21320343559643)">
<g transform="rotate(135)">
<circle class="loader-circle" fill-opacity="0.625" fill="#ffd943" r="6" cy="0" cx="0">
<animateTransform
repeatCount="indefinite"
dur="0.9345794392523364s"
keyTimes="0;1"
values="1.5 1.5;1 1"
begin="-0.4672897196261682s"
type="scale"
attributeName="transform"
></animateTransform>
<animate
begin="-0.4672897196261682s"
values="1;0"
repeatCount="indefinite"
dur="0.9345794392523364s"
keyTimes="0;1"
attributeName="fill-opacity"
></animate>
</circle>
</g>
</g>
<g transform="translate(20,50.00000000000001)">
<g transform="rotate(180)">
<circle class="loader-circle" fill-opacity="0.5" fill="#ffd943" r="6" cy="0" cx="0">
<animateTransform
repeatCount="indefinite"
dur="0.9345794392523364s"
keyTimes="0;1"
values="1.5 1.5;1 1"
begin="-0.35046728971962615s"
type="scale"
attributeName="transform"
></animateTransform>
<animate
begin="-0.35046728971962615s"
values="1;0"
repeatCount="indefinite"
dur="0.9345794392523364s"
keyTimes="0;1"
attributeName="fill-opacity"
></animate>
</circle>
</g>
</g>
<g transform="translate(28.78679656440357,28.786796564403577)">
<g transform="rotate(225)">
<circle class="loader-circle" fill-opacity="0.375" fill="#ffd943" r="6" cy="0" cx="0">
<animateTransform
repeatCount="indefinite"
dur="0.9345794392523364s"
keyTimes="0;1"
values="1.5 1.5;1 1"
begin="-0.2336448598130841s"
type="scale"
attributeName="transform"
></animateTransform>
<animate
begin="-0.2336448598130841s"
values="1;0"
repeatCount="indefinite"
dur="0.9345794392523364s"
keyTimes="0;1"
attributeName="fill-opacity"
></animate>
</circle>
</g>
</g>
<g transform="translate(49.99999999999999,20)">
<g transform="rotate(270)">
<circle class="loader-circle" fill-opacity="0.25" fill="#ffd943" r="6" cy="0" cx="0">
<animateTransform
repeatCount="indefinite"
dur="0.9345794392523364s"
keyTimes="0;1"
values="1.5 1.5;1 1"
begin="-0.11682242990654206s"
type="scale"
attributeName="transform"
></animateTransform>
<animate
begin="-0.11682242990654206s"
values="1;0"
repeatCount="indefinite"
dur="0.9345794392523364s"
keyTimes="0;1"
attributeName="fill-opacity"
></animate>
</circle>
</g>
</g>
<g transform="translate(71.21320343559643,28.78679656440357)">
<g transform="rotate(315)">
<circle class="loader-circle" fill-opacity="0.125" fill="#ffd943" r="6" cy="0" cx="0">
<animateTransform
repeatCount="indefinite"
dur="0.9345794392523364s"
keyTimes="0;1"
values="1.5 1.5;1 1"
begin="0s"
type="scale"
attributeName="transform"
></animateTransform>
<animate
begin="0s"
values="1;0"
repeatCount="indefinite"
dur="0.9345794392523364s"
keyTimes="0;1"
attributeName="fill-opacity"
></animate>
</circle>
</g>
</g>
<g></g>
</g>
<!-- [ldio] generated by https://loading.io -->
</svg>
</template>
<style scoped lang="scss">
.loader-circle {
fill: rgb(var(--v-theme-buttonActive));
}
</style>