bars guud

This commit is contained in:
Michael Freno
2025-12-18 22:55:03 -05:00
parent bb11775d82
commit 84bcd554e5
7 changed files with 173 additions and 115 deletions

View File

@@ -449,7 +449,7 @@ input[type="checkbox"]:checked::before {
visibility: hidden; visibility: hidden;
min-width: fit-content; min-width: fit-content;
background-color: var(--color-mantle); background-color: var(--color-mantle);
color: #fff; color: var(--color-text);
text-align: center; text-align: center;
padding: 5px 0; padding: 5px 0;
border-radius: 6px; border-radius: 6px;
@@ -548,3 +548,41 @@ input[type="checkbox"]:checked::before {
.shaker:hover { .shaker:hover {
animation: shaker 0.5s ease; animation: shaker 0.5s ease;
} }
.prose {
--tw-prose-body: var(--color-text);
--tw-prose-headings: var(--color-text);
--tw-prose-lead: var(--color-text);
--tw-prose-links: var(--color-blue);
--tw-prose-bold: var(--color-text);
--tw-prose-counters: var(--color-subtext1);
--tw-prose-bullets: var(--color-subtext1);
--tw-prose-hr: var(--color-surface2);
--tw-prose-quotes: var(--color-text);
--tw-prose-quote-borders: var(--color-surface2);
--tw-prose-captions: var(--color-subtext1);
--tw-prose-code: var(--color-text);
--tw-prose-pre-code: var(--color-text);
--tw-prose-pre-bg: var(--color-surface0);
--tw-prose-th-borders: var(--color-surface2);
--tw-prose-td-borders: var(--color-surface1);
}
.prose-invert {
--tw-prose-body: var(--color-text);
--tw-prose-headings: var(--color-text);
--tw-prose-lead: var(--color-text);
--tw-prose-links: var(--color-blue);
--tw-prose-bold: var(--color-text);
--tw-prose-counters: var(--color-subtext1);
--tw-prose-bullets: var(--color-subtext1);
--tw-prose-hr: var(--color-surface2);
--tw-prose-quotes: var(--color-text);
--tw-prose-quote-borders: var(--color-surface2);
--tw-prose-captions: var(--color-subtext1);
--tw-prose-code: var(--color-text);
--tw-prose-pre-code: var(--color-text);
--tw-prose-pre-bg: var(--color-surface0);
--tw-prose-th-borders: var(--color-surface2);
--tw-prose-td-borders: var(--color-surface1);
}

View File

@@ -42,12 +42,8 @@ export function RightBarContent() {
}; };
return ( return (
<div class="text-text flex h-full flex-col justify-between py-6"> <div class="text-text flex h-full flex-col justify-between">
<Typewriter keepAlive={false} class="z-50 px-4 pt-4"> <Typewriter keepAlive={false} class="z-50 px-4">
<div class="flex flex-col gap-6">
<h3 class="text-subtext0 rule-around text-lg font-semibold">
Connect
</h3>
<ul class="flex flex-col gap-4"> <ul class="flex flex-col gap-4">
<li class="hover:text-subtext0 w-fit transition-transform duration-200 ease-in-out hover:-translate-y-0.5 hover:scale-110 hover:font-bold"> <li class="hover:text-subtext0 w-fit transition-transform duration-200 ease-in-out hover:-translate-y-0.5 hover:scale-110 hover:font-bold">
<a href="/contact">Contact Me</a> <a href="/contact">Contact Me</a>
@@ -60,7 +56,7 @@ export function RightBarContent() {
class="hover:text-subtext0 flex items-center gap-3 transition-transform duration-200 ease-in-out hover:-translate-y-0.5 hover:scale-105" class="hover:text-subtext0 flex items-center gap-3 transition-transform duration-200 ease-in-out hover:-translate-y-0.5 hover:scale-105"
> >
<span class="shaker rounded-full p-2"> <span class="shaker rounded-full p-2">
<GitHub height={24} width={24} fill={undefined} /> <GitHub height={24} width={24} fill={`var(--color-text)`} />
</span> </span>
<span>GitHub</span> <span>GitHub</span>
</a> </a>
@@ -98,10 +94,9 @@ export function RightBarContent() {
</a> </a>
</li> </li>
</ul> </ul>
</div>
</Typewriter> </Typewriter>
{/* Dark Mode Toggle */} {/* Dark Mode Toggle */}
<div class="border-overlay0 border-t px-4 pt-6"> <div class="border-overlay0 border-t p-4">
<button <button
onClick={toggleDarkMode} onClick={toggleDarkMode}
class="hover:bg-surface0 flex w-full items-center gap-3 rounded-lg p-3 transition-all duration-200 ease-in-out hover:scale-105" class="hover:bg-surface0 flex w-full items-center gap-3 rounded-lg p-3 transition-all duration-200 ease-in-out hover:scale-105"
@@ -128,7 +123,8 @@ export function RightBarContent() {
} }
export function LeftBar() { export function LeftBar() {
const { setLeftBarSize, leftBarVisible, setLeftBarVisible } = useBars(); const { setLeftBarSize, leftBarSize, leftBarVisible, setLeftBarVisible } =
useBars();
let ref: HTMLDivElement | undefined; let ref: HTMLDivElement | undefined;
let actualWidth = 0; let actualWidth = 0;
let touchStartX = 0; let touchStartX = 0;
@@ -268,7 +264,8 @@ export function LeftBar() {
style={{ style={{
"transition-timing-function": leftBarVisible() "transition-timing-function": leftBarVisible()
? "cubic-bezier(0.34, 1.56, 0.64, 1)" // Bounce out when revealing ? "cubic-bezier(0.34, 1.56, 0.64, 1)" // Bounce out when revealing
: "cubic-bezier(0.4, 0, 0.2, 1)" // Smooth when hiding : "cubic-bezier(0.4, 0, 0.2, 1)", // Smooth when hiding
"min-width": leftBarSize() > 0 ? `${leftBarSize()}px` : undefined
}} }}
> >
{/* Hamburger menu button - positioned at right edge of navbar */} {/* Hamburger menu button - positioned at right edge of navbar */}
@@ -346,8 +343,7 @@ export function LeftBar() {
{/* Navigation Links */} {/* Navigation Links */}
<div class="mt-auto"> <div class="mt-auto">
<Typewriter keepAlive={false}> <Typewriter keepAlive={false}>
<div class="flex flex-col gap-4 py-6"> <ul class="flex flex-row gap-4 py-6 md:flex-col">
<ul class="gap-4">
<li class="hover:text-subtext0 w-fit transition-transform duration-200 ease-in-out hover:-translate-y-0.5 hover:scale-110 hover:font-bold"> <li class="hover:text-subtext0 w-fit transition-transform duration-200 ease-in-out hover:-translate-y-0.5 hover:scale-110 hover:font-bold">
<a href="/">Home</a> <a href="/">Home</a>
</li> </li>
@@ -358,7 +354,6 @@ export function LeftBar() {
<a href="/login">Login</a> <a href="/login">Login</a>
</li> </li>
</ul> </ul>
</div>
</Typewriter> </Typewriter>
{/* RightBar content on mobile */} {/* RightBar content on mobile */}
@@ -373,7 +368,7 @@ export function LeftBar() {
} }
export function RightBar() { export function RightBar() {
const { setRightBarSize, rightBarVisible } = useBars(); const { setRightBarSize, rightBarSize, rightBarVisible } = useBars();
let ref: HTMLDivElement | undefined; let ref: HTMLDivElement | undefined;
let actualWidth = 0; let actualWidth = 0;
@@ -415,7 +410,8 @@ export function RightBar() {
style={{ style={{
"transition-timing-function": rightBarVisible() "transition-timing-function": rightBarVisible()
? "cubic-bezier(0.34, 1.56, 0.64, 1)" ? "cubic-bezier(0.34, 1.56, 0.64, 1)"
: "cubic-bezier(0.4, 0, 0.2, 1)" : "cubic-bezier(0.4, 0, 0.2, 1)",
"min-width": rightBarSize() > 0 ? `${rightBarSize()}px` : undefined
}} }}
> >
<RightBarContent /> <RightBarContent />

View File

@@ -118,7 +118,7 @@ export default function PostBodyClient(props: PostBodyClientProps) {
<div class="mx-auto max-w-4xl px-4 pt-32 md:pt-40"> <div class="mx-auto max-w-4xl px-4 pt-32 md:pt-40">
<div <div
ref={contentRef} ref={contentRef}
class="prose dark:prose-invert max-w-none" class="text-text prose dark:prose-invert max-w-none"
innerHTML={props.body} innerHTML={props.body}
/> />
</div> </div>

View File

@@ -36,19 +36,22 @@ export default function SessionDependantLike(props: SessionDependantLikeProps) {
if (initialHasLiked) { if (initialHasLiked) {
const result = await api.database.removePostLike.mutate({ const result = await api.database.removePostLike.mutate({
user_id: props.currentUserID, user_id: props.currentUserID,
post_id: props.projectID.toString(), post_id: props.projectID.toString()
}); });
setLikes(result.newLikes as PostLike[]); setLikes(result.newLikes as PostLike[]);
} else { } else {
const result = await api.database.addPostLike.mutate({ const result = await api.database.addPostLike.mutate({
user_id: props.currentUserID, user_id: props.currentUserID,
post_id: props.projectID.toString(), post_id: props.projectID.toString()
}); });
setLikes(result.newLikes as PostLike[]); setLikes(result.newLikes as PostLike[]);
} }
setInstantOffset(0); setInstantOffset(0);
} catch (error) { } catch (error) {
console.error("There has been a problem with your like operation:", error); console.error(
"There has been a problem with your like operation:",
error
);
setHasLiked(initialHasLiked); setHasLiked(initialHasLiked);
setInstantOffset(0); setInstantOffset(0);
} }
@@ -56,18 +59,6 @@ export default function SessionDependantLike(props: SessionDependantLikeProps) {
const likeCount = () => likes().length + instantOffset(); const likeCount = () => likes().length + instantOffset();
const getLikeIconColor = () => {
if (hasLiked()) {
return "fill-orange-400";
}
if (hovering()) {
return "fill-orange-400 dark:fill-orange-500";
}
return "fill-black dark:fill-white";
};
return ( return (
<Show <Show
when={props.privilegeLevel !== "anonymous"} when={props.privilegeLevel !== "anonymous"}
@@ -76,12 +67,12 @@ export default function SessionDependantLike(props: SessionDependantLikeProps) {
<div class="mx-auto"> <div class="mx-auto">
<LikeIcon <LikeIcon
strokeWidth={1} strokeWidth={1}
color="fill-black dark:fill-white" color="fill-text"
height={32} height={32}
width={32} width={32}
/> />
</div> </div>
<div class="my-auto pl-2 pt-0.5 text-sm text-black dark:text-white"> <div class="my-auto pt-0.5 pl-2 text-sm text-black dark:text-white">
{likes().length} {likes().length === 1 ? "Like" : "Likes"} {likes().length} {likes().length === 1 ? "Like" : "Likes"}
</div> </div>
<div class="tooltip-text -ml-12 w-12">Must be logged in</div> <div class="tooltip-text -ml-12 w-12">Must be logged in</div>
@@ -93,18 +84,18 @@ export default function SessionDependantLike(props: SessionDependantLikeProps) {
onMouseOver={() => setHovering(true)} onMouseOver={() => setHovering(true)}
onMouseLeave={() => setHovering(false)} onMouseLeave={() => setHovering(false)}
> >
<div class="hover:text-orange-400 tooltip flex flex-col text-black dark:text-white"> <div class="tooltip text-text flex flex-col hover:brightness-125">
<div class="mx-auto"> <div class="mx-auto hover:brightness-125">
<LikeIcon <LikeIcon
strokeWidth={1} strokeWidth={1}
color={getLikeIconColor()} color={`fill-blue`}
height={32} height={32}
width={32} width={32}
/> />
</div> </div>
<div <div
class={`${ class={`${
hasLiked() ? "text-orange-400" : "" hasLiked() ? "text-blue" : ""
} mx-auto flex pl-2 transition-colors duration-200 ease-in`} } mx-auto flex pl-2 transition-colors duration-200 ease-in`}
> >
{likeCount()} {likeCount() === 1 ? "Like" : "Likes"} {likeCount()} {likeCount() === 1 ? "Like" : "Likes"}

View File

@@ -9,7 +9,7 @@ export default function CommentIcon(props: {
fill="none" fill="none"
viewBox="0 0 24 24" viewBox="0 0 24 24"
strokeWidth={props.strokeWidth} strokeWidth={props.strokeWidth}
class="fill-black dark:fill-white" class="hover:fill-blue fill-text"
height={props.height} height={props.height}
width={props.width} width={props.width}
> >

View File

@@ -1,4 +1,4 @@
import { Accessor, createContext, useContext } from "solid-js"; import { Accessor, createContext, useContext, createMemo } from "solid-js";
import { createSignal } from "solid-js"; import { createSignal } from "solid-js";
import { hapticFeedback } from "~/lib/client-utils"; import { hapticFeedback } from "~/lib/client-utils";
@@ -38,37 +38,70 @@ export function useBars() {
} }
export function BarsProvider(props: { children: any }) { export function BarsProvider(props: { children: any }) {
const [leftBarSize, setLeftBarSize] = createSignal(0); const [_leftBarNaturalSize, _setLeftBarNaturalSize] = createSignal(0);
const [rightBarSize, setRightBarSize] = createSignal(0); const [_rightBarNaturalSize, _setRightBarNaturalSize] = createSignal(0);
const [syncedBarSize, setSyncedBarSize] = createSignal(0);
const [centerWidth, setCenterWidth] = createSignal(0); const [centerWidth, setCenterWidth] = createSignal(0);
const [leftBarVisible, _setLeftBarVisible] = createSignal(true); const [leftBarVisible, _setLeftBarVisible] = createSignal(true);
const [rightBarVisible, _setRightBarVisible] = createSignal(true); const [rightBarVisible, _setRightBarVisible] = createSignal(true);
const [barsInitialized, setBarsInitialized] = createSignal(false); const [barsInitialized, setBarsInitialized] = createSignal(false);
// Track when both bars have been sized at least once
let leftBarSized = false; let leftBarSized = false;
let rightBarSized = false; let rightBarSized = false;
const wrappedSetLeftBarSize = (size: number) => { const wrappedSetLeftBarSize = (size: number) => {
setLeftBarSize(size); if (!barsInitialized()) {
// Before initialization, capture natural size
_setLeftBarNaturalSize(size);
if (!leftBarSized && size > 0) { if (!leftBarSized && size > 0) {
leftBarSized = true; leftBarSized = true;
if (rightBarSized) { checkAndSync();
setBarsInitialized(true);
} }
} else {
// After initialization, just update the natural size for visibility handling
_setLeftBarNaturalSize(size);
} }
}; };
const wrappedSetRightBarSize = (size: number) => { const wrappedSetRightBarSize = (size: number) => {
setRightBarSize(size); if (!barsInitialized()) {
// Before initialization, capture natural size
_setRightBarNaturalSize(size);
if (!rightBarSized && size > 0) { if (!rightBarSized && size > 0) {
rightBarSized = true; rightBarSized = true;
if (leftBarSized) { checkAndSync();
setBarsInitialized(true);
} }
} else {
// After initialization, just update the natural size for visibility handling
_setRightBarNaturalSize(size);
} }
}; };
const checkAndSync = () => {
const isMobile = typeof window !== "undefined" && window.innerWidth < 768;
const bothBarsReady = leftBarSized && (isMobile || rightBarSized);
if (bothBarsReady) {
const maxWidth = Math.max(_leftBarNaturalSize(), _rightBarNaturalSize());
setSyncedBarSize(maxWidth);
setBarsInitialized(true);
}
};
const leftBarSize = createMemo(() => {
// Return 0 if hidden (natural size is 0), otherwise return synced size when initialized
const naturalSize = _leftBarNaturalSize();
if (naturalSize === 0) return 0; // Hidden
return barsInitialized() ? syncedBarSize() : naturalSize;
});
const rightBarSize = createMemo(() => {
// Return 0 if hidden (natural size is 0), otherwise return synced size when initialized
const naturalSize = _rightBarNaturalSize();
if (naturalSize === 0) return 0; // Hidden
return barsInitialized() ? syncedBarSize() : naturalSize;
});
// Wrap visibility setters with haptic feedback // Wrap visibility setters with haptic feedback
const setLeftBarVisible = (visible: boolean) => { const setLeftBarVisible = (visible: boolean) => {
hapticFeedback(50); hapticFeedback(50);

View File

@@ -179,7 +179,7 @@ export default function PostPage() {
/> />
</div> </div>
<div <div
class="text-shadow absolute top-1/3 z-10 my-auto px-4 text-center tracking-widest text-white brightness-150 select-text" class="text-shadow text-text absolute top-1/3 z-10 my-auto px-4 text-center tracking-widest brightness-150 select-text"
style={{ style={{
"pointer-events": "none", "pointer-events": "none",
width: `${centerWidth()}px`, width: `${centerWidth()}px`,
@@ -223,7 +223,7 @@ export default function PostPage() {
<div class="flex flex-row justify-center pt-4 md:pt-0 md:pr-8"> <div class="flex flex-row justify-center pt-4 md:pt-0 md:pr-8">
<a href="#comments" class="mx-2"> <a href="#comments" class="mx-2">
<div class="tooltip flex flex-col"> <div class="tooltip flex flex-col">
<div class="mx-auto"> <div class="mx-auto hover:brightness-125">
<CommentIcon <CommentIcon
strokeWidth={1} strokeWidth={1}
height={32} height={32}