Split up HTTP sending logic (#320)

This commit is contained in:
Gregory Schier
2025-12-20 14:10:55 -08:00
committed by GitHub
parent cfbfd66eef
commit 46933059f6
41 changed files with 2708 additions and 732 deletions

View File

@@ -1,19 +1,48 @@
import classNames from 'classnames';
import { atom, useAtom } from 'jotai';
import type { HTMLAttributes, ReactNode } from 'react';
import { useMemo } from 'react';
import { atomWithKVStorage } from '../../lib/atoms/atomWithKVStorage';
import type { BannerProps } from './Banner';
import { Banner } from './Banner';
interface Props extends HTMLAttributes<HTMLDetailsElement> {
summary: ReactNode;
color?: BannerProps['color'];
open?: boolean;
defaultOpen?: boolean;
storageKey?: string;
}
export function DetailsBanner({ className, color, summary, children, ...extraProps }: Props) {
export function DetailsBanner({
className,
color,
summary,
children,
defaultOpen,
storageKey,
...extraProps
}: Props) {
// biome-ignore lint/correctness/useExhaustiveDependencies: We only want to recompute the atom when storageKey changes
const openAtom = useMemo(
() =>
storageKey
? atomWithKVStorage<boolean>(['details_banner', storageKey], defaultOpen ?? false)
: atom(defaultOpen ?? false),
[storageKey],
);
const [isOpen, setIsOpen] = useAtom(openAtom);
const handleToggle = (e: React.SyntheticEvent<HTMLDetailsElement>) => {
if (storageKey) {
setIsOpen(e.currentTarget.open);
}
};
return (
<Banner color={color} className={className}>
<details className="group list-none" {...extraProps}>
<summary className="!cursor-default !select-none list-none flex items-center gap-2 focus:outline-none opacity-70 hover:opacity-100 focus:opacity-100">
<details className="group list-none" open={isOpen} onToggle={handleToggle} {...extraProps}>
<summary className="!cursor-default !select-none list-none flex items-center gap-3 focus:outline-none opacity-70">
<div
className={classNames(
'transition-transform',