V0.3.3: Even more optimization
Some checks failed
Build and Push Docker Image to GHCR / build-and-push (push) Failing after 25m29s

In this realease, I have further optimized Passport. The css that
Passport now uses is entirely handrolled and build via postcss (sadly).
Several bugs have also been fixed in this release, as well as a few
performance improvements relating to the admin UI.
This commit is contained in:
Zoe
2025-10-04 22:02:15 -05:00
parent f6ffc90ec2
commit 68284bc963
28 changed files with 1771 additions and 642 deletions

View File

@@ -1,70 +1,238 @@
.modal-bg {
visibility: hidden;
opacity: 0;
}
@import "./base.css";
@import "./card.css";
.modal-bg.is-visible {
visibility: visible;
opacity: 1;
}
.modal {
opacity: 0;
}
.modal.is-visible {
opacity: 1;
}
@media (prefers-reduced-motion: no-preference) {
@layer components {
.modal-bg {
position: fixed;
visibility: hidden;
opacity: 0;
transition: opacity 0.3s ease, visibility 0s 0.3s;
transition-timing-function: cubic-bezier(0.45, 0, 0.55, 1);
inset: 0;
background-color: color-mix(in srgb, #000 45%, #0000);
justify-content: center;
align-items: center;
}
.modal-bg.is-visible {
visibility: visible;
opacity: 1;
transition-delay: 0s;
}
.modal {
opacity: 0;
transform: translateY(20px) scale(0.95);
transition: opacity 0.3s ease, transform 0.3s ease;
transition-timing-function: cubic-bezier(0.45, 0, 0.55, 1);
background-color: var(--color-overlay);
border-radius: calc(var(--spacing) * 3);
overflow: hidden;
padding: calc(var(--spacing) * 4);
width: 100%;
max-width: 24rem;
}
.modal.is-visible {
opacity: 1;
visibility: visible;
transform: translateY(0) scale(1);
transition-delay: 0s;
}
}
.action-button {
display: flex;
width: fit-content;
height: fit-content;
padding: 0.25rem;
background-color: var(--color-highlight-sm);
border: 1px solid color-mix(in srgb, var(--color-highlight) 70%, #0000);
border-radius: 9999px;
box-shadow: var(--shadow-sm);
cursor: pointer;
transition: filter 0.15s cubic-bezier(0.45, 0, 0.55, 1);
contain: layout style paint;
&:hover {
filter: brightness(125%);
}
&:active {
filter: brightness(95%);
}
#blur-target {
transition: filter 300ms cubic-bezier(0.45, 0, 0.55, 1);
}
@media (prefers-reduced-motion: no-preference) {
.modal-bg {
visibility: hidden;
opacity: 0;
transition: opacity 0.3s ease, visibility 0s 0.3s;
transition-timing-function: cubic-bezier(0.45, 0, 0.55, 1);
}
.modal-bg.is-visible {
visibility: visible;
opacity: 1;
transition-delay: 0s;
}
.modal {
opacity: 0;
transform: translateY(20px) scale(0.95);
transition: opacity 0.3s ease, transform 0.3s ease;
transition-timing-function: cubic-bezier(0.45, 0, 0.55, 1);
}
.modal.is-visible {
opacity: 1;
visibility: visible;
transform: translateY(0) scale(1);
transition-delay: 0s;
}
#blur-target {
transition: none;
}
}
.modal-form {
display: flex;
flex-direction: column;
gap: calc(var(--spacing) * 2);
& > div {
display: flex;
flex-direction: column;
gap: calc(var(--spacing) * 1);
}
& > button {
background-color: var(--color-accent);
color: #fff;
border-radius: calc(var(--spacing) * 1.5);
padding-inline: calc(var(--spacing) * 4);
padding-block: calc(var(--spacing) * 2);
}
}
.delete-modal {
text-align: center;
& > p {
margin-bottom: calc(var(--spacing) * 3);
}
& > div {
display: flex;
justify-content: end;
flex-direction: column;
row-gap: calc(var(--spacing) * 2);
& > button {
padding-inline: calc(var(--spacing) * 4);
padding-block: calc(var(--spacing) * 2);
border-radius: calc(var(--spacing) * 1.5);
width: 100%;
color: #fff;
transition: filter 300ms cubic-bezier(0.45, 0, 0.55, 1);
&:nth-child(1) {
background-color: var(--color-error);
}
&:nth-child(2) {
border: 1px solid var(--color-highlight);
background-color: #0000;
}
&:hover {
filter: brightness(125%);
}
&:active {
filter: brightness(95%);
}
}
}
}
input:invalid.invalid {
border: 1px solid var(--color-error);
}
.new-link-card {
border: calc(var(--spacing) * 0.5) dashed var(--color-subtle);
cursor: pointer;
user-select: none;
&:hover {
text-decoration: underline;
}
}
.action-container {
display: flex;
flex-direction: row;
gap: calc(var(--spacing) * 2);
}
.link-grid > div > div:nth-child(3) {
position: absolute;
right: var(--spacing);
top: var(--spacing);
}
.category-header > div:nth-child(2) {
padding-left: calc(var(--spacing) * 2);
}
.add-category-button {
width: fit-content;
display: flex;
align-items: center;
color: var(--color-subtle);
cursor: pointer;
}
.add-category-button > h2 {
text-decoration: underline;
text-decoration-style: dashed;
text-decoration-thickness: calc(var(--spacing) * 0.5);
&:hover {
text-decoration: none;
}
}
.action-button {
display: flex;
width: fit-content;
height: fit-content;
padding: 0.25rem;
background-color: var(--color-highlight-sm);
border: 1px solid color-mix(in srgb, var(--color-highlight) 70%, #0000);
border-radius: 9999px;
box-shadow: var(--shadow-sm);
cursor: pointer;
transition: filter 0.15s cubic-bezier(0.45, 0, 0.55, 1);
contain: layout style paint;
&:hover {
filter: brightness(125%);
}
&:active {
filter: brightness(95%);
}
}
.select-icon-button {
display: flex;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: color-mix(in srgb, var(--color-highlight) 70%, #0000);
color: var(--color-base);
justify-content: center;
align-items: center;
}
header {
display: flex;
width: 100%;
padding: calc(var(--spacing) * 3);
& > a {
text-decoration: none;
display: flex;
flex-direction: row;
align-items: center;
gap: calc(var(--spacing) * 2);
color: var(--color-text);
border-bottom: 1px solid var(--color-text);
justify-content: center;
line-height: var(--leading-condensed);
&:hover {
border-bottom-color: transparent;
}
}
}
}

199
src/styles/base.css Normal file
View File

@@ -0,0 +1,199 @@
@layer reset, base, components, utilities;
@font-face {
font-family: "Instrument Sans";
src: url("/assets/fonts/InstrumentSans-VariableFont_wdth,wght.woff2")
format("woff2");
font-display: swap;
}
@layer reset {
/*
Josh's Custom CSS Reset slightly Modified
https://www.joshwcomeau.com/css/custom-css-reset/
*/
*,
*::before,
*::after {
box-sizing: border-box;
}
* {
border: 0 solid;
line-height: calc(1em + 0.5rem);
margin: 0;
padding: 0;
}
body {
-webkit-font-smoothing: antialiased;
}
img,
picture,
video,
canvas,
svg {
display: block;
max-width: 100%;
}
input,
button,
textarea,
select {
font: inherit;
}
button {
cursor: pointer;
}
p,
h1,
h2,
h3,
h4,
h5,
h6 {
word-break: break-word;
}
p {
text-wrap: pretty;
hyphens: auto;
}
h1,
h2,
h3,
h4,
h5,
h6 {
text-wrap: balance;
}
a {
color: #fff;
}
}
@layer base {
:root {
--family-sans: "Instrument Sans", ui-sans-serif, system-ui, sans-serif,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol",
"Noto Color Emoji";
--color-accent: oklch(57.93% 0.258 294.12);
--color-success: oklch(70.19% 0.158 160.44);
--color-error: oklch(53% 0.251 28.48);
--color-base: oklch(11% 0.007 285);
--color-surface: oklch(19% 0.007 285.66);
--color-overlay: oklch(26% 0.008 285.66);
--color-muted: oklch(63% 0.015 286);
--color-subtle: oklch(72% 0.015 286);
--color-text: oklch(87% 0.015 286);
--color-highlight-sm: oklch(30.67% 0.007 286);
--color-highlight: oklch(39.26% 0.01 286);
--color-highlight-lg: oklch(47.72% 0.011 286);
--spacing: 0.25rem;
--leading-condensed: normal;
}
html,
body {
font-family: var(--family-sans);
color-scheme: dark;
color: var(--color-text);
background-color: var(--color-surface);
min-height: 100vh;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 600;
}
h1 {
font-size: clamp(42px, 10vw, 64px);
}
h2 {
font-size: clamp(30px, 6vw, 36px);
}
h3 {
font-size: 1.25rem;
}
input:not(.search) {
color: var(--color-text);
padding-inline: calc(var(--spacing) * 4);
padding-block: calc(var(--spacing) * 2);
border-radius: calc(var(--spacing) * 1.5);
width: 100%;
background-color: var(--color-surface);
border: 1px solid color-mix(in srgb, var(--color-highlight) 70%, #0000);
transition-property: color, border, background-color;
transition-duration: 300ms;
transition-timing-function: cubic-bezier(0.45, 0, 0.55, 1);
overflow: hidden;
&::placeholder {
font-style: italic;
color: var(--color-highlight);
}
&:focus-visible {
outline: none;
}
&[type="file"] {
padding: 0;
cursor: pointer;
&::file-selector-button {
border: 0px;
padding: calc(var(--spacing) * 2);
margin-right: var(--spacing);
background-color: var(--color-highlight);
color: var(--color-subtle);
cursor: pointer;
}
}
}
}
@layer utilities {
.flex {
display: flex;
}
.hidden {
display: none;
}
.leading-condensed {
line-height: var(--leading-condensed);
}
.text-error {
color: var(--color-error);
}
.text-success {
color: var(--color-success);
}
}

148
src/styles/card.css Normal file
View File

@@ -0,0 +1,148 @@
/* All css related to the card and category stuff */
@layer components {
.link-grid > :is(a, div) {
display: flex;
flex-direction: row;
border-radius: calc(var(--spacing) * 4);
padding: calc(var(--spacing) * 2.5);
align-items: center;
transition-property: box-shadow, transform, translate;
transition-duration: 150ms;
transition-timing-function: cubic-bezier(0.45, 0, 0.55, 1);
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1),
0 2px 4px -2px rgb(0 0 0 / 0.1);
contain: layout style paint;
&:not(:is(div)) {
&:hover {
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1),
0 4px 6px -4px rgb(0 0 0 / 0.1);
transform: translateY(-4px);
}
&:active {
box-shadow: 0 2px 4px -2px rgb(0 0 0 / 0.1);
transform: translateY(2px);
}
}
&:not(.new-link-card) {
text-decoration: none;
background: var(--color-overlay);
}
}
@media (prefers-reduced-motion: reduce) {
.link-grid > :is(a, div) {
transition: none;
&:hover {
transform: none;
}
&:active {
transform: none;
}
}
}
/* Div that holds the image */
.link-grid > :is(a, div) > div:first-child {
position: relative;
flex-shrink: 0;
margin-right: calc(var(--spacing) * 2);
border-radius: calc(var(--spacing) * 2.5);
overflow: hidden;
}
.link-grid > :is(a, div) > div:first-child img {
user-select: none;
aspect-ratio: 1/1;
object-fit: cover;
}
/* Div that holds the text */
.link-grid > :is(a, div) > div:nth-child(2) {
display: flex;
flex-grow: 1;
flex-direction: column;
row-gap: 1px;
overflow: hidden;
word-break: break-all;
}
.link-grid > :is(a, div) > div:nth-child(2) h3 {
border: 1px solid transparent;
}
.link-grid > :is(a, div) > div:nth-child(2) p {
color: var(--color-subtle);
white-space: pre-wrap;
border: 1px solid #0000;
min-height: calc(1em + 0.5rem);
border: 1px solid transparent;
min-height: 26px;
}
.category-header {
display: flex;
align-items: center;
}
.category-header > div:first-child {
display: flex;
flex-shrink: 0;
position: relative;
margin-right: calc(var(--spacing) * 2);
align-items: center;
justify-content: center;
width: calc(var(--spacing) * 8);
height: calc(var(--spacing) * 8);
border-radius: calc(var(--spacing) * 1.5);
overflow: hidden;
}
.categoy-header > div:first-child img {
user-select: none;
object-fit: cover;
aspect-ratio: 1/1;
}
.category-header h2 {
text-transform: capitalize;
word-break: break-all;
border-width: 1px;
border-color: #0000;
}
.link-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(min(330px, 100%), 1fr));
gap: calc(var(--spacing) * 2);
padding: calc(var(--spacing) * 2.5);
contain: layout style paint;
}
/* Empty state */
.link-grid > p {
color: var(--color-subtle);
}
.card-section {
display: flex;
justify-content: center;
width: 100%;
}
.card-section > div {
width: 100%;
padding: calc(var(--spacing) * 2.5);
}
@media (min-width: 640px) {
.card-section > div {
width: 80%;
}
}
}

58
src/styles/login.css Normal file
View File

@@ -0,0 +1,58 @@
@import "./base.css";
@layer base {
html,
body {
background-color: var(--color-base);
}
body {
display: flex;
justify-content: center;
align-items: center;
}
}
@layer components {
.login-container {
width: fit-content;
display: flex;
position: relative;
background-color: var(--color-surface);
border-radius: calc(var(--spacing) * 3);
overflow: hidden;
}
.login-container > img {
height: calc(var(--spacing) * 96);
width: calc(var(--spacing) * 64);
object-fit: cover;
}
.login-container > div {
display: flex;
flex-direction: column;
padding: calc(var(--spacing) * 4);
text-align: center;
}
.login-form {
display: flex;
flex-direction: column;
row-gap: calc(var(--spacing) * 3);
margin-top: calc(var(--spacing) * 2);
margin-bottom: calc(var(--spacing) * 2);
}
.login-form button {
padding-left: calc(var(--spacing) * 4);
padding-right: calc(var(--spacing) * 4);
padding-top: calc(var(--spacing) * 2);
padding-bottom: calc(var(--spacing) * 2);
border-radius: calc(var(--spacing) * 2.5);
background-color: var(--color-accent);
color: #fff;
}
}

133
src/styles/main.css Normal file
View File

@@ -0,0 +1,133 @@
@import "./base.css";
@import "./card.css";
@layer components {
.hero {
/* grid grid-rows-3 grid-cols-[1fr] justify-center items-center h-screen bg-base */
display: grid;
grid-template: repeat(3, minmax(0, 1fr)) / 1fr;
justify-content: center;
align-items: center;
height: 100vh;
background-color: var(--color-base);
}
.glance-container {
display: flex;
color: var(--color-subtle);
height: 100%;
padding: calc(var(--spacing) * 2.5);
justify-content: space-between;
}
.primary-hero-container {
display: flex;
flex-direction: column;
align-items: center;
grid-row-start: 2;
padding-left: calc(var(--spacing) * 3);
padding-right: calc(var(--spacing) * 3);
width: 100%;
}
.primary-hero-container > div {
display: flex;
align-items: center;
margin-bottom: calc(var(--spacing) * 2.5);
& > svg {
margin-right: calc(var(--spacing) * 3);
aspect-ratio: 1/1;
width: clamp(42px, 10vw, 60px);
}
}
.primary-hero-container > form {
width: 100%;
max-width: 48rem;
& > input {
color: #fff;
width: 100%;
background-color: var(--color-surface);
border: 1px solid
color-mix(in srgb, var(--color-highlight-sm) 70%, #0000);
padding-left: calc(var(--spacing) * 3);
padding-right: calc(var(--spacing) * 3);
padding-top: var(--spacing);
padding-bottom: var(--spacing);
height: calc(var(--spacing) * 7);
border-radius: 9999px;
&::placeholder {
font-style: italic;
color: var(--color-highlight);
opacity: 1;
}
}
}
.weather-data {
display: flex;
height: fit-content;
align-items: center;
font-weight: 600;
}
.weather-data span {
margin-right: calc(var(--spacing) * 2);
}
.uptime-data {
display: flex;
flex-direction: column;
align-items: end;
& > div {
display: flex;
align-items: center;
& > span {
margin-right: calc(var(--spacing) * 2);
line-height: var(--leading-condensed);
}
}
}
.uptime-status {
position: relative;
display: flex;
margin-top: auto;
margin-bottom: auto;
width: calc(var(--spacing) * 2);
height: calc(var(--spacing) * 2);
}
.uptime-status > svg {
position: relative;
display: inline-flex;
height: 100%;
width: 100%;
fill: currentColor;
}
.uptime-status > svg:nth-child(1) {
position: absolute;
animation: ping 1s linear infinite;
opacity: 0.8;
}
}
@layer utilities {
.animate-ping {
animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite;
}
@keyframes ping {
75%,
100% {
transform: scale(2);
opacity: 0;
}
}
}

View File

@@ -1,195 +0,0 @@
@import "tailwindcss";
@theme {
--color-accent: oklch(57.93% 0.258 294.12);
--color-success: oklch(70.19% 0.158 160.44);
--color-error: oklch(53% 0.251 28.48);
--color-base: oklch(11% 0.007 285);
--color-surface: oklch(19% 0.007 285.66);
--color-overlay: oklch(26% 0.008 285.66);
--color-muted: oklch(63% 0.015 286);
--color-subtle: oklch(72% 0.015 286);
--color-text: oklch(87% 0.015 286);
--color-highlight-sm: oklch(30.67% 0.007 286);
--color-highlight: oklch(39.26% 0.01 286);
--color-highlight-lg: oklch(47.72% 0.011 286);
}
@font-face {
font-family: "Instrument Sans";
src: url("/assets/fonts/InstrumentSans-VariableFont_wdth,wght.woff2")
format("woff2");
font-display: swap;
}
:root {
--default-font-family: "Instrument Sans", ui-sans-serif, system-ui,
sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol",
"Noto Color Emoji";
}
html {
line-height: normal;
color-scheme: dark;
color: var(--color-text);
}
@layer base {
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 600;
}
h1 {
font-size: clamp(42px, 10vw, 64px);
}
h2 {
font-size: clamp(30px, 6vw, 36px);
}
h3 {
font-size: 1.25rem;
}
}
button {
cursor: pointer;
}
input:not(.search) {
@apply px-4 py-2 rounded-md w-full bg-surface border border-highlight/70 placeholder:text-highlight text-text focus-visible:outline-none transition-colors duration-300 ease-out overflow-hidden;
&[type="file"] {
@apply p-0 cursor-pointer;
&::file-selector-button {
@apply px-2 py-2 mr-1 bg-highlight text-subtle cursor-pointer;
}
}
}
.link-card {
background: var(--color-overlay);
display: flex;
flex-direction: row;
text-decoration: none;
border-radius: 1rem;
padding: 0.625rem;
align-items: center;
transition-property: box-shadow, transform, translate;
transition-duration: 150ms;
transition-timing-function: cubic-bezier(0.45, 0, 0.55, 1);
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
contain: layout style paint;
&:not(.admin) {
&:hover {
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1),
0 4px 6px -4px rgb(0 0 0 / 0.1);
transform: translateY(-4px);
}
&:active {
box-shadow: 0 2px 4px -2px rgb(0 0 0 / 0.1);
transform: translateY(2px);
}
}
}
@media (prefers-reduced-motion: reduce) {
.link-card {
transition: none;
&:hover {
transform: none;
}
&:active {
transform: none;
}
}
}
/* Div that holds the image */
.link-card div[data-img-container] {
flex-shrink: 0;
padding-right: 0.5rem;
}
.link-card div[data-img-container] img {
user-select: none;
border-radius: 0.375rem;
aspect-ratio: 1/1;
object-fit: cover;
}
/* Div that holds the text */
.link-card div[data-text-container] {
display: flex;
flex-grow: 1;
flex-direction: column;
row-gap: 1px;
overflow: hidden;
word-break: break-all;
}
.link-card div[data-text-container] p {
color: var(--color-subtle);
white-space: pre-wrap;
border: 1px solid #0000;
min-height: 22px;
}
.new-link-card {
display: flex;
flex-direction: row;
align-items: center;
padding: 0.625rem;
border: 0.125rem dashed var(--color-subtle);
border-radius: 1rem;
transition: box-shadow, transofrm 150ms cubic-bezier(0.45, 0, 0.55, 1);
cursor: pointer;
user-select: none;
&:hover {
text-decoration: underline;
}
}
.categoy-header {
display: flex;
align-items: center;
}
.category-header div[data-img-container] {
@apply shrink-0 relative mr-2 h-full flex items-center justify-center size-8;
}
.categoy-header div[data-img-container] img {
user-select: none;
object-fit: cover;
aspect-ratio: 1/1;
}
.category-header h2 {
text-transform: capitalize;
word-break: break-all;
border-width: 1px;
border-color: #0000;
}
.link-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(min(330px, 100%), 1fr));
gap: 0.5rem;
padding: 0.625rem;
contain: layout style paint;
}