Address compliance-portal review feedback

Fix the valid issues raised in the scaffold review.

UI kit: the Button loading state now replaces only the leading icon
instead of dropping the label, Button consumes the `active` variant so
it no longer leaks onto the DOM, and every v2 skeleton sets aria-hidden
after the prop spread so a consumer cannot override it.

@probo/relay: guard the caller-supplied onCompleted/onError callbacks so
a throwing callback still settles the awaitable mutation promise instead
of leaving it pending.

compliance-portal: normalize external website hrefs and read hostname
via URL.hostname, add a localized catch-all not-found route, and widen
the .gitattributes glob so colocated __generated__ artifacts at any depth
are marked generated.

Docs: correct the forms guide (Base UI passes plain values, Zod v3
flatten API), spread the child fragment in the permissions example, and
drop references to v2 components that do not exist in the ui guide.

Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
Émile Ré
2026-06-28 18:40:08 +02:00
parent 4f3d3dc3b3
commit 6bcb7461be
20 changed files with 116 additions and 32 deletions

View File

@@ -24,5 +24,5 @@ export type AvatarSkeletonProps = Omit<ComponentProps<"span">, "children"> & Var
export function AvatarSkeleton(props: AvatarSkeletonProps) {
const { size, radius, className, ...rest } = props;
return <span aria-hidden className={avatarSkeleton({ size, radius, className })} {...rest} />;
return <span className={avatarSkeleton({ size, radius, className })} {...rest} aria-hidden />;
}

View File

@@ -24,5 +24,5 @@ export type BadgeSkeletonProps = Omit<ComponentProps<"span">, "children"> & Vari
export function BadgeSkeleton(props: BadgeSkeletonProps) {
const { size, className, ...rest } = props;
return <span aria-hidden className={badgeSkeleton({ size, className })} {...rest} />;
return <span className={badgeSkeleton({ size, className })} {...rest} aria-hidden />;
}

View File

@@ -32,7 +32,7 @@ export type ButtonProps
// or router link (Link) are separate components. See contrib/claude/ui.md.
export function Button(props: ButtonProps) {
const {
size, variant, color, highContrast, className,
size, variant, color, highContrast, active, className,
iconStart, iconEnd, loading = false, disabled, type = "button", children, ...rest
} = props;
@@ -41,18 +41,12 @@ export function Button(props: ButtonProps) {
type={type}
disabled={disabled || loading}
aria-busy={loading || undefined}
className={button({ size, variant, color, highContrast, className })}
className={button({ size, variant, color, highContrast, active, className })}
{...rest}
>
{loading
? <SpinnerGapIcon className="animate-spin" aria-hidden />
: (
<>
{iconStart}
{children}
{iconEnd}
</>
)}
{loading ? <SpinnerGapIcon className="animate-spin" aria-hidden /> : iconStart}
{children}
{iconEnd}
</button>
);
}

View File

@@ -24,5 +24,5 @@ export type ButtonSkeletonProps = Omit<ComponentProps<"span">, "children"> & Var
export function ButtonSkeleton(props: ButtonSkeletonProps) {
const { size, className, ...rest } = props;
return <span aria-hidden className={buttonSkeleton({ size, className })} {...rest} />;
return <span className={buttonSkeleton({ size, className })} {...rest} aria-hidden />;
}

View File

@@ -23,5 +23,5 @@ export type CalloutSkeletonProps = Omit<ComponentProps<"div">, "children"> & Var
export function CalloutSkeleton(props: CalloutSkeletonProps) {
const { size, className, ...rest } = props;
return <div aria-hidden className={calloutSkeleton({ size, className })} {...rest} />;
return <div className={calloutSkeleton({ size, className })} {...rest} aria-hidden />;
}

View File

@@ -23,5 +23,5 @@ export type CardSkeletonProps = Omit<ComponentProps<"div">, "children"> & Varian
export function CardSkeleton(props: CardSkeletonProps) {
const { size, className, ...rest } = props;
return <div aria-hidden className={cardSkeleton({ size, className })} {...rest} />;
return <div className={cardSkeleton({ size, className })} {...rest} aria-hidden />;
}

View File

@@ -24,5 +24,5 @@ export type IconButtonSkeletonProps = Omit<ComponentProps<"span">, "children"> &
export function IconButtonSkeleton(props: IconButtonSkeletonProps) {
const { size, className, ...rest } = props;
return <span aria-hidden className={iconButtonSkeleton({ size, className })} {...rest} />;
return <span className={iconButtonSkeleton({ size, className })} {...rest} aria-hidden />;
}

View File

@@ -26,7 +26,7 @@ export function HeadingSkeleton(props: HeadingSkeletonProps) {
const { size, className, ...rest } = props;
return (
<span aria-hidden className={headingSkeleton({ size, className })} {...rest}>
<span className={headingSkeleton({ size, className })} {...rest} aria-hidden>
{"\u00A0"}
</span>
);

View File

@@ -26,7 +26,7 @@ export function TextSkeleton(props: TextSkeletonProps) {
const { size, className, ...rest } = props;
return (
<span aria-hidden className={textSkeleton({ size, className })} {...rest}>
<span className={textSkeleton({ size, className })} {...rest} aria-hidden>
{"\u00A0"}
</span>
);