add: dynamic themes and streamlined theme creation system
This commit is contained in:
@@ -1,15 +1,13 @@
|
||||
<script lang="ts">
|
||||
import TopPattern from './svgs/TopPattern.svelte';
|
||||
import BottomPattern from './svgs/BottomPattern.svelte';
|
||||
import { getTheme } from '$lib/utils/themes';
|
||||
|
||||
const patternOpacity = 0.1;
|
||||
import { getTheme, getPatternColor, PATTERN_OPACITY } from '$lib/utils/themes';
|
||||
|
||||
let {
|
||||
themeName,
|
||||
showTop = true,
|
||||
showBottom = true,
|
||||
color = "#FFFFFF"
|
||||
color
|
||||
}: {
|
||||
themeName?: string | null;
|
||||
showTop?: boolean;
|
||||
@@ -18,21 +16,14 @@
|
||||
} = $props();
|
||||
|
||||
const theme = $derived(getTheme(themeName));
|
||||
const patternColor = $derived(getPatternColor(color));
|
||||
</script>
|
||||
|
||||
{#if theme.pattern !== 'none'}
|
||||
{#if showTop}
|
||||
<TopPattern
|
||||
pattern={theme.pattern}
|
||||
color={color}
|
||||
opacity={patternOpacity}
|
||||
/>
|
||||
<TopPattern pattern={theme.pattern} color={patternColor} opacity={PATTERN_OPACITY} />
|
||||
{/if}
|
||||
{#if showBottom}
|
||||
<BottomPattern
|
||||
pattern={theme.pattern}
|
||||
color={color}
|
||||
opacity={patternOpacity}
|
||||
/>
|
||||
<BottomPattern pattern={theme.pattern} color={patternColor} opacity={PATTERN_OPACITY} />
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
<script lang="ts">
|
||||
import CardPattern from './svgs/CardPattern.svelte';
|
||||
import { getTheme } from '$lib/utils/themes';
|
||||
|
||||
const patternOpacity = 0.1;
|
||||
import { getTheme, getPatternColor, PATTERN_OPACITY } from '$lib/utils/themes';
|
||||
|
||||
let {
|
||||
themeName,
|
||||
@@ -13,11 +11,9 @@
|
||||
} = $props();
|
||||
|
||||
const theme = $derived(getTheme(themeName));
|
||||
const patternColor = $derived(getPatternColor(color));
|
||||
</script>
|
||||
|
||||
{#if theme.pattern !== 'none'}
|
||||
<CardPattern
|
||||
pattern={theme.pattern}
|
||||
opacity={patternOpacity}
|
||||
/>
|
||||
<CardPattern pattern={theme.pattern} color={patternColor} opacity={PATTERN_OPACITY} />
|
||||
{/if}
|
||||
|
||||
@@ -1,38 +1,32 @@
|
||||
<script lang="ts">
|
||||
import { asset } from '$app/paths';
|
||||
|
||||
let {
|
||||
color = 'currentColor',
|
||||
opacity = 0.1,
|
||||
pattern = 'waves'
|
||||
pattern = 'none',
|
||||
color = '#000000',
|
||||
opacity = 0.1
|
||||
}: {
|
||||
pattern?: string;
|
||||
color?: string;
|
||||
opacity?: number;
|
||||
pattern?: 'waves' | 'geometric' | 'dots';
|
||||
} = $props();
|
||||
|
||||
const patternPath = $derived(asset(`/themes/${pattern}/bgbottom.svg`));
|
||||
</script>
|
||||
|
||||
<div class="absolute bottom-0 left-0 right-0 pointer-events-none overflow-hidden" style="opacity: {opacity};">
|
||||
{#if pattern === 'waves'}
|
||||
<svg class="w-full h-auto" viewBox="0 0 1440 200" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
fill={color}
|
||||
d="M0,100 C240,50 480,150 720,100 C960,50 1200,150 1440,100 L1440,200 L0,200 Z"
|
||||
/>
|
||||
</svg>
|
||||
{:else if pattern === 'geometric'}
|
||||
<svg class="w-full h-auto" viewBox="0 0 1440 200" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
fill={color}
|
||||
d="M0,200 L720,50 L1440,200 Z"
|
||||
/>
|
||||
</svg>
|
||||
{:else if pattern === 'dots'}
|
||||
<svg class="w-full h-auto" viewBox="0 0 1440 200" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<pattern id="dots-pattern-bottom" x="0" y="0" width="40" height="40" patternUnits="userSpaceOnUse">
|
||||
<circle cx="20" cy="20" r="3" fill={color} />
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect width="1440" height="200" fill="url(#dots-pattern-bottom)" />
|
||||
</svg>
|
||||
{/if}
|
||||
</div>
|
||||
{#if pattern !== 'none'}
|
||||
<div
|
||||
class="absolute bottom-0 left-0 right-0 pointer-events-none overflow-hidden"
|
||||
style="
|
||||
mask-image: url({patternPath});
|
||||
-webkit-mask-image: url({patternPath});
|
||||
mask-size: cover;
|
||||
-webkit-mask-size: cover;
|
||||
mask-repeat: repeat;
|
||||
-webkit-mask-repeat: repeat;
|
||||
background-color: {color};
|
||||
opacity: {opacity};
|
||||
height: 200px;
|
||||
"
|
||||
/>
|
||||
{/if}
|
||||
|
||||
@@ -1,14 +1,33 @@
|
||||
<script lang="ts">
|
||||
import { asset } from '$app/paths';
|
||||
|
||||
let {
|
||||
pattern = 'none'
|
||||
pattern = 'none',
|
||||
color = '#000000',
|
||||
opacity = 0.1
|
||||
}: {
|
||||
pattern?: string;
|
||||
color?: string;
|
||||
opacity?: number;
|
||||
} = $props();
|
||||
const patternPath = `/themes/${pattern}/item.svg`;
|
||||
const patternOpacity = 0.2;
|
||||
|
||||
const patternPath = $derived(asset(`/themes/${pattern}/item.svg`));
|
||||
</script>
|
||||
|
||||
<div class="absolute bottom-0 right-0 pointer-events-none overflow-hidden rounded-b-lg" style="opacity: {patternOpacity};">
|
||||
<img alt="card svg background pattern" src={asset(patternPath)}>
|
||||
</div>
|
||||
{#if pattern !== 'none'}
|
||||
<div
|
||||
class="absolute bottom-0 right-0 pointer-events-none overflow-hidden rounded-b-lg"
|
||||
style="
|
||||
mask-image: url({patternPath});
|
||||
-webkit-mask-image: url({patternPath});
|
||||
mask-size: cover;
|
||||
-webkit-mask-size: cover;
|
||||
mask-repeat: repeat;
|
||||
-webkit-mask-repeat: repeat;
|
||||
background-color: {color};
|
||||
opacity: {opacity};
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
"
|
||||
/>
|
||||
{/if}
|
||||
|
||||
@@ -1,45 +1,32 @@
|
||||
<script lang="ts">
|
||||
import { asset } from "$app/paths";
|
||||
import { themeStore } from '$lib/stores/theme.svelte';
|
||||
import { asset } from '$app/paths';
|
||||
|
||||
let {
|
||||
pattern = 'none'
|
||||
pattern = 'none',
|
||||
color = '#000000',
|
||||
opacity = 0.1
|
||||
}: {
|
||||
pattern?: string;
|
||||
color?: string;
|
||||
opacity?: number;
|
||||
} = $props();
|
||||
const patternOpacity = 0.1;
|
||||
|
||||
let svgContainer = $state<HTMLDivElement>();
|
||||
let svgContent = $state('');
|
||||
const lightColor = "#000000";
|
||||
const darkColor = "#FFFFFF";
|
||||
|
||||
$effect(() => {
|
||||
const patternPath = `/themes/${pattern}/bgtop.svg`;
|
||||
const color = themeStore.getResolvedTheme() === 'dark' ? darkColor : lightColor;
|
||||
|
||||
fetch(asset(patternPath))
|
||||
.then(res => res.text())
|
||||
.then(svg => {
|
||||
// Manipulate SVG to change colors
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(svg, 'image/svg+xml');
|
||||
const svgEl = doc.querySelector('svg');
|
||||
|
||||
if (svgEl) {
|
||||
// Change fill colors
|
||||
svgEl.querySelectorAll('[fill]').forEach(el => {
|
||||
if (el.getAttribute('fill') !== 'none') {
|
||||
el.setAttribute('fill', color);
|
||||
}
|
||||
});
|
||||
|
||||
svgContent = svgEl.outerHTML;
|
||||
}
|
||||
});
|
||||
});
|
||||
const patternPath = $derived(asset(`/themes/${pattern}/bgtop.svg`));
|
||||
</script>
|
||||
|
||||
<div class="absolute top-0 left-0 right-0 pointer-events-none overflow-hidden" bind:this={svgContainer} style="opacity: {patternOpacity};">
|
||||
{@html svgContent}
|
||||
</div>
|
||||
{#if pattern !== 'none'}
|
||||
<div
|
||||
class="absolute top-0 left-0 right-0 pointer-events-none overflow-hidden"
|
||||
style="
|
||||
mask-image: url({patternPath});
|
||||
-webkit-mask-image: url({patternPath});
|
||||
mask-size: cover;
|
||||
-webkit-mask-size: cover;
|
||||
mask-repeat: repeat;
|
||||
-webkit-mask-repeat: repeat;
|
||||
background-color: {color};
|
||||
opacity: {opacity};
|
||||
height: 200px;
|
||||
"
|
||||
/>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user