From 9c6aafe940c04c7ac20819bcbf9fcc0c8ed9cc13 Mon Sep 17 00:00:00 2001 From: "a.tolmachev" Date: Thu, 26 Mar 2026 23:56:03 +0300 Subject: [PATCH] fix: render create action bar in page layout --- .../operation-form/operation-form.tsx | 59 +++++++++++++------ apps/ui/src/pages/operation-create/page.tsx | 7 ++- apps/ui/src/styles.css | 12 ++-- 3 files changed, 52 insertions(+), 26 deletions(-) diff --git a/apps/ui/src/features/operation-form/operation-form.tsx b/apps/ui/src/features/operation-form/operation-form.tsx index 35c64cc..9f3ad78 100644 --- a/apps/ui/src/features/operation-form/operation-form.tsx +++ b/apps/ui/src/features/operation-form/operation-form.tsx @@ -2,6 +2,7 @@ import { zodResolver } from "@hookform/resolvers/zod"; import { useMutation } from "@tanstack/react-query"; import { useEffect, useMemo, useRef } from "react"; import { useForm } from "react-hook-form"; +import { createPortal } from "react-dom"; import { useNavigate } from "react-router-dom"; import { createOperation } from "../../entities/operation/api"; @@ -195,7 +196,11 @@ function bytesToBase64(buffer: ArrayBuffer) { return window.btoa(binary); } -export function OperationForm() { +type OperationFormProps = { + actionBarContainerId?: string; +}; + +export function OperationForm({ actionBarContainerId }: OperationFormProps) { const navigate = useNavigate(); const form = useForm({ defaultValues: defaultOperationFormValues, @@ -236,6 +241,9 @@ export function OperationForm() { } }, [activeProtocol]); + const actionBarContainer = + actionBarContainerId === undefined ? null : document.getElementById(actionBarContainerId); + async function handleDescriptorFileChange(file: File | undefined) { if (file === undefined) { return; @@ -339,13 +347,15 @@ export function OperationForm() { } return ( -
{ - creationMutation.mutate(values); - })} - > -
+ <> + { + creationMutation.mutate(values); + })} + > +
@@ -503,17 +513,28 @@ export function OperationForm() { : "Failed to create operation"}
) : null} -
- -
-
- ready to publish later -

{protocolSummary(activeProtocol)}

- -
- + + + {actionBarContainer + ? createPortal( +
+
+ ready to publish later +

{protocolSummary(activeProtocol)}

+
+ +
, + actionBarContainer, + ) + : null} + ); } diff --git a/apps/ui/src/pages/operation-create/page.tsx b/apps/ui/src/pages/operation-create/page.tsx index cbafcd1..d186c6d 100644 --- a/apps/ui/src/pages/operation-create/page.tsx +++ b/apps/ui/src/pages/operation-create/page.tsx @@ -1,5 +1,10 @@ import { OperationForm } from "../../features/operation-form/operation-form"; export function OperationCreatePage() { - return ; + return ( +
+ +
+
+ ); } diff --git a/apps/ui/src/styles.css b/apps/ui/src/styles.css index 0a7f960..a931902 100644 --- a/apps/ui/src/styles.css +++ b/apps/ui/src/styles.css @@ -398,6 +398,7 @@ button { .page-stack, .stack-layout, .builder-stack, +.create-page-layout, .service-grid, .service-method-list { display: grid; @@ -872,9 +873,7 @@ button { align-items: center; justify-content: space-between; gap: 16px; - width: calc(100% + 56px); - margin-left: -28px; - margin-right: -28px; + width: 100%; padding: 12px 28px; border-radius: 0; background: rgba(255, 255, 255, 0.9); @@ -894,6 +893,10 @@ button { font-size: 12.5px; } +.sticky-action-bar-slot { + width: 100%; +} + .field-error { color: #a1422c; font-size: 12px; @@ -1162,9 +1165,6 @@ pre { } .sticky-action-bar { - width: calc(100% + 32px); - margin-left: -16px; - margin-right: -16px; padding-left: 16px; padding-right: 16px; }