Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions components/ui/component-meta/component-overview.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,23 @@
.tab {
border-bottom: 0;
}

// Mobile: ResponsiveNavbar hides any tab that doesn't fit its container (and reserves extra
// room for its "…" overflow button), so at phone widths the second tab ("Modify component")
// collapses into a bare "…". Sizing the nav to its content makes the width check always pass
// (this wrapper scrolls instead), and the now-useless overflow button is dropped so its
// reserved width can't hide the last tab.
@media screen and (max-width: $br-md) {
overflow-x: auto;

.nav {
min-width: max-content;

> div:last-child {
display: none;
}
}
}
}

.copyBox {
Expand Down
45 changes: 45 additions & 0 deletions scopes/component/component/ui/menu/menu.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,51 @@
min-width: 0;
}

// Minimal mode, mobile: one 46px row can't fit breadcrumb + nav tabs + pinned widgets +
// version dropdown, and since only the nav can shrink, ResponsiveNavbar collapses every tab
// (Overview / Preview) into an overflow dropdown that itself gets clipped — leaving no way to
// reach the preview. `display: contents` promotes this bar's children into the workspace
// top bar's wrapping flex row (see workspace.module.scss), producing two rows:
// back + breadcrumb + pinned widgets + right-side actions, then the nav tabs at full width.
.topBarMinimal {
@media screen and (max-width: $br-md) {
display: contents;

> .leftSide {
order: 10;
flex: 1 0 100%;
box-sizing: border-box;
Comment on lines +30 to +33

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

1. Visual/dom order mismatch 🐞 Bug ☼ Reliability

In mobile minimal mode, .topBarMinimal uses order: 10 to visually move the nav tabs row after
other controls, but the DOM order in ComponentMenu still places the nav before pinned
widgets/right-side actions. This can cause keyboard tabbing and screen-reader reading order to
disagree with what users see on screen.
Agent Prompt
### Issue description
On mobile minimal mode, CSS reorders focusable UI (nav tabs) using `order`, but the DOM order remains unchanged. This can create confusing keyboard focus order and screen-reader navigation because assistive tech follows DOM order, not visual order.

### Issue Context
- The PR intentionally wraps the workspace top bar into two rows in minimal mode.
- The nav row is moved to the second row via CSS `order`.

### Fix Focus Areas
- scopes/component/component/ui/menu/menu.module.scss[26-36]
- scopes/component/component/ui/menu/menu.tsx[171-180]

### Suggested fix
Avoid relying on CSS `order` to move focusable elements.
- Prefer reordering the JSX for the mobile-minimal layout so DOM order matches the visual order (e.g., render pinned widgets and right-side actions first-row, then render the nav row after them when the viewport is `<= $br-md`).
- If you need to keep the desktop minimal DOM structure unchanged, gate the DOM reorder behind a runtime media query hook (e.g., `useMediaQuery('(max-width: 768px)')`) so only the mobile layout swaps the render order.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

height: 40px;
overflow-x: auto;
Comment on lines +32 to +35

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

1. Tabs row too short 🐞 Bug ≡ Correctness

In minimal mobile mode, the component nav tabs row is forced to 40px height, which reduces the
clickable/tappable area of each tab because the tab list items and ResponsiveNavbar are sized to
100% height of that row. This can make navigation harder to use on touch devices and is inconsistent
with the workspace topbar’s 46px minimal height.
Agent Prompt
### Issue description
On mobile minimal mode, `.topBarMinimal > .leftSide` sets `height: 40px`, but the tab items are height-driven (100%) by their container. This shrinks the tab hit area below the workspace minimal topbar height (46px) and typical touch target guidance.

### Issue Context
- The workspace minimal topbar is 46px tall and now wraps on mobile.
- `ResponsiveNavbar` is explicitly styled to `height: 100%`, and `.navigation li` is also `height: 100%`, so the 40px container height directly becomes the tab row / tab hit target height.

### Fix Focus Areas
- scopes/component/component/ui/menu/menu.module.scss[30-36]
- scopes/component/component/ui/menu/menu-nav.tsx[91-100]
- scopes/workspace/workspace/ui/workspace/workspace.module.scss[151-166]

### Suggested fix
Change the mobile minimal `.leftSide` row sizing from a hard `height: 40px` to either:
- `height: 46px` (to match the minimal topbar), or
- `min-height: 46px` and remove/avoid a smaller fixed height,
so tabs maintain a consistent and sufficiently large interaction area.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

padding: 0 8px 0 4px;

// ResponsiveNavbar hides any tab that doesn't fit its container and reserves extra room
// for its "…" overflow button. Sizing the nav to its content makes the width check always
// pass (the row scrolls instead), and the now-useless overflow button is dropped so its
// reserved width can't hide the last tab.
nav {
min-width: max-content;

> div:last-child {
display: none;
}
Comment thread
luvkapur marked this conversation as resolved.
}
}

// the pinned widgets carry an inline `height: 100%`, which in the wrapped two-row bar
// resolves against the full (two-row) height and inflates the first row until the nav row
// is pushed outside the bar, over the page content — pin every first-row item to the bar
// height instead
> :not(.leftSide) {
height: 46px !important;
}
Comment thread
luvkapur marked this conversation as resolved.

> .rightSide {
margin-left: auto;
}
}
}

.navigation {
list-style: none;
height: 100%;
Expand Down
2 changes: 1 addition & 1 deletion scopes/component/component/ui/menu/menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ export function ComponentMenu({
<Route
path={`${resolvedComponentIdStr}/*`}
element={
<div className={classnames(styles.topBar, className)}>
<div className={classnames(styles.topBar, isMinimal && styles.topBarMinimal, className)}>
<div className={styles.leftSide}>
<CollapsibleMenuNav navigationSlot={navigationSlot} widgetSlot={widgetSlot} />
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@import '@teambit/base-ui.layout.breakpoints/_breakpoints.scss';

.container {
width: 100%;
height: 100%;
Expand Down Expand Up @@ -25,6 +27,10 @@
margin: auto;
padding: 48px 32px;
text-align: center;

@media screen and (max-width: $br-sm) {
padding: 32px 20px;
}
}

.headline {
Expand All @@ -37,6 +43,10 @@
letter-spacing: -0.02em;
text-wrap: balance;

@media screen and (max-width: $br-sm) {
font-size: 34px;
}

em {
color: var(--bit-accent-color, #6c5ce7);
font-style: italic;
Expand Down Expand Up @@ -117,7 +127,11 @@

.diyGrid {
display: grid;
grid-template-columns: 1fr 1fr;
// auto-fit instead of a bare `1fr 1fr`: `1fr` has an `auto` minimum, so the nowrap command
// text set the column's min width and pushed the second card past the viewport edge on
// narrow screens. 280px is the width at which a full command + Copy button still fit, so
// the cards sit side by side when there's room and stack when there isn't.
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 16px;
Comment thread
luvkapur marked this conversation as resolved.
}

Expand Down
20 changes: 20 additions & 0 deletions scopes/workspace/workspace/ui/workspace/workspace.module.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@import '@teambit/ui-foundation.ui.constants.z-indexes/z-indexes.module.scss';
@import '@teambit/base-ui.layout.breakpoints/_breakpoints.scss';

.emptyContainer {
height: 100vh;
Expand Down Expand Up @@ -39,6 +40,15 @@
display: flex;
align-items: center;
height: 100%;

// when the minimal top bar wraps into two rows on mobile, keep the breadcrumb row at the
// original bar height instead of stretching across both rows, and let a long component
// path clip rather than push the menu actions off-screen
@media screen and (max-width: $br-md) {
height: 46px;
min-width: 0;
overflow: hidden;
}
}

.breadcrumb {
Expand Down Expand Up @@ -143,6 +153,16 @@
--bit-bg-heaviest: color-mix(in srgb, var(--bit-accent-color, #6c5ce7) 3%, var(--background-color, #fff));
--bit-border-color-lightest: var(--bit-bg-heaviest);
border-bottom: 1px solid var(--border-medium-color, #e6e6e6);

// Mobile: a single 46px row can't fit breadcrumb + nav tabs + pinned widgets + version
// dropdown. The component menu switches to `display: contents` (see the component menu's
// topBarMinimal in menu.module.scss) so its pieces join this wrapping row: breadcrumb and
// actions stay on the first row, and the nav tabs wrap to a second full-width row.
@media screen and (max-width: $br-md) {
height: auto;
min-height: 46px;
flex-wrap: wrap;
}
}
}

Expand Down
Loading