diff --git a/e b/e
index 651424c0a2cd7..021d1ab54544d 160000
--- a/e
+++ b/e
@@ -1 +1 @@
-Subproject commit 651424c0a2cd7e1eb6020563622121e59b1e75de
+Subproject commit 021d1ab54544d4d37de1c1f31389e70c14215551
diff --git a/web/packages/design/src/ShimmerBox/ShimmerBox.tsx b/web/packages/design/src/ShimmerBox/ShimmerBox.tsx
index 465a5e1221301..ab1167265833f 100644
--- a/web/packages/design/src/ShimmerBox/ShimmerBox.tsx
+++ b/web/packages/design/src/ShimmerBox/ShimmerBox.tsx
@@ -31,7 +31,7 @@ const loading = keyframes`
const ShimmerWrapper = styled.div`
width: 100%;
height: 100%;
- background-color: ${props => props.theme.colors.levels.surface};
+ background-color: ${props => props.theme.colors.spotBackground[0]};
border-radius: ${props => props.theme.radii[2]}px;
overflow: hidden;
position: relative;
@@ -43,7 +43,7 @@ const Shimmer = styled.div`
background: linear-gradient(
90deg,
transparent 25%,
- ${props => props.theme.colors.levels.elevated} 50%,
+ ${props => props.theme.colors.spotBackground[0]} 50%,
transparent 75%
);
background-size: 200% 100%;
diff --git a/web/packages/shared/components/UnifiedResources/CardsView/CardsView.tsx b/web/packages/shared/components/UnifiedResources/CardsView/CardsView.tsx
index 3c8c2e0cd8ddf..5cf7eae0a457c 100644
--- a/web/packages/shared/components/UnifiedResources/CardsView/CardsView.tsx
+++ b/web/packages/shared/components/UnifiedResources/CardsView/CardsView.tsx
@@ -23,8 +23,9 @@ import { FETCH_MORE_SIZE } from '../UnifiedResources';
import { ResourceViewProps } from '../types';
-import { LoadingSkeleton } from '../LoadingSkeleton';
-import { LoadingCard } from '../LoadingCard';
+import { LoadingSkeleton } from '../shared/LoadingSkeleton';
+
+import { LoadingCard } from './LoadingCard';
import { ResourceCard } from './ResourceCard';
@@ -57,7 +58,6 @@ export function CardsView({
pinResource={() => onPinResource(key)}
/>
))}
- {/* Using index as key here is ok because these elements never change order */}
{isProcessing && (
} />
)}
diff --git a/web/packages/shared/components/UnifiedResources/LoadingCard.tsx b/web/packages/shared/components/UnifiedResources/CardsView/LoadingCard.tsx
similarity index 100%
rename from web/packages/shared/components/UnifiedResources/LoadingCard.tsx
rename to web/packages/shared/components/UnifiedResources/CardsView/LoadingCard.tsx
diff --git a/web/packages/shared/components/UnifiedResources/ListView/ListView.tsx b/web/packages/shared/components/UnifiedResources/ListView/ListView.tsx
index 61fc58a3d6185..885bd7319617c 100644
--- a/web/packages/shared/components/UnifiedResources/ListView/ListView.tsx
+++ b/web/packages/shared/components/UnifiedResources/ListView/ListView.tsx
@@ -16,11 +16,15 @@
import React from 'react';
-import { Flex, Box, Indicator } from 'design';
+import { Flex } from 'design';
import { ResourceViewProps } from '../types';
+import { FETCH_MORE_SIZE } from '../UnifiedResources';
+
+import { LoadingSkeleton } from '../shared/LoadingSkeleton';
import { ResourceListItem } from './ResourceListItem';
+import { LoadingListItem } from './LoadingListItem';
export function ListView({
mappedResources,
@@ -51,11 +55,11 @@ export function ListView({
pinResource={() => onPinResource(key)}
/>
))}
- {/* TODO (rudream): Add skeleton loader */}
{isProcessing && (
-
-
-
+ }
+ />
)}
);
diff --git a/web/packages/shared/components/UnifiedResources/ListView/LoadingListItem.tsx b/web/packages/shared/components/UnifiedResources/ListView/LoadingListItem.tsx
new file mode 100644
index 0000000000000..e7f375d184b43
--- /dev/null
+++ b/web/packages/shared/components/UnifiedResources/ListView/LoadingListItem.tsx
@@ -0,0 +1,87 @@
+/**
+ * Copyright 2023 Gravitational, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+import styled from 'styled-components';
+
+import { Box, Flex } from 'design';
+import { ShimmerBox } from 'design/ShimmerBox';
+
+export function LoadingListItem() {
+ return (
+
+ {/* Image */}
+
+ {/* Name and description */}
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+function randomNum(min: number, max: number) {
+ return Math.floor(Math.random() * (max - min + 1)) + min;
+}
+
+const LoadingListItemWrapper = styled(Box)`
+ height: 58px;
+ min-width: 100%;
+
+ display: grid;
+ align-items: center;
+ column-gap: ${props => props.theme.space[3]}px;
+ grid-template-columns: 36px 2fr 1fr 1fr 90px;
+ grid-template-areas: 'image name type address button';
+ padding-right: ${props => props.theme.space[3]}px;
+ padding-left: ${props => props.theme.space[3]}px;
+`;
diff --git a/web/packages/shared/components/UnifiedResources/LoadingSkeleton.tsx b/web/packages/shared/components/UnifiedResources/shared/LoadingSkeleton.tsx
similarity index 100%
rename from web/packages/shared/components/UnifiedResources/LoadingSkeleton.tsx
rename to web/packages/shared/components/UnifiedResources/shared/LoadingSkeleton.tsx