* Studio: make UI font size scale all text without moving layout The UI font size setting changes the root rem base, so only rem sized text reacted. Hundreds of px text classes, px font sizes in CSS, and chart labels stayed fixed, while rem based padding, widths and radii wrongly grew. Convert all text sizes to rem so every font follows the setting, and pin spacing, radius, container widths, sidebar and thread widths to px so layout no longer follows the rem base. Library styles (streamdown, react-flow) are re-based via overrides. All conversions are exact at the default 16px root, so the default rendering is unchanged. * Studio: keep logo at fixed size and fit tight controls at large UI fonts The logo lockups (sidebar wordmark with beta badge, onboarding wizard) are branding and now keep px sizes at any UI font size. Two controls clipped their text at the largest setting: the appearance color chips (fixed w-24) and the voice tab selects (fixed w-56). Both use min widths now, so they keep the default look at 16px and only grow when the text needs the room. * Studio: keep dropdown corners rounded when the menu scrolls A scrolling dropdown lost its rounded corners on the scrollbar side: WebKit paints the surface square when the rounded element itself hosts the scrollbar, which shows up in the desktop app whenever a menu overflows, for example at larger UI font sizes. Dropdown menu and select content now clip with overflow hidden and scroll an inner viewport instead. The surface padding insets the scrollbar clear of the curve, so corners stay rounded in every engine. Submenus are unaffected since sub content is portaled. * Studio: scale the logo lockups at half the UI font size rate Rather than pinning the logo, the sidebar lockup (sticker, wordmark, beta badge) and the onboarding lockup now follow the UI font size at half the rate of the change: size = base + (root - 16px) / 2, written as calc((base - 8)px + 0.5rem). A 4px font size change moves the logo by 2px, and the default 16px root renders the exact base sizes. * Studio: address review feedback on leading, grid tracks and select scrolling Numeric leading utilities (leading-3 through leading-10) derive from --spacing, so pinning spacing to px also froze their line-heights while the paired text sizes now scale. Define them as rem theme tokens so line-height follows the UI font size again; values are identical at the 16px default. Convert the grid tracks the rem-to-px codemod missed (rem followed by an underscore escaped the word boundary): the response details label column and the on-device folder rows. Make the Radix select viewport the bounded scroller instead of a wrapper div, so Radix's scroll handling and the browser scroll the same element. Restore the app's thin scrollbar with an inline style, which beats the scrollbar hiding stylesheet Radix injects at runtime. * Studio: cap voice select widths and update CI contracts
41 lines
1.5 KiB
Python
41 lines
1.5 KiB
Python
"""Compact viewport contracts for nested dropdown menus."""
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
REPO = Path(__file__).resolve().parents[2]
|
|
DROPDOWN_MENU = REPO / "studio/frontend/src/components/ui/dropdown-menu.tsx"
|
|
FRONTEND_SRC = REPO / "studio/frontend/src"
|
|
|
|
|
|
def test_shared_submenu_uses_its_layout_width_on_mobile():
|
|
source = DROPDOWN_MENU.read_text(encoding = "utf-8")
|
|
assert 'import { useIsMobile } from "@/hooks/use-mobile";' in source
|
|
assert "element.offsetWidth" in source
|
|
assert "element.getBoundingClientRect().width" not in source
|
|
assert "new ResizeObserver(updateContentWidth)" in source
|
|
assert "isMobile && contentWidth > 0 ? -contentWidth : sideOffset" in source
|
|
assert "sideOffset={compactSideOffset}" in source
|
|
assert 'isMobile && contentWidth === 0 ? "hidden"' in source
|
|
assert "-248" not in source
|
|
|
|
|
|
def test_shared_submenu_never_exceeds_the_compact_viewport():
|
|
source = DROPDOWN_MENU.read_text(encoding = "utf-8")
|
|
assert "max-w-[calc(100vw-32px)]" in source
|
|
|
|
|
|
def test_consumers_do_not_duplicate_compact_offset_logic():
|
|
for path in FRONTEND_SRC.rglob("*.tsx"):
|
|
if path == DROPDOWN_MENU:
|
|
continue
|
|
source = path.read_text(encoding = "utf-8")
|
|
assert "compactSubmenuOffset" not in source, path
|
|
|
|
|
|
def test_all_submenu_consumers_use_the_shared_primitive():
|
|
for path in FRONTEND_SRC.rglob("*.tsx"):
|
|
if path == DROPDOWN_MENU:
|
|
continue
|
|
source = path.read_text(encoding = "utf-8")
|
|
assert "DropdownMenuPrimitive.SubContent" not in source, path
|