mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 20:19:49 +02:00
fix: hydration
This commit is contained in:
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>
|
||||||
Reference in new issue
Block a user