fix: render create action bar in page layout

This commit is contained in:
a.tolmachev
2026-03-26 23:56:03 +03:00
parent f0c9e0d14c
commit 9c6aafe940
3 changed files with 52 additions and 26 deletions
@@ -2,6 +2,7 @@ import { zodResolver } from "@hookform/resolvers/zod";
import { useMutation } from "@tanstack/react-query"; import { useMutation } from "@tanstack/react-query";
import { useEffect, useMemo, useRef } from "react"; import { useEffect, useMemo, useRef } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { createPortal } from "react-dom";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { createOperation } from "../../entities/operation/api"; import { createOperation } from "../../entities/operation/api";
@@ -195,7 +196,11 @@ function bytesToBase64(buffer: ArrayBuffer) {
return window.btoa(binary); return window.btoa(binary);
} }
export function OperationForm() { type OperationFormProps = {
actionBarContainerId?: string;
};
export function OperationForm({ actionBarContainerId }: OperationFormProps) {
const navigate = useNavigate(); const navigate = useNavigate();
const form = useForm<OperationFormValues>({ const form = useForm<OperationFormValues>({
defaultValues: defaultOperationFormValues, defaultValues: defaultOperationFormValues,
@@ -236,6 +241,9 @@ export function OperationForm() {
} }
}, [activeProtocol]); }, [activeProtocol]);
const actionBarContainer =
actionBarContainerId === undefined ? null : document.getElementById(actionBarContainerId);
async function handleDescriptorFileChange(file: File | undefined) { async function handleDescriptorFileChange(file: File | undefined) {
if (file === undefined) { if (file === undefined) {
return; return;
@@ -339,8 +347,10 @@ export function OperationForm() {
} }
return ( return (
<>
<form <form
className="builder-stack" className="builder-stack"
id="operation-create-form"
onSubmit={form.handleSubmit((values) => { onSubmit={form.handleSubmit((values) => {
creationMutation.mutate(values); creationMutation.mutate(values);
})} })}
@@ -504,16 +514,27 @@ export function OperationForm() {
</div> </div>
) : null} ) : null}
</div> </div>
</form>
{actionBarContainer
? createPortal(
<div className="sticky-action-bar"> <div className="sticky-action-bar">
<div className="sticky-action-copy"> <div className="sticky-action-copy">
<span className="status-pill status-testing">ready to publish later</span> <span className="status-pill status-testing">ready to publish later</span>
<p>{protocolSummary(activeProtocol)}</p> <p>{protocolSummary(activeProtocol)}</p>
</div> </div>
<button className="button-primary button-primary-strong" type="submit" disabled={creationMutation.isPending}> <button
className="button-primary button-primary-strong"
type="submit"
form="operation-create-form"
disabled={creationMutation.isPending}
>
{creationMutation.isPending ? "Creating..." : "Create operation"} {creationMutation.isPending ? "Creating..." : "Create operation"}
</button> </button>
</div> </div>,
</form> actionBarContainer,
)
: null}
</>
); );
} }
+6 -1
View File
@@ -1,5 +1,10 @@
import { OperationForm } from "../../features/operation-form/operation-form"; import { OperationForm } from "../../features/operation-form/operation-form";
export function OperationCreatePage() { export function OperationCreatePage() {
return <OperationForm />; return (
<div className="create-page-layout">
<OperationForm actionBarContainerId="operation-create-action-bar" />
<div className="sticky-action-bar-slot" id="operation-create-action-bar" />
</div>
);
} }
+6 -6
View File
@@ -398,6 +398,7 @@ button {
.page-stack, .page-stack,
.stack-layout, .stack-layout,
.builder-stack, .builder-stack,
.create-page-layout,
.service-grid, .service-grid,
.service-method-list { .service-method-list {
display: grid; display: grid;
@@ -872,9 +873,7 @@ button {
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
gap: 16px; gap: 16px;
width: calc(100% + 56px); width: 100%;
margin-left: -28px;
margin-right: -28px;
padding: 12px 28px; padding: 12px 28px;
border-radius: 0; border-radius: 0;
background: rgba(255, 255, 255, 0.9); background: rgba(255, 255, 255, 0.9);
@@ -894,6 +893,10 @@ button {
font-size: 12.5px; font-size: 12.5px;
} }
.sticky-action-bar-slot {
width: 100%;
}
.field-error { .field-error {
color: #a1422c; color: #a1422c;
font-size: 12px; font-size: 12px;
@@ -1162,9 +1165,6 @@ pre {
} }
.sticky-action-bar { .sticky-action-bar {
width: calc(100% + 32px);
margin-left: -16px;
margin-right: -16px;
padding-left: 16px; padding-left: 16px;
padding-right: 16px; padding-right: 16px;
} }