Object icon visual parity (#19374)
## 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>
This commit is contained in:
+6
-3
@@ -8,6 +8,7 @@ import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/Dropdow
|
||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||
|
||||
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
||||
import { useObjectMetadataSelectHelpers } from '@/object-metadata/hooks/useObjectMetadataSelectHelpers';
|
||||
import { isObjectMetadataAvailableForRelation } from '@/object-metadata/utils/isObjectMetadataAvailableForRelation';
|
||||
import { MultiSelectControl } from '@/ui/input/components/MultiSelectControl';
|
||||
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
|
||||
@@ -21,7 +22,7 @@ import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states
|
||||
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { IconBox, useIcons, type IconComponent } from 'twenty-ui/display';
|
||||
import { IconBox, type IconComponent } from 'twenty-ui/display';
|
||||
import { MenuItem, MenuItemMultiSelect } from 'twenty-ui/navigation';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
@@ -101,12 +102,13 @@ export const SettingsMorphRelationMultiSelect = ({
|
||||
|
||||
const [searchInputValue, setSearchInputValue] = useState('');
|
||||
|
||||
const { getSelectIconPropsFromObjectMetadataItem } =
|
||||
useObjectMetadataSelectHelpers();
|
||||
const { activeObjectMetadataItems } = useFilteredObjectMetadataItems();
|
||||
|
||||
const [localSelectedObjectMetadataIds, setLocalSelectedObjectMetadataIds] =
|
||||
useState<string[]>(selectedObjectMetadataIds);
|
||||
|
||||
const { getIcon } = useIcons();
|
||||
const options = activeObjectMetadataItems
|
||||
.filter(isObjectMetadataAvailableForRelation)
|
||||
.sort((item1, item2) =>
|
||||
@@ -114,8 +116,8 @@ export const SettingsMorphRelationMultiSelect = ({
|
||||
)
|
||||
.map((objectMetadataItem) => ({
|
||||
label: objectMetadataItem.labelSingular,
|
||||
Icon: getIcon(objectMetadataItem.icon),
|
||||
objectMetadataId: objectMetadataItem.id,
|
||||
...getSelectIconPropsFromObjectMetadataItem(objectMetadataItem),
|
||||
}));
|
||||
|
||||
const selectedOptions = options.filter((option) =>
|
||||
@@ -256,6 +258,7 @@ export const SettingsMorphRelationMultiSelect = ({
|
||||
<MenuItemMultiSelect
|
||||
className=""
|
||||
LeftIcon={option.Icon ?? undefined}
|
||||
iconThemeColor={option.iconThemeColor}
|
||||
text={option.label}
|
||||
selected={selectedObjectMetadataIds.some(
|
||||
(selectedObjectMetadataId) =>
|
||||
|
||||
Reference in New Issue
Block a user