fix: polish kumo dialog and select styling

This commit is contained in:
2026-07-02 09:45:21 -07:00
parent 22e61f5efe
commit 04f2dfc229
4 changed files with 49 additions and 26 deletions

View File

@@ -111,6 +111,17 @@ a,
} }
} }
@keyframes dialog-panel-enter {
from {
opacity: 0;
transform: translate(-50%, -48%) scale(0.97);
}
to {
opacity: 1;
transform: translate(-50%, -50%) scale(1);
}
}
.page-enter { .page-enter {
animation: page-enter 180ms ease-out both; animation: page-enter 180ms ease-out both;
} }
@@ -119,6 +130,14 @@ a,
animation: page-enter 160ms ease-out both; animation: page-enter 160ms ease-out both;
} }
.dialog-panel-enter {
animation: dialog-panel-enter 160ms ease-out both;
}
:where([role="presentation"].fixed.inset-0.bg-kumo-recessed) {
z-index: 40;
}
.loading-progress { .loading-progress {
width: 55%; width: 55%;
animation: loading-progress 900ms ease-in-out infinite; animation: loading-progress 900ms ease-in-out infinite;
@@ -127,6 +146,7 @@ a,
@media (prefers-reduced-motion: reduce) { @media (prefers-reduced-motion: reduce) {
.page-enter, .page-enter,
.table-row-enter, .table-row-enter,
.dialog-panel-enter,
.loading-progress { .loading-progress {
animation: none; animation: none;
} }

View File

@@ -17,6 +17,9 @@ type DialogProps = {
className?: string; className?: string;
}; };
const kumoBackdropClassNames =
"fixed inset-0 bg-kumo-recessed opacity-80 transition-all duration-150 data-ending-style:opacity-0 data-starting-style:opacity-0";
export function Dialog({ export function Dialog({
open, open,
title, title,
@@ -37,14 +40,16 @@ export function Dialog({
> >
<KumoDialog <KumoDialog
className={cn( className={cn(
"flex max-h-[92svh] w-[min(calc(100vw-1.5rem),48rem)] flex-col overflow-hidden rounded-lg border border-kumo-line bg-kumo-base p-0 shadow-xl", "dialog-panel-enter fixed left-1/2 top-1/2 z-50 flex max-h-[min(92svh,52rem)] w-[min(calc(100vw-1.5rem),48rem)] -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-lg border border-kumo-line bg-kumo-base p-0 shadow-xl outline-none ring-1 ring-kumo-line",
"data-ending-style:scale-95 data-ending-style:opacity-0 data-starting-style:scale-95 data-starting-style:opacity-0",
className, className,
)} )}
data-kumo-backdrop-classes={kumoBackdropClassNames}
size="xl" size="xl"
> >
<header className="flex shrink-0 items-start justify-between gap-4 border-b border-kumo-line p-5"> <header className="flex shrink-0 items-start justify-between gap-4 border-b border-kumo-line bg-kumo-base p-5">
<div className="min-w-0"> <div className="min-w-0">
<KumoDialog.Title>{title}</KumoDialog.Title> <KumoDialog.Title className="text-lg font-semibold leading-7 text-kumo-strong">{title}</KumoDialog.Title>
{description ? <KumoDialog.Description className="mt-1">{description}</KumoDialog.Description> : null} {description ? <KumoDialog.Description className="mt-1">{description}</KumoDialog.Description> : null}
</div> </div>
<Button aria-label="关闭弹窗" onClick={onClose} size="icon" type="button" variant="outline"> <Button aria-label="关闭弹窗" onClick={onClose} size="icon" type="button" variant="outline">

View File

@@ -36,7 +36,14 @@ export function Select({
}: SelectProps): React.ReactElement { }: SelectProps): React.ReactElement {
return ( return (
<KumoSelect<string> <KumoSelect<string>
className={cn("w-full", className)} className={cn(
"min-h-10 w-full rounded-md border border-input bg-card px-3 py-2 text-left text-sm font-medium text-foreground shadow-sm",
"transition-colors hover:border-primary/45 hover:bg-secondary/35",
"focus-visible:border-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/25",
"disabled:cursor-not-allowed disabled:opacity-50",
"[&_[data-placeholder]]:text-muted-foreground [&_svg]:text-primary",
className,
)}
defaultValue={defaultValue} defaultValue={defaultValue}
onValueChange={(nextValue) => onValueChange?.(String(nextValue))} onValueChange={(nextValue) => onValueChange?.(String(nextValue))}
placeholder={placeholder} placeholder={placeholder}

View File

@@ -72,8 +72,8 @@ export function OrganizationManagementClient(): React.ReactElement {
title="新增机构" title="新增机构"
> >
<form className="grid gap-4" onSubmit={handleSubmit}> <form className="grid gap-4" onSubmit={handleSubmit}>
<Input name="name" placeholder="机构名称" required /> <Input label="机构名称" name="name" placeholder="机构名称" required />
<Input name="slug" placeholder="机构标识,可留空" /> <Input label="机构标识" name="slug" placeholder="可留空" />
{message ? ( {message ? (
<p className="rounded-md bg-secondary px-3 py-2 text-sm text-secondary-foreground" role="status"> <p className="rounded-md bg-secondary px-3 py-2 text-sm text-secondary-foreground" role="status">
{message} {message}
@@ -195,26 +195,17 @@ export function OrganizationRowActions({
title="编辑机构" title="编辑机构"
> >
<form className="grid gap-4" onSubmit={handleSubmit}> <form className="grid gap-4" onSubmit={handleSubmit}>
<label className="grid gap-2 text-sm"> <Input defaultValue={organization.name} label="机构名称" name="name" required />
<span className="font-medium"></span> <Input defaultValue={organization.slug} label="机构标识" name="slug" required />
<Input defaultValue={organization.name} name="name" required /> <Select
</label> defaultValue={organization.status}
<label className="grid gap-2 text-sm"> label="状态"
<span className="font-medium"></span> name="status"
<Input defaultValue={organization.slug} name="slug" required /> options={[
</label> { value: "active", label: "启用" },
<label className="grid gap-2 text-sm"> { value: "disabled", label: "停用" },
<span className="font-medium"></span> ]}
<Select />
aria-label="机构状态"
defaultValue={organization.status}
name="status"
options={[
{ value: "active", label: "启用" },
{ value: "disabled", label: "停用" },
]}
/>
</label>
{message ? ( {message ? (
<p className="rounded-md bg-secondary px-3 py-2 text-sm text-secondary-foreground" role="status"> <p className="rounded-md bg-secondary px-3 py-2 text-sm text-secondary-foreground" role="status">
{message} {message}