From 71664aa4273ca9cf89da69b81e1a1e424d820a7f Mon Sep 17 00:00:00 2001 From: sachin-bruno Date: Mon, 10 Aug 2026 12:45:10 +0530 Subject: [PATCH 1/2] fix(collection-docs):Table of content minor UI improvements (#37) * Table of content style fix * Table of content style fix --- .../src/components/PageWrapper/StyledWrapper.ts | 2 +- .../src/components/SectionNav/SectionNav.tsx | 4 ++-- .../src/components/SectionNav/StyledWrapper.ts | 16 +++++++++++++--- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/packages/bruno-api-docs/src/components/PageWrapper/StyledWrapper.ts b/packages/bruno-api-docs/src/components/PageWrapper/StyledWrapper.ts index 3f25c5e0..7fbe07ab 100644 --- a/packages/bruno-api-docs/src/components/PageWrapper/StyledWrapper.ts +++ b/packages/bruno-api-docs/src/components/PageWrapper/StyledWrapper.ts @@ -3,7 +3,7 @@ import styled from '@emotion/styled'; export const StyledWrapper = styled.div` max-width: 100rem; margin-inline: auto; - padding: 1rem 3rem; + padding: 1rem 5rem; @container docs (max-width: 768px) { padding: 0.9375rem 1.25rem; diff --git a/packages/bruno-api-docs/src/components/SectionNav/SectionNav.tsx b/packages/bruno-api-docs/src/components/SectionNav/SectionNav.tsx index 818119b1..429c3784 100644 --- a/packages/bruno-api-docs/src/components/SectionNav/SectionNav.tsx +++ b/packages/bruno-api-docs/src/components/SectionNav/SectionNav.tsx @@ -32,9 +32,9 @@ const rowIndent = (level: number): string => `${0.5 + Math.min(level, 7) * 0.4}r // The docs column's outer padding collapses at its `@container docs (max-width: 768px)` breakpoint, // leaving no gutter — below it the rail hides rather than overlapping the content. const DOCS_MIN_WIDTH = 768; -// The rail's fixed top (`top: 5rem`) plus a small gap; its height is capped at the docs area's +// The rail's fixed top (`top: 13rem`) plus a small gap; its height is capped at the docs area's // bottom minus this so it clips at, rather than draws over, a bottom-docked playground. -const RAIL_TOP_PX = 88; +const RAIL_TOP_PX = 216; // Below this remaining height the rail hides entirely rather than show a cramped/overlapping sliver. const MIN_RAIL_HEIGHT = 24; diff --git a/packages/bruno-api-docs/src/components/SectionNav/StyledWrapper.ts b/packages/bruno-api-docs/src/components/SectionNav/StyledWrapper.ts index 29aa390d..8cf303fb 100644 --- a/packages/bruno-api-docs/src/components/SectionNav/StyledWrapper.ts +++ b/packages/bruno-api-docs/src/components/SectionNav/StyledWrapper.ts @@ -2,7 +2,7 @@ import styled from '@emotion/styled'; export const StyledWrapper = styled.div` position: fixed; - top: 5rem; + top: 13rem; right: 0; z-index: calc(var(--z-overlay, 50) - 1); font-family: var(--font-sans); @@ -81,7 +81,18 @@ export const StyledWrapper = styled.div` background: var(--bg-primary); border-color: var(--border-color); overflow-y: auto; - transition: background 0.16s ease, border-color 0.16s ease, box-shadow 0.16s ease; + animation: sectionNavOpen 0.3s cubic-bezier(0.22, 1, 0.36, 1); + } + + @keyframes sectionNavOpen { + from { + opacity: 0; + transform: translateX(1.25rem); + } + to { + opacity: 1; + transform: translateX(0); + } } &.section-nav--open .section-nav-item { justify-content: flex-start; @@ -93,7 +104,6 @@ export const StyledWrapper = styled.div` opacity: 1; white-space: normal; overflow-wrap: break-word; - transition: max-width 0.18s ease, max-height 0.18s ease, opacity 0.18s ease; } &.section-nav--open .section-nav-tick-slot { display: none; From d8c7ae6953b5062b7a5bc5c639bbf57a2dce536c Mon Sep 17 00:00:00 2001 From: "Vineet Sharma (vasharma05)" Date: Mon, 10 Aug 2026 12:47:29 +0530 Subject: [PATCH 2/2] fix: Match the response action icons to the Bruno app (BRU-3765) (#31) * Match the Action Icon buttons to that of the app * Increase the response actions expanded width to fix the collapsing width for response actions * Address comments * Remove the unused import --- .../ActionIconButton.spec.tsx | 25 +++++++++++++++++ .../ActionIconButton/ActionIconButton.tsx | 22 +++++++++++++++ .../ActionIconButton/StyledWrapper.ts | 27 +++++++++++++++++++ .../ChangeLayout/ChangeLayout.tsx | 10 +++---- .../ClearResponse/ClearResponse.tsx | 7 ++--- .../CopyResponse/CopyResponse.tsx | 12 ++++++--- .../DownloadResponse/DownloadResponse.tsx | 7 ++--- .../ResponseActions/ResponseActions.tsx | 8 +++--- .../ResponseActions/StyledWrapper.ts | 16 ++++++++--- .../ResponseDuration/ResponseDuration.tsx | 6 ++--- .../ResponseSize/ResponseSize.tsx | 2 +- .../ResponseStatus/ResponseStatus.tsx | 2 +- .../ResponsePane/ResponsePane.tsx | 24 ++++++++--------- .../bruno-api-docs/src/constants/response.ts | 2 +- 14 files changed, 129 insertions(+), 41 deletions(-) create mode 100644 packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/ActionIconButton/ActionIconButton.spec.tsx create mode 100644 packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/ActionIconButton/ActionIconButton.tsx create mode 100644 packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/ActionIconButton/StyledWrapper.ts diff --git a/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/ActionIconButton/ActionIconButton.spec.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/ActionIconButton/ActionIconButton.spec.tsx new file mode 100644 index 00000000..72c93905 --- /dev/null +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/ActionIconButton/ActionIconButton.spec.tsx @@ -0,0 +1,25 @@ +import { describe, it, expect } from 'vitest'; +import ActionIconButton from './ActionIconButton'; +import { useRenderToDom } from '@/hooks/useRenderToDom'; +import { getByTestId, query } from '@/test-utils/dom'; + +describe('ActionIconButton', () => { + it('renders a button with the accessible label and its child glyph', () => { + const root = useRenderToDom( + + + + ); + expect(getByTestId(root, 'glyph')).toBeDefined(); + expect(query(root, 'button').getAttribute('aria-label')).toBe('Toggle sidebar'); + }); + + it('forwards extra props (aria-expanded)', () => { + const root = useRenderToDom( + + + + ); + expect(query(root, 'button').getAttribute('aria-expanded')).toBe('true'); + }); +}); diff --git a/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/ActionIconButton/ActionIconButton.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/ActionIconButton/ActionIconButton.tsx new file mode 100644 index 00000000..eb72f29e --- /dev/null +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/ActionIconButton/ActionIconButton.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import { StyledWrapper } from './StyledWrapper'; +import Tooltip from '@/ui/Tooltip/Tooltip'; + +export interface ActionIconButtonProps extends React.ButtonHTMLAttributes { + /** Accessible label — icon buttons have no visible text. */ + label: string; + /** Show the hover/focus tooltip carrying `label`. Defaults to `true`. */ + showTooltip?: boolean; +} + +const ActionIconButton = React.forwardRef( + ({ label, children, type = 'button', showTooltip = true, ...rest }, ref) => ( + + + {children} + + + ) +); + +export default ActionIconButton; diff --git a/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/ActionIconButton/StyledWrapper.ts b/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/ActionIconButton/StyledWrapper.ts new file mode 100644 index 00000000..075d89bd --- /dev/null +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/ActionIconButton/StyledWrapper.ts @@ -0,0 +1,27 @@ +import styled from '@emotion/styled'; + +export const StyledWrapper = styled.button` + display: inline-flex; + align-items: center; + justify-content: center; + width: 1.5rem; + height: 1.5rem; + padding: 0; + flex: none; + background: transparent; + color: var(--oc-text); + border: none; + border-radius: var(--oc-radius); + cursor: pointer; + transition: background-color 0.12s ease, color 0.12s ease; + + &:hover { + background: var(--oc-background-surface0); + color: var(--oc-text); + } + + &[aria-expanded='true'] { + background: var(--oc-background-surface0); + color: var(--oc-text); + } +`; diff --git a/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/ChangeLayout/ChangeLayout.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/ChangeLayout/ChangeLayout.tsx index 295fe43c..a688b93c 100644 --- a/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/ChangeLayout/ChangeLayout.tsx +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/ChangeLayout/ChangeLayout.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import IconButton from '@/ui/IconButton/IconButton'; +import ActionIconButton from '../ActionIconButton/ActionIconButton'; import { IconLayoutColumns, IconLayoutRows } from '@tabler/icons'; interface ChangeLayoutProps { @@ -9,13 +9,13 @@ interface ChangeLayoutProps { const ChangeLayout: React.FC = ({ orientation, handleChangeLayout }) => { return ( - + {orientation === 'vertical' ? ( - + ) : ( - + )} - + ); }; diff --git a/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/ClearResponse/ClearResponse.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/ClearResponse/ClearResponse.tsx index e983abb8..a5d92cb9 100644 --- a/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/ClearResponse/ClearResponse.tsx +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/ClearResponse/ClearResponse.tsx @@ -1,6 +1,7 @@ import React from 'react'; import IconButton from '@/ui/IconButton/IconButton'; import { IconEraser } from '@tabler/icons'; +import ActionIconButton from '../ActionIconButton/ActionIconButton'; interface ClearResponseProps { onClick: () => void; @@ -8,9 +9,9 @@ interface ClearResponseProps { const ClearResponse: React.FC = ({ onClick }) => { return ( - - - + + + ); }; diff --git a/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/CopyResponse/CopyResponse.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/CopyResponse/CopyResponse.tsx index f70c9c58..e19b3170 100644 --- a/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/CopyResponse/CopyResponse.tsx +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/CopyResponse/CopyResponse.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { IconCheck, IconCopy } from '@tabler/icons'; -import IconButton from '@/ui/IconButton/IconButton'; +import ActionIconButton from '../ActionIconButton/ActionIconButton'; interface CopyResponseProps { copied: boolean; @@ -10,9 +10,13 @@ interface CopyResponseProps { const CopyResponse: React.FC = ({ copied, onClick, disabled }) => { return ( - - {copied ? : } - + + {copied ? ( + + ) : ( + + )} + ); }; diff --git a/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/DownloadResponse/DownloadResponse.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/DownloadResponse/DownloadResponse.tsx index 1823bb00..ddf447e3 100644 --- a/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/DownloadResponse/DownloadResponse.tsx +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/DownloadResponse/DownloadResponse.tsx @@ -1,6 +1,7 @@ import React from 'react'; import IconButton from '@/ui/IconButton/IconButton'; import { IconDownload } from '@tabler/icons'; +import ActionIconButton from '../ActionIconButton/ActionIconButton'; interface DownloadResponseProps { onClick: () => void; @@ -9,9 +10,9 @@ interface DownloadResponseProps { const DownloadResponse: React.FC = ({ onClick, disabled }) => { return ( - - - + + + ); }; diff --git a/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/ResponseActions.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/ResponseActions.tsx index d8746d8c..446ea7c7 100644 --- a/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/ResponseActions.tsx +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/ResponseActions.tsx @@ -14,7 +14,7 @@ import ChangeLayout from './ChangeLayout/ChangeLayout'; import { StyledWrapper } from './StyledWrapper'; import MenuDropdown from '@/ui/MenuDropdown'; import type { MenuDropdownItem } from '@/ui/MenuDropdown'; -import IconButton from '@/ui/IconButton/IconButton'; +import ActionIconButton from './ActionIconButton/ActionIconButton'; import type { RunRequestResponse } from '@/runner'; import type { ResponseBodyFormat } from '@/constants'; import { useAppDispatch } from '@/store/hooks'; @@ -85,9 +85,9 @@ const ResponseActions: React.FC = ({
- - - + + +
diff --git a/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/StyledWrapper.ts b/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/StyledWrapper.ts index 3543c7a9..506bb2bb 100644 --- a/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/StyledWrapper.ts +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseActions/StyledWrapper.ts @@ -3,13 +3,23 @@ import styled from '@emotion/styled'; export const StyledWrapper = styled.div` display: flex; align-items: center; - gap: 0.5rem; .actions-dropdown { display: flex; } .actions-buttons { display: none; } + .more-actions-button { + border: 1px solid var(--oc-input-border); + height: 1.25rem; + } + .expandable & { - .actions-dropdown { display: none; } - .actions-buttons { display: flex; align-items: center; gap: 0.5rem; } + .actions-dropdown { + display: none; + } + .actions-buttons { + display: flex; + align-items: center; + gap: 0.125rem; + } } `; diff --git a/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseInfo/ResponseDuration/ResponseDuration.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseInfo/ResponseDuration/ResponseDuration.tsx index e898b07c..7d692bf6 100644 --- a/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseInfo/ResponseDuration/ResponseDuration.tsx +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseInfo/ResponseDuration/ResponseDuration.tsx @@ -10,10 +10,8 @@ const ResponseDuration: React.FC = ({ duration }) => { }; return ( -
- - {duration}ms - +
+ {duration}ms
); }; diff --git a/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseInfo/ResponseSize/ResponseSize.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseInfo/ResponseSize/ResponseSize.tsx index 649a84cb..dd1cb605 100644 --- a/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseInfo/ResponseSize/ResponseSize.tsx +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseInfo/ResponseSize/ResponseSize.tsx @@ -20,7 +20,7 @@ const ResponseSize: React.FC = ({ size }) => { ); return ( -
+
{sizeToDisplay}
); diff --git a/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseInfo/ResponseStatus/ResponseStatus.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseInfo/ResponseStatus/ResponseStatus.tsx index 4ea9df45..59b0b95b 100644 --- a/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseInfo/ResponseStatus/ResponseStatus.tsx +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/PlaygroundView/ResponsePane/ResponseInfo/ResponseStatus/ResponseStatus.tsx @@ -13,7 +13,7 @@ const ResponseStatus: React.FC = ({ status, statusText }) = return (
= ({ response, isLoading, orient // the responsive tab bar can measure the actions block (the last child) to decide whether to show // it as inline buttons or collapse it into a menu. const statusInfo = ( - <> -
- {activeTab === 'response' && ( - handleFormatChange(value)} - showPreview={showPreview} - toggleView={toggleView} - /> - )} +
+ {activeTab === 'response' && ( + handleFormatChange(value)} + showPreview={showPreview} + toggleView={toggleView} + /> + )} +
@@ -136,7 +136,7 @@ const ResponsePane: React.FC = ({ response, isLoading, orient selectedFormat={selectedFormat} showPreview={showPreview} /> - +
); return ( diff --git a/packages/bruno-api-docs/src/constants/response.ts b/packages/bruno-api-docs/src/constants/response.ts index be509b24..b019c84f 100644 --- a/packages/bruno-api-docs/src/constants/response.ts +++ b/packages/bruno-api-docs/src/constants/response.ts @@ -222,4 +222,4 @@ export const FORMAT_ICONS: Record = { // Width the actions block occupies when shown as buttons; the responsive tab bar uses it to // decide whether to expand the actions inline or collapse them into a menu. -export const RESPONSE_ACTIONS_EXPANDED_WIDTH = 135; +export const RESPONSE_ACTIONS_EXPANDED_WIDTH = 302;