diff --git a/src/components/ComponentsSelection/ComponentsSelection.module.css b/src/components/ComponentsSelection/ComponentsSelection.module.css index f8b7ecbf..e45e641b 100644 --- a/src/components/ComponentsSelection/ComponentsSelection.module.css +++ b/src/components/ComponentsSelection/ComponentsSelection.module.css @@ -3,3 +3,37 @@ background: var(--sapBackgroundColor); border-bottom: 1px solid var(--sapList_BorderColor); } + +.row:hover { + background: var(--sapList_Hover_Background); +} + +.row.providerRow { + position: relative; + padding-inline-start: calc(1rem + 16px); + background: color-mix(in srgb, var(--sapBackgroundColor) 98%, #000 2%); +} + +@media (prefers-color-scheme: dark) { + .row.providerRow { + background: color-mix(in srgb, var(--sapBackgroundColor) 97%, #fff 3%); + } +} + +.row.providerRow:hover { + background: var(--sapList_Hover_Background); +} + +.row.providerRow::before { + content: ""; + position: absolute; + inset-block: 6px; + inset-inline-start: 1.6rem; + width: 2px; + background: var(--sapList_BorderColor); +} + +.providerRow :global(ui5-checkbox) { + transform: scale(0.9); + transform-origin: left center; +} \ No newline at end of file diff --git a/src/components/ComponentsSelection/ComponentsSelection.tsx b/src/components/ComponentsSelection/ComponentsSelection.tsx index fbe4ca3f..fc31c988 100644 --- a/src/components/ComponentsSelection/ComponentsSelection.tsx +++ b/src/components/ComponentsSelection/ComponentsSelection.tsx @@ -40,10 +40,31 @@ export const ComponentsSelection: React.FC = ({ const selectedComponents = useMemo(() => getSelectedComponents(componentsList), [componentsList]); + const isProvider = useCallback((componentName: string) => { + return componentName.includes('provider') && componentName !== 'crossplane'; + }, []); + const searchResults = useMemo(() => { const lowerSearch = searchTerm.toLowerCase(); - return componentsList.filter(({ name }) => name.toLowerCase().includes(lowerSearch)); - }, [componentsList, searchTerm]); + const filtered = componentsList.filter(({ name }) => name.toLowerCase().includes(lowerSearch)); + + // Sort components: crossplane first, then providers, then rest + return filtered.sort((a, b) => { + const isCrossplaneA = a.name === 'crossplane'; + const isCrossplaneB = b.name === 'crossplane'; + + if (isCrossplaneA && !isCrossplaneB) return -1; + if (isCrossplaneB && !isCrossplaneA) return 1; + + const isProviderA = isProvider(a.name); + const isProviderB = isProvider(b.name); + + if (isProviderA && !isProviderB) return -1; + if (isProviderB && !isProviderA) return 1; + + return a.name.localeCompare(b.name); + }); + }, [componentsList, searchTerm, isProvider]); const handleSelectionChange = useCallback( (e: Ui5CustomEvent) => { @@ -105,10 +126,12 @@ export const ComponentsSelection: React.FC = ({ {searchResults.length > 0 ? ( searchResults.map((component) => { const providerDisabled = isProviderDisabled(component); + const isProviderComponent = isProvider(component.name); + return ( = ({ checked={component.isSelected} disabled={providerDisabled} aria-label={component.name} + className={isProviderComponent ? styles.checkBox : ''} onChange={handleSelectionChange} />