fix(page-layout): let the column surface win over the solo presentation (#23412)
## Why In the side panel and on mobile, a tab holding a single widget renders with no gutter at all: the field list sits flush against the panel border. Regression from #23109. `getWidgetCardVariant` checked the derived presentation before the surface: ```ts if (presentation === 'solo') return 'solo'; const isSideColumnContext = isInPinnedTab || isMobile || isInSidePanel; ``` So a single-widget tab resolved to `'solo'` even in the side panel or on mobile, and `'solo'` has no branch in `WidgetCard`'s padding switch, so it falls through to `0`. The same widget used to match `variant === 'side-column' && !isEditable` and get `spacing[3]` (12px). The pinned left panel escaped this only because `PageLayoutLeftPanel` hardcodes `presentation: 'stack'` — the rule was already there ("the pinned left panel is always a column, a surface rule not a widget rule"), just applied at one call site instead of being the rule. ## Why only the Home tab looks broken Every widget that used to live on a `CANVAS` tab carries its own gutter, so losing the card padding costs them nothing: | Widget | Own horizontal padding | |---|---| | Timeline | `spacing[6]` | | Notes | `spacing[6]` | | Files | `spacing[6]` | | Tasks | `spacing[6]` | | **Fields** | **none** | `Fields` was the only widget on a `VERTICAL_LIST` tab, so it was the only one relying on the card for its gutter, and the only one that ends up flush. ## What Resolve the surface first: a column surface (pinned panel, side panel, mobile) is always a column of cards, whatever the tab presentation is. Solo stays a main-tab-area concept. Header visibility is untouched: `showHeader` keys off `presentation`, not the variant, so a solo tab still shows no bare title row. The `Fields` widget does not regain the header it lost in #23109. ## Measured Side panel, custom object whose Home tab holds a single Fields widget (1600x1000, panel at x=1200): | | Card padding | First label x | |---|---|---| | main | `0px` | 1221 | | this PR | `12px` | 1233 | 12px restored, matching what the pinned left panel gives the same widget. ## Trade-off worth a second opinion In the side panel and on mobile, the activity widgets now resolve to `'side-column'` instead of `'solo'`, so they pick up the card's 12px on top of their own 24px, i.e. 36px instead of 24px. Nothing overlaps or clips, but it is a visible change on those tabs. If you would rather keep them at 24px, the follow-up is to drop the intrinsic `spacing[6]` from the activity cards and let the surface own the gutter everywhere. ## Test plan - `getWidgetCardVariant` tests extended: `'side-column'` now wins over `'solo'` for each of `isInPinnedTab` / `isMobile` / `isInSidePanel`. 13 tests pass. - 88 suites / 620 tests across `page-layout/widgets` pass. - `lint:diff-with-main twenty-front` clean. - Verified against a local stack: side panel on a single-widget Home tab, before and after.
This commit is contained in:
+18
@@ -72,5 +72,23 @@ describe('getWidgetCardVariant', () => {
|
||||
}),
|
||||
).toBe('side-column');
|
||||
});
|
||||
|
||||
it.each([
|
||||
['isInPinnedTab', { isInPinnedTab: true }],
|
||||
['isMobile', { isMobile: true }],
|
||||
['isInSidePanel', { isInSidePanel: true }],
|
||||
])(
|
||||
"returns 'side-column' over 'solo' when %s is true",
|
||||
(_label, override) => {
|
||||
expect(
|
||||
getWidgetCardVariant({
|
||||
...baseParams,
|
||||
...override,
|
||||
presentation: 'solo',
|
||||
pageLayoutType: PageLayoutType.RECORD_PAGE,
|
||||
}),
|
||||
).toBe('side-column');
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -17,12 +17,16 @@ export const getWidgetCardVariant = ({
|
||||
isMobile,
|
||||
isInSidePanel,
|
||||
}: GetWidgetCardVariantParams): WidgetCardVariant => {
|
||||
const isSideColumnContext = isInPinnedTab || isMobile || isInSidePanel;
|
||||
|
||||
if (isSideColumnContext) {
|
||||
return 'side-column';
|
||||
}
|
||||
|
||||
if (presentation === 'solo') {
|
||||
return 'solo';
|
||||
}
|
||||
|
||||
const isSideColumnContext = isInPinnedTab || isMobile || isInSidePanel;
|
||||
|
||||
switch (pageLayoutType) {
|
||||
case PageLayoutType.DASHBOARD:
|
||||
return 'dashboard';
|
||||
@@ -31,6 +35,6 @@ export const getWidgetCardVariant = ({
|
||||
case PageLayoutType.RECORD_PAGE:
|
||||
case PageLayoutType.RECORD_INDEX:
|
||||
case null:
|
||||
return isSideColumnContext ? 'side-column' : 'record-page';
|
||||
return 'record-page';
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user