mirror of
https://github.com/directus/directus.git
synced 2026-04-25 03:00:53 -04:00
Updated Public Page Artwork (#20309)
* from rainbow to lava lamp * svg paths to divs for performance * Clean up styles * Public view themable options * Make speed themable * Add changeset --------- Co-authored-by: Rijk van Zanten <rijkvanzanten@me.com>
This commit is contained in:
6
.changeset/new-pugs-speak.md
Normal file
6
.changeset/new-pugs-speak.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@directus/themes': minor
|
||||
'@directus/app': minor
|
||||
---
|
||||
|
||||
Added a new login page default art
|
||||
@@ -1,9 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { useServerStore } from '@/stores/server';
|
||||
import { getAppearance } from '@/utils/get-appearance';
|
||||
import { getRootPath } from '@/utils/get-root-path';
|
||||
import { cssVar } from '@directus/utils/browser';
|
||||
import Color from 'color';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
@@ -21,47 +18,6 @@ const serverStore = useServerStore();
|
||||
|
||||
const { info } = storeToRefs(serverStore);
|
||||
|
||||
const colors = computed(() => {
|
||||
const primary = info.value?.project?.project_color || 'var(--theme--primary)';
|
||||
const primaryHex = primary.startsWith('var(--') ? cssVar(primary.substring(4, primary.length - 1)) : primary;
|
||||
const isDark = getAppearance() === 'dark';
|
||||
const primaryColor = Color(primaryHex);
|
||||
|
||||
const primaryColorHSL = primaryColor.hsl() as unknown as {
|
||||
model: 'hsl';
|
||||
color: [number, number, number];
|
||||
valpha: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* The default light mode secondary color is based on the standard difference between Directus purple and pink, which is:
|
||||
* primary = 250.9, 100, 63.3
|
||||
* secondary = 320, 100, 80
|
||||
* diff = +69.1, 0, +16.7
|
||||
*
|
||||
* For dark mode, we greatly reduce the lightness value to -50
|
||||
*/
|
||||
|
||||
const secondaryColor = Color({
|
||||
h: primaryColorHSL.color[0] + (isDark ? -69.1 : 69.1),
|
||||
s: primaryColorHSL.color[1] + 0,
|
||||
l: primaryColorHSL.color[2] + (isDark ? -50 : 16.7),
|
||||
});
|
||||
|
||||
const shades = [];
|
||||
|
||||
for (let i = 1; i < 6; i++) {
|
||||
const color = Color(primaryColor).mix(secondaryColor, i / 10);
|
||||
shades.push(color.hex().toString());
|
||||
}
|
||||
|
||||
return {
|
||||
primary: primaryColor.hex().toString(),
|
||||
secondary: secondaryColor.hex().toString(),
|
||||
shades: shades,
|
||||
};
|
||||
});
|
||||
|
||||
const hasCustomBackground = computed(() => {
|
||||
return !!info.value?.project?.public_background;
|
||||
});
|
||||
@@ -121,29 +77,11 @@ const logoURL = computed<string | null>(() => {
|
||||
</div>
|
||||
</div>
|
||||
<div class="art" :style="artStyles">
|
||||
<svg v-if="!hasCustomBackground" viewBox="0 0 1152 1152" preserveAspectRatio="none" fill="none" class="fallback">
|
||||
<rect width="1152" height="1152" :fill="colors.primary" />
|
||||
<path
|
||||
d="M1152 409.138C1148.61 406.92 1146.7 405.765 1146.7 405.765L6.87761e-07 958.424L-7.3277e-07 1152L506.681 1152C558.985 1126.93 614.88 1101.25 672.113 1074.95C839.401 998.085 1018.12 915.967 1152 828.591L1152 409.138Z"
|
||||
:fill="colors.shades[0]"
|
||||
/>
|
||||
<path
|
||||
d="M1152 159.866C1130.19 146.319 1114.45 138.98 1114.45 138.98L-6.09246e-07 759.421L-3.66364e-07 1152L88.7501 1152C131.867 1108.8 194.289 1054.33 281.936 993.927C371.847 931.97 507.23 864.306 651.138 792.382C828.097 703.939 1017.95 609.052 1152 510.407L1152 159.866Z"
|
||||
:fill="colors.shades[1]"
|
||||
/>
|
||||
<path
|
||||
d="M772.894 -0.000472457L-4.49523e-07 457.782L-5.22658e-07 953.071C22.142 919.082 94.6279 821.1 262.854 696.786C351.427 631.334 485.624 558.338 628.272 480.744C816.642 378.28 1019.75 267.8 1152 156.087L1152 -0.000477328L772.894 -0.000472457Z"
|
||||
:fill="colors.shades[2]"
|
||||
/>
|
||||
<path
|
||||
d="M286.365 -0.000483108L-1.73191e-07 176.373L2.43255e-06 662.21C33.488 615.87 106.028 529.959 243.326 424.909C331.205 357.671 464.771 281.956 606.749 201.473C720.914 136.756 840.519 68.9554 946.182 -0.000479285L286.365 -0.000483108Z"
|
||||
:fill="colors.shades[3]"
|
||||
/>
|
||||
<path
|
||||
d="M0.00195277 363.139C37.1564 313.499 107.096 233.66 228.181 137.623C281.94 94.9838 353.09 48.7594 432.872 9.43526e-06L0.00195595 0L0.00195277 363.139Z"
|
||||
:fill="colors.shades[4]"
|
||||
/>
|
||||
</svg>
|
||||
<div v-if="!hasCustomBackground" class="fallback">
|
||||
<div><div></div></div>
|
||||
<div><div></div></div>
|
||||
<div><div></div></div>
|
||||
</div>
|
||||
|
||||
<transition name="scale">
|
||||
<v-image v-if="foregroundURL" class="foreground" :src="foregroundURL" :alt="info?.project?.project_name" />
|
||||
@@ -225,12 +163,157 @@ const logoURL = computed<string | null>(() => {
|
||||
background-size: cover;
|
||||
|
||||
.fallback {
|
||||
position: absolute;
|
||||
background-color: var(--theme--public--art--background);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: -1;
|
||||
overflow: hidden;
|
||||
|
||||
> div {
|
||||
position: absolute;
|
||||
|
||||
> div {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
animation-iteration-count: infinite;
|
||||
animation-timing-function: ease-in-out;
|
||||
transform-origin: center center;
|
||||
}
|
||||
}
|
||||
|
||||
> div:nth-child(1) {
|
||||
bottom: -25%;
|
||||
left: -25%;
|
||||
height: 50%;
|
||||
width: 50%;
|
||||
filter: blur(100px);
|
||||
z-index: 3;
|
||||
|
||||
> div {
|
||||
background-color: var(--theme--public--art--primary);
|
||||
opacity: 0.5;
|
||||
animation-name: floating1;
|
||||
animation-duration: calc(33s / var(--theme--public--art--speed));
|
||||
}
|
||||
}
|
||||
|
||||
> div:nth-child(2) {
|
||||
bottom: -25%;
|
||||
left: 15%;
|
||||
height: 40%;
|
||||
width: 60%;
|
||||
filter: blur(150px);
|
||||
z-index: 2;
|
||||
|
||||
> div {
|
||||
background: linear-gradient(
|
||||
107.7deg,
|
||||
var(--theme--public--art--primary) 0%,
|
||||
var(--theme--public--art--secondary) 50%
|
||||
);
|
||||
opacity: 0.7;
|
||||
animation-name: floating2;
|
||||
animation-duration: calc(19s / var(--theme--public--art--speed));
|
||||
}
|
||||
}
|
||||
|
||||
> div:nth-child(3) {
|
||||
bottom: -20%;
|
||||
left: 75%;
|
||||
height: 20%;
|
||||
width: 40%;
|
||||
filter: blur(50px);
|
||||
z-index: 1;
|
||||
|
||||
> div {
|
||||
background-color: var(--theme--public--art--primary);
|
||||
opacity: 0.6;
|
||||
animation-name: floating3;
|
||||
animation-duration: calc(27s / var(--theme--public--art--speed));
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes floating1 {
|
||||
0% {
|
||||
transform: translate(00%, 00%) scale(1, 1) rotate(0deg);
|
||||
}
|
||||
10% {
|
||||
transform: translate(25%, -20%) scale(1.5, 1) rotate(0deg);
|
||||
}
|
||||
20% {
|
||||
transform: translate(10%, -25%) scale(1, 1.5) rotate(0deg);
|
||||
}
|
||||
30% {
|
||||
transform: translate(00%, -20%) scale(1, 1.5) rotate(-45deg);
|
||||
}
|
||||
40% {
|
||||
transform: translate(10%, -30%) scale(1, 2) rotate(0deg);
|
||||
}
|
||||
50% {
|
||||
transform: translate(15%, -35%) scale(2, 0.5) rotate(45deg);
|
||||
}
|
||||
60% {
|
||||
transform: translate(10%, -30%) scale(1, 2) rotate(90deg);
|
||||
}
|
||||
70% {
|
||||
transform: translate(25%, -10%) scale(1, 1.5) rotate(45deg);
|
||||
}
|
||||
80% {
|
||||
transform: translate(40%, 20%) scale(1.5, 0.5) rotate(-45deg);
|
||||
}
|
||||
90% {
|
||||
transform: translate(15%, -20%) scale(2, 1.5) rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: translate(00%, 00%) scale(1, 1) rotate(0deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes floating2 {
|
||||
0% {
|
||||
transform: translate(00%, 00%) scale(1, 1) rotate(0deg);
|
||||
}
|
||||
20% {
|
||||
transform: translate(-10%, -05%) scale(1.5, 1.5) rotate(15deg);
|
||||
}
|
||||
40% {
|
||||
transform: translate(00%, -15%) scale(2, 0.5) rotate(-45deg);
|
||||
}
|
||||
60% {
|
||||
transform: translate(-15%, -10%) scale(1.5, 1) rotate(45deg);
|
||||
}
|
||||
80% {
|
||||
transform: translate(-25%, -05%) scale(2.5, 0.5) rotate(180deg);
|
||||
}
|
||||
100% {
|
||||
transform: translate(00%, 00%) scale(1, 1) rotate(0deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes floating3 {
|
||||
0% {
|
||||
transform: translate(00%, 00%) scale(1, 1) rotate(0deg);
|
||||
}
|
||||
25% {
|
||||
transform: translate(-10%, -10%) scale(2, 1) rotate(-15deg);
|
||||
}
|
||||
50% {
|
||||
transform: translate(-20%, -05%) scale(1, 0.5) rotate(45deg);
|
||||
}
|
||||
75% {
|
||||
transform: translate(-15%, -15%) scale(2, 1.5) rotate(180deg);
|
||||
}
|
||||
100% {
|
||||
transform: translate(00%, 00%) scale(1, 1) rotate(0deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.foreground {
|
||||
|
||||
@@ -6,6 +6,7 @@ const FamilyName = Type.String({ $id: 'FamilyName' });
|
||||
const Length = Type.String({ $id: 'Length' });
|
||||
const Percentage = Type.String({ $id: 'Percentage' });
|
||||
const BoxShadow = Type.String({ $id: 'BoxShadow' });
|
||||
const Number = Type.String({ $id: 'Number' });
|
||||
|
||||
const LineWidth = Type.Union([Type.String(), Type.Literal('thin'), Type.Literal('medium'), Type.Literal('thick')], {
|
||||
$id: 'LineWidth',
|
||||
@@ -189,6 +190,15 @@ const Rules = Type.Object({
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
|
||||
public: Type.Object({
|
||||
art: Type.Object({
|
||||
background: Type.Ref(Color),
|
||||
primary: Type.Ref(Color),
|
||||
secondary: Type.Ref(Color),
|
||||
speed: Type.Ref(Number),
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
export const ThemeSchema = Type.Object({
|
||||
@@ -205,6 +215,7 @@ export const Definitions = {
|
||||
Percentage,
|
||||
LineWidth,
|
||||
BoxShadow,
|
||||
Number,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -173,5 +173,14 @@ export const theme: Theme = {
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
public: {
|
||||
art: {
|
||||
background: '#0e1c2f',
|
||||
primary: 'var(--theme--primary)',
|
||||
secondary: 'var(--theme--secondary)',
|
||||
speed: '1',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -67,7 +67,7 @@ export const theme: Theme = {
|
||||
},
|
||||
|
||||
modules: {
|
||||
background: '#18222f',
|
||||
background: '#0e1c2f',
|
||||
borderColor: 'transparent',
|
||||
borderWidth: '0px',
|
||||
|
||||
@@ -173,5 +173,14 @@ export const theme: Theme = {
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
public: {
|
||||
art: {
|
||||
background: '#0e1c2f',
|
||||
primary: 'var(--theme--primary)',
|
||||
secondary: 'var(--theme--secondary)',
|
||||
speed: '1',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user