fix(ui): make key detail panel scroll so the edit form Save button stays reachable

The key detail/edit panel wraps its content in a div meant to be the
internal scroll container (overflow-y-auto) but sizes it with h-full.
h-full only resolves when every ancestor has a definite height, and the
chain breaks: a Tremor Grid and Col with no height sit between this div
and the only fixed height in the tree (h-[75vh] in user_dashboard). So
h-full collapses to auto, the panel grows to fit content and never
scrolls internally, and reaching "Save Changes" falls back to the whole
window scrolling. In any constrained-height shell that window scroll
isn't available, so a long edit form's footer is cut off and the user
cannot save from the UI.

Add max-h-[85vh] to the container. A viewport-relative max-height always
resolves regardless of ancestor heights, so the panel becomes a real
bounded scroll container and the Save button is always reachable. The
fix lives on the KeyInfoView component, so it covers every caller (keys
page, team keys, usage, logs) without touching the shared dashboard
layout or the table view.
This commit is contained in:
ryan-crabbe-berri 2026-06-19 12:46:33 -07:00
parent 4847fa5dd5
commit db1ea2d588
2 changed files with 19 additions and 1 deletions

View file

@ -163,6 +163,24 @@ describe("KeyInfoView", () => {
});
});
it("bounds the detail panel scroll container to the viewport so edit form actions stay reachable", async () => {
vi.mocked(useAuthorized).mockReturnValue(baseUseAuthorizedMock);
const { container } = renderWithProviders(
<KeyInfoView
keyData={MOCK_KEY_DATA}
onClose={() => {}}
keyId={"test-key-id"}
onKeyDataUpdate={() => {}}
teams={[]}
/>,
);
const scrollContainer = container.querySelector(".overflow-y-auto");
expect(scrollContainer).not.toBeNull();
expect(scrollContainer!.className).toContain("max-h-[85vh]");
});
it("should not render tags in metadata textarea", async () => {
vi.mocked(useAuthorized).mockReturnValue(baseUseAuthorizedMock);

View file

@ -412,7 +412,7 @@ export default function KeyInfoView({
};
return (
<div className="w-full h-full overflow-y-auto p-4">
<div className="w-full h-full max-h-[85vh] overflow-y-auto p-4">
<KeyInfoHeader
data={{
keyName: currentKeyData.key_alias || "Virtual Key",