34a903b4fa
## Summary Aligns **object metadata** icons with the **tinted tile** look everywhere we show a workspace object, and **retires** the navigation-only `NavigationMenuItemStyleIcon` wrapper in favor of **shared** UI primitives under `@/ui/display` and `@/object-metadata`. ## What changed ### Global tinted icon building blocks (`@/ui/display`) - **`TintedIconTile`** / **`StyledTintedIconTileContainer`** support optional **`size`** and **`stroke`**, and grow the tile when **`size`** is set so layouts match previous `theme.icon` usage. - Shared helpers and constants for theme color parsing and tinted backgrounds/borders/icon color (e.g. **`getTintedIconTileStyleFromColor`**, **`parseThemeColor`**, **`getColorFromTheme`**, related constants). ### Object metadata icon (`@/object-metadata`) - **`ObjectMetadataIcon`** composes **`TintedIconTile`** with **`getObjectColorWithFallback`**, forwards optional **`size`** / **`stroke`** for **visual parity** with old `getIcon` + explicit sizing. - **`getSelectOptionIconFromObjectMetadataItem`** returns an **`IconComponent`** for selects/menus that expect a component, not a React node. ### Navigation module cleanup - **Removed** **`NavigationMenuItemStyleIcon`**; call sites use **`ObjectMetadataIcon`**, **`TintedIconTile`**, and/or the shared **`getTintedIconTileStyleFromColor`** pipeline so the same treatment is **not** tied to the navigation package. - **`NavigationMenuItemIcon`**, view/link overlays, DnD handle, and sidebar editor flows updated to use the shared pattern where they render object (or tinted) icons. ### Product surfaces updated (non-exhaustive) - **Settings:** role object picker/rows, data model tables/graph/overview, object preview summary, webhooks entity list, morph relation multiselect. - **Workflows:** create/update/delete/upsert/find records, triggers, filters, variables dropdowns, AI agent object rows, object dropdowns. - **Shell:** side panel object filter / data sources / folder chrome where object icons appear. - **Records:** index header icon, show breadcrumb styling. - **Activity:** timeline event icon when linked object metadata applies. - **`NavigationDrawerItem`:** tinted branch aligned with shared **`TintedIconTile`** behavior. --------- Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com>
116 lines
4.1 KiB
TypeScript
116 lines
4.1 KiB
TypeScript
import { useLingui } from '@lingui/react/macro';
|
|
import { IconSettings, TintedIconTile } from 'twenty-ui/display';
|
|
|
|
import { CommandMenuItem } from '@/command-menu/components/CommandMenuItem';
|
|
import { SidePanelObjectPickerItem } from '@/navigation-menu-item/edit/side-panel/components/SidePanelObjectPickerItem';
|
|
import { type EnrichedObjectMetadataItem } from '@/object-metadata/types/EnrichedObjectMetadataItem';
|
|
import { SidePanelAddToNavigationDroppable } from '@/side-panel/components/SidePanelAddToNavigationDroppable';
|
|
import { SidePanelGroup } from '@/side-panel/components/SidePanelGroup';
|
|
import { SidePanelList } from '@/side-panel/components/SidePanelList';
|
|
import { SidePanelSubViewWithSearch } from '@/side-panel/components/SidePanelSubViewWithSearch';
|
|
import { useSidePanelFilteredPickerItems } from '@/side-panel/hooks/useSidePanelFilteredPickerItems';
|
|
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
|
|
|
|
type SidePanelObjectPickerSubViewProps = {
|
|
objects: EnrichedObjectMetadataItem[];
|
|
searchValue: string;
|
|
onSearchChange: (value: string) => void;
|
|
onOpenSystemPicker: () => void;
|
|
isViewItem: boolean;
|
|
onSelectObjectForViewEdit?: (
|
|
objectMetadataItem: EnrichedObjectMetadataItem,
|
|
) => void;
|
|
onChangeObject: (objectMetadataItem: EnrichedObjectMetadataItem) => void;
|
|
objectMenuItemVariant?: 'add' | 'edit';
|
|
emptyNoResultsText?: string;
|
|
disableDrag?: boolean;
|
|
};
|
|
|
|
export const SidePanelObjectPickerSubView = ({
|
|
objects,
|
|
searchValue,
|
|
onSearchChange,
|
|
onOpenSystemPicker,
|
|
isViewItem,
|
|
onSelectObjectForViewEdit,
|
|
onChangeObject,
|
|
objectMenuItemVariant = 'edit',
|
|
emptyNoResultsText,
|
|
disableDrag = false,
|
|
}: SidePanelObjectPickerSubViewProps) => {
|
|
const { t } = useLingui();
|
|
const { filteredItems, selectableItemIds, isEmpty, hasSearchQuery } =
|
|
useSidePanelFilteredPickerItems({
|
|
items: objects,
|
|
searchQuery: searchValue,
|
|
getSearchableValues: (item) => [item.labelPlural],
|
|
appendSelectableIds: ['system'],
|
|
});
|
|
|
|
const noResultsText = hasSearchQuery
|
|
? t`No results found`
|
|
: (emptyNoResultsText ?? t`All objects are already in the sidebar`);
|
|
|
|
const isAddVariant = objectMenuItemVariant === 'add';
|
|
|
|
const listContent = (
|
|
<SidePanelGroup heading={t`Objects`}>
|
|
{filteredItems.map((objectMetadataItem, index) => (
|
|
<SidePanelObjectPickerItem
|
|
key={objectMetadataItem.id}
|
|
objectMetadataItem={objectMetadataItem}
|
|
isViewItem={isViewItem}
|
|
onSelectObjectForViewEdit={onSelectObjectForViewEdit}
|
|
onChangeObject={onChangeObject}
|
|
objectMenuItemVariant={objectMenuItemVariant}
|
|
dragIndex={isAddVariant && !disableDrag ? index : undefined}
|
|
disableDrag={disableDrag}
|
|
/>
|
|
))}
|
|
<SelectableListItem itemId="system" onEnter={onOpenSystemPicker}>
|
|
<CommandMenuItem
|
|
Icon={() => <TintedIconTile Icon={IconSettings} />}
|
|
label={t`System objects`}
|
|
id="system"
|
|
hasSubMenu
|
|
onClick={onOpenSystemPicker}
|
|
/>
|
|
</SelectableListItem>
|
|
</SidePanelGroup>
|
|
);
|
|
|
|
return (
|
|
<SidePanelSubViewWithSearch
|
|
searchPlaceholder={t`Search an object...`}
|
|
searchValue={searchValue}
|
|
onSearchChange={onSearchChange}
|
|
>
|
|
{isAddVariant ? (
|
|
<SidePanelAddToNavigationDroppable>
|
|
{({ innerRef, droppableProps, placeholder }) => (
|
|
<SidePanelList
|
|
selectableItemIds={selectableItemIds}
|
|
noResults={isEmpty}
|
|
noResultsText={noResultsText}
|
|
>
|
|
{/* oxlint-disable-next-line react/jsx-props-no-spreading */}
|
|
<div ref={innerRef} {...droppableProps}>
|
|
{listContent}
|
|
{placeholder}
|
|
</div>
|
|
</SidePanelList>
|
|
)}
|
|
</SidePanelAddToNavigationDroppable>
|
|
) : (
|
|
<SidePanelList
|
|
selectableItemIds={selectableItemIds}
|
|
noResults={isEmpty}
|
|
noResultsText={noResultsText}
|
|
>
|
|
{listContent}
|
|
</SidePanelList>
|
|
)}
|
|
</SidePanelSubViewWithSearch>
|
|
);
|
|
};
|