fix(twenty-front): new layout fast-follows — settings drawer, loading & command menu (#21389)
Second batch of new-layout fast-follows (master: twentyhq/core-team-issues#2478). All changes verified live against a running workspace. ## Settings drawer & header - **twentyhq/core-team-issues#2489** — sidebar icons render as plain 16px icons, no background tiles. - **twentyhq/core-team-issues#2488** — Advanced toggle spans the full drawer width; yellow dot removed. - **twentyhq/core-team-issues#2497** — page title stays centered in the settings header (breadcrumb stays left). - **twentyhq/core-team-issues#2490** — Exit Settings control aligned to the workspace switcher (24px, matching padding/gap). - **twentyhq/core-team-issues#2499** — 2px vertical gap restored between collapsible drawer section items. - **twentyhq/core-team-issues#2491** — settings drawer rhythm now matches the main app (28px items, 2px gaps, 28px section headers). - **twentyhq/core-team-issues#2492** — Home/Chat tab switch no longer flickers: both tab subtrees stay mounted (a shared `NavigationDrawerTabbedContent` toggles visibility instead of remounting + flashing the chat skeleton). ## Loading states - **twentyhq/core-team-issues#2486** — metadata loading shows an empty body (no dense skeleton rows). - **twentyhq/core-team-issues#2487** — settings table keeps its layout while loading, with the shimmer localized to the first row's first cell. ## Command menu & navigation - **twentyhq/core-team-issues#2501** — navigation section header height matches the nav item rhythm (28px). - **twentyhq/core-team-issues#2502 (part 1)** — the page side-panel toggle stays as the dots glyph while the command menu is open, instead of morphing into a second close control. ## New-field flow - **twentyhq/core-team-issues#2494** — the new-field stepper moved from a breadcrumb dropdown into a centered secondary wizard bar (back chevron + Save on the configure step); breadcrumb stays clean and the object label is the centered title. ## Descoped (substantive bugs already fixed) - **twentyhq/core-team-issues#2500** — command-menu highlight right gutter: the menu-item base measures full-width, so it's likely a scrollbar gutter on the list, not the shared component. Left for a focused follow-up. - **twentyhq/core-team-issues#2502 part 2** — moving the command-menu close from left to right is cosmetic (the duplicate-control bug is fixed by part 1) and would touch the shared `SidePanelTopBar` used by search/AI panels. ## Verification typecheck (tsgo) + oxlint + oxfmt green for all changed files; each change DOM-measured / screenshotted in the running app.
This commit is contained in:
-135
@@ -1,135 +0,0 @@
|
||||
import { type SettingsFieldType } from '@/settings/data-model/types/SettingsFieldType';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||
import { styled } from '@linaria/react';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useContext } from 'react';
|
||||
import { useLocation, useParams, useSearchParams } from 'react-router-dom';
|
||||
import { SettingsPath } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { IconChevronDown } from 'twenty-ui-deprecated/display';
|
||||
import { Button } from 'twenty-ui-deprecated/input';
|
||||
import { MenuItem } from 'twenty-ui-deprecated/navigation';
|
||||
import {
|
||||
ThemeContext,
|
||||
themeCssVariables,
|
||||
} from 'twenty-ui-deprecated/theme-constants';
|
||||
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
align-items: center;
|
||||
color: ${themeCssVariables.font.color.tertiary};
|
||||
cursor: default;
|
||||
display: flex;
|
||||
font-size: ${themeCssVariables.font.size.md};
|
||||
`;
|
||||
|
||||
const StyledButtonContainer = styled.div`
|
||||
position: relative;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const StyledDownChevronContainer = styled.span`
|
||||
align-items: center;
|
||||
color: ${themeCssVariables.font.color.primary};
|
||||
display: flex;
|
||||
position: absolute;
|
||||
right: ${themeCssVariables.spacing['1.5']};
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
`;
|
||||
|
||||
const StyledMenuItemWrapper = styled.div<{ disabled?: boolean }>`
|
||||
cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const StyledSpan = styled.span`
|
||||
margin-left: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
const StyledButtonWrapper = styled.div`
|
||||
button {
|
||||
color: ${themeCssVariables.font.color.primary};
|
||||
padding-right: ${themeCssVariables.spacing[6]};
|
||||
}
|
||||
`;
|
||||
|
||||
export const SettingsDataModelNewFieldBreadcrumbDropDown = () => {
|
||||
const { theme } = useContext(ThemeContext);
|
||||
const dropdownId = `settings-object-new-field-breadcrumb-dropdown`;
|
||||
const { closeDropdown } = useCloseDropdown();
|
||||
const navigate = useNavigateSettings();
|
||||
const location = useLocation();
|
||||
const { objectNamePlural = '' } = useParams();
|
||||
const [searchParams] = useSearchParams();
|
||||
|
||||
const fieldType = searchParams.get('fieldType') as SettingsFieldType;
|
||||
const isConfigureStep = location.pathname.includes('/configure');
|
||||
|
||||
const handleClick = (step: 'select' | 'configure') => {
|
||||
if (step === 'configure' && isDefined(fieldType)) {
|
||||
navigate(
|
||||
SettingsPath.ObjectNewFieldConfigure,
|
||||
{ objectNamePlural },
|
||||
{ fieldType },
|
||||
);
|
||||
} else {
|
||||
navigate(
|
||||
SettingsPath.ObjectNewFieldSelect,
|
||||
{ objectNamePlural },
|
||||
fieldType ? { fieldType } : undefined,
|
||||
);
|
||||
}
|
||||
closeDropdown(dropdownId);
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledContainer>
|
||||
{t`New Field`} <StyledSpan>-</StyledSpan>
|
||||
<Dropdown
|
||||
dropdownPlacement="bottom-start"
|
||||
dropdownId={dropdownId}
|
||||
clickableComponent={
|
||||
<StyledButtonContainer>
|
||||
<StyledDownChevronContainer>
|
||||
<IconChevronDown size={theme.icon.size.md} />
|
||||
</StyledDownChevronContainer>
|
||||
{isConfigureStep ? (
|
||||
<StyledButtonWrapper>
|
||||
<Button variant="tertiary" title={t`2. Configure`} />
|
||||
</StyledButtonWrapper>
|
||||
) : (
|
||||
<StyledButtonWrapper>
|
||||
<Button variant="tertiary" title={t`1. Type`} />
|
||||
</StyledButtonWrapper>
|
||||
)}
|
||||
</StyledButtonContainer>
|
||||
}
|
||||
dropdownComponents={
|
||||
<DropdownContent>
|
||||
<DropdownMenuItemsContainer>
|
||||
<StyledMenuItemWrapper>
|
||||
<MenuItem
|
||||
text={t`1. Type`}
|
||||
onClick={() => handleClick('select')}
|
||||
selected={!isConfigureStep}
|
||||
/>
|
||||
</StyledMenuItemWrapper>
|
||||
<StyledMenuItemWrapper disabled={!isDefined(fieldType)}>
|
||||
<MenuItem
|
||||
text={t`2. Configure`}
|
||||
onClick={() => handleClick('configure')}
|
||||
selected={isConfigureStep}
|
||||
disabled={!isDefined(fieldType)}
|
||||
/>
|
||||
</StyledMenuItemWrapper>
|
||||
</DropdownMenuItemsContainer>
|
||||
</DropdownContent>
|
||||
}
|
||||
/>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user