loading indicator for editor

This commit is contained in:
shrt 2025-03-08 20:30:47 +01:00
parent 47a79cd171
commit bccd089c7f
2 changed files with 99 additions and 71 deletions

View File

@ -117,85 +117,97 @@ export default ({ server_article }: { server_article: Article }) => {
/> />
<div <div
className={cn( className={cn(
"sticky top-4 h-max w-full max-w-md space-y-4 rounded-md border-t-2 bg-muted p-4", "sticky top-4 h-max w-full max-w-md",
loading && "border-t-blue-600", // loading && "border-t-blue-600",
)} )}
> >
<div className="flex w-full items-center justify-between"> <div className="relative w-full space-y-4 overflow-hidden rounded-md border-t-2 bg-muted p-4">
<div className="flex items-center gap-2"> <div
<Badge variant={"outline"} className="flex items-center gap-1"> className={cn(
{!form.formState.isDirty && !loading ? ( "saving absolute left-0 right-0 top-0 h-0.5 rounded-full bg-primary",
<> !loading && "hidden",
<CheckCircle className="size-4 text-emerald-600" /> )}
<span>Gespeichert</span> />
</>
) : ( <div className="flex w-full items-center justify-between">
<> <div className="flex items-center gap-2">
<XCircle className="size-4 text-destructive" /> <Badge
<span>Nicht Gespeichert</span> variant={"outline"}
</> className="flex items-center gap-1"
)} >
</Badge> {!form.formState.isDirty && !loading ? (
<span <>
className={cn( <CheckCircle className="size-4 text-emerald-600" />
"text-xs", <span>Gespeichert</span>
published ? "text-emerald-700" : "text-muted-foreground", </>
)} ) : (
<>
<XCircle className="size-4 text-destructive" />
<span>Nicht Gespeichert</span>
</>
)}
</Badge>
<span
className={cn(
"text-xs",
published ? "text-emerald-700" : "text-muted-foreground",
)}
>
{published
? "Veröffentlicht"
: "Draft (nicht veröffentlicht)"}
</span>
</div>
<Link
href={"/editoren-hilfe"}
target="_blank"
className="size-max scale-90 p-0 text-xs text-muted-foreground"
> >
{published <span>? Hilfe</span>
? "Veröffentlicht" </Link>
: "Draft (nicht veröffentlicht)"}
</span>
</div> </div>
<Link <FormField
href={"/editoren-hilfe"} control={form.control}
target="_blank" name="published"
className="size-max scale-90 p-0 text-xs text-muted-foreground" render={({ field }) => (
> <FormItem className="rounded-md border bg-background px-4 py-2">
<span>? Hilfe</span> <FormControl>
</Link> <div className="flex items-center gap-2">
</div> <Label>Veröffentlicht </Label>
<FormField <PublishArticleAlertDialog
control={form.control} published={field.value}
name="published" setPublished={(value) => {
render={({ field }) => ( field.onChange(value);
<FormItem className="rounded-md border bg-background px-4 py-2"> form.handleSubmit(onSubmit)();
<FormControl> }}
<div className="flex items-center gap-2"> />
<Label>Veröffentlicht </Label> </div>
<PublishArticleAlertDialog </FormControl>
published={field.value}
setPublished={(value) => { <FormMessage />
field.onChange(value); </FormItem>
)}
/>
<FormField
control={form.control}
name="categoryId"
render={({ field }) => (
<FormItem className="w-full">
<FormControl>
<CategorySelect
initialValue={field.value}
onSelect={(categoryId) => {
field.onChange(categoryId);
form.handleSubmit(onSubmit)(); form.handleSubmit(onSubmit)();
}} }}
/> />
</div> </FormControl>
</FormControl>
<FormMessage /> <FormMessage />
</FormItem> </FormItem>
)} )}
/> />
<FormField </div>
control={form.control}
name="categoryId"
render={({ field }) => (
<FormItem className="w-full">
<FormControl>
<CategorySelect
initialValue={field.value}
onSelect={(categoryId) => {
field.onChange(categoryId);
form.handleSubmit(onSubmit)();
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div> </div>
</div> </div>
</form> </form>

View File

@ -86,3 +86,19 @@
width: var(--radix-popover-trigger-width); width: var(--radix-popover-trigger-width);
max-height: var(--radix-popover-content-available-height); max-height: var(--radix-popover-content-available-height);
} }
@keyframes loadingBar {
0% {
transform: scaleX(0);
}
60% {
transform: scaleX(1); /* Slight overshoot for bounce effect */
}
100% {
transform: scaleX(0.2);
}
}
.saving {
animation: loadingBar 0.8s cubic-bezier(0.3, 0.8, 0.4, 1) infinite alternate;
}