fix: hydration

This commit is contained in:
TrèsAbhi committed 2026-01-16 20:13:56 -06:00
1 parent 369ac113fa
commit 47b583821e
5 files changed
+37 -24

No files matched your search

@@ -1,5 +1,5 @@
import { MagnifyingGlassIcon } from "@radix-ui/react-icons"; import { MagnifyingGlassIcon } from "@radix-ui/react-icons";
import { useRef } from "react"; import { useCallback, useEffect, useRef } from "react";
import { useStrings } from "../../hooks/useStrings"; import { useStrings } from "../../hooks/useStrings";
import { Avatars } from "../../stores/avatars"; import { Avatars } from "../../stores/avatars";
import { TextField } from "../TextField"; import { TextField } from "../TextField";
@@ -9,23 +9,29 @@ export function AvatarControls() {
const strings = useStrings(); const strings = useStrings();
const search = useRef<HTMLInputElement>(null); const search = useRef<HTMLInputElement>(null);
const onChange = useCallback(() => {
if (!search.current) return;
const trimmed = search.current.value.trim();
Avatars.mutate((draft) => {
if (trimmed.length === 0) {
draft.search = null;
} else {
draft.search = trimmed;
}
});
}, []);
useEffect(onChange, []);
return ( return (
<div className="avatar-controls"> <div className="avatar-controls">
<TextField <TextField
ref={search} ref={search}
className="search" className="search"
placeholder={strings.avatars.search} placeholder={strings.avatars.search}
onChange={(event) => { onLoad={onChange}
const trimmed = event.target.value.trim();
Avatars.mutate((draft) => {
if (trimmed.length === 0) {
draft.search = null;
} else {
draft.search = trimmed;
}
});
}}
> >
<MagnifyingGlassIcon /> <MagnifyingGlassIcon />
</TextField> </TextField>
@@ -9,6 +9,7 @@
background-color: var(--gray-1); background-color: var(--gray-1);
box-shadow: var(--shadow-interactive), var(--shadow-cavity); box-shadow: var(--shadow-interactive), var(--shadow-cavity);
cursor: text;
font-size: var(--font-size-regular); font-size: var(--font-size-regular);
color: var(--gray-11); color: var(--gray-11);
@@ -26,6 +27,17 @@
box-shadow: var(--shadow-focus); box-shadow: var(--shadow-focus);
} }
&[data-disabled="true"] {
cursor: not-allowed;
background-color: var(--gray-3);
color: var(--gray-9);
input::placeholder {
color: var(--gray-9);
}
}
svg { svg {
width: 1em; width: 1em;
height: 1em; height: 1em;
@@ -37,6 +49,7 @@
background: none; background: none;
border: none; border: none;
cursor: inherit;
font-size: inherit; font-size: inherit;
font-weight: medium; font-weight: medium;
@@ -13,7 +13,7 @@ export interface TextFieldProps extends ComponentProps<"input"> {
} }
export const TextField = forwardRef<HTMLInputElement, TextFieldProps>( export const TextField = forwardRef<HTMLInputElement, TextFieldProps>(
({ children, className, ...props }, ref) => { ({ children, className, disabled, ...props }, ref) => {
const input = useRef<HTMLInputElement>(null); const input = useRef<HTMLInputElement>(null);
useImperativeHandle(ref, () => input.current!, []); useImperativeHandle(ref, () => input.current!, []);
@@ -22,9 +22,10 @@ export const TextField = forwardRef<HTMLInputElement, TextFieldProps>(
<div <div
className={classNames("text-field", className)} className={classNames("text-field", className)}
data-has-icon={children !== undefined} data-has-icon={children !== undefined}
data-disabled={disabled}
> >
{children} {children}
<input ref={input} {...props} /> <input disabled={disabled} ref={input} {...props} />
</div> </div>
); );
} }
@@ -3,7 +3,7 @@ import { AvatarsList } from "../../../components/AvatarsList";
import { Section } from "../../../components/Section"; import { Section } from "../../../components/Section";
import { LocaleProvider } from "../../../hooks/useLocale"; import { LocaleProvider } from "../../../hooks/useLocale";
interface PageProps extends ContentProps { interface PageProps {
locale: string; locale: string;
} }
@@ -15,11 +15,7 @@ export function Page({ locale, ...props }: PageProps) {
); );
} }
interface ContentProps { function Content() {
skeleton?: boolean;
}
function Content({}: ContentProps) {
return ( return (
<> <>
<Section> <Section>
@@ -11,8 +11,5 @@ const { locale } = Astro.props;
<BaseLayout {locale} accent="gold"> <BaseLayout {locale} accent="gold">
<ToolBanner {locale} tool={tools.avatars} slot="pre-app" /> <ToolBanner {locale} tool={tools.avatars} slot="pre-app" />
<Page {locale} client:load />
<Page {locale} client:only="react">
<Page {locale} skeleton slot="fallback" />
</Page>
</BaseLayout> </BaseLayout>