Repository: GoogleChromeLabs/ps-analysis-tool
Pull request #102 (2023-08-09 14:16:22)

Feature: Cookie Landing page - Part-3
## Description

Implement design for cookies landing page and update popup design.

## Relevant Technical Choices

- Add stories for components.
- Refactor code to reuse developer tools components in the popup.
- Refactor code.
- Add dummy data for tests.

## Testing Instructions

<!--
How can the changes in this PR be verified?
Please provide step-by-step instructions to test the changes.
-->

## Additional Information:

<!-- Any other information. -->

## Screenshot/Screencast

**Landing Page**
<img width="1439" alt="image" src="https://github.com/GoogleChromeLabs/ps-analysis-tool/assets/6297436/346bf425-7c24-4ca1-92c7-a1827f50eaaa">

**Popup**
<img width="392" alt="image" src="https://github.com/GoogleChromeLabs/ps-analysis-tool/assets/6297436/4f5cfd44-8718-45b0-a80d-1e897dc6b35a">


---

<!--
Example:

Fixes #123
Partially addresses #22
See #834
-->

Fixes https://github.com/GoogleChromeLabs/ps-analysis-tool/issues/66
Fixes https://github.com/GoogleChromeLabs/ps-analysis-tool/issues/99



Patch:
diff --git a/packages/extension/src/utils/prepareCookieStatsComponents.ts b/packages/extension/src/utils/prepareCookieStatsComponents.ts
new file mode 100644
index 00000000..558f34dc
--- /dev/null
+++ b/packages/extension/src/utils/prepareCookieStatsComponents.ts
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * 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
+ *
+ *     https://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.
+ */
+/**
+ * Internal dependencies.
+ */
+import { COLOR_MAP } from '../view/design-system/theme/colors';
+import type { CookiesCount } from '../view/popup/types';
+import type { CookieStatsComponents } from '../view/devtools/cookies.types';
+
+export const prepareCookieStatsComponents = (
+  cookieStats: CookiesCount
+): CookieStatsComponents => {
+  return {
+    legend: [
+      {
+        label: 'Functional',
+        count:
+          cookieStats.firstParty.functional + cookieStats.thirdParty.functional,
+        color: COLOR_MAP.functional,
+        countClassName: 'text-functional',
+      },
+      {
+        label: 'Marketing',
+        count:
+          cookieStats.firstParty.marketing + cookieStats.thirdParty.marketing,
+        color: COLOR_MAP.marketing,
+        countClassName: 'text-marketing',
+      },
+      {
+        label: 'Analytics',
+        count:
+          cookieStats.firstParty.analytics + cookieStats.thirdParty.analytics,
+        color: COLOR_MAP.analytics,
+        countClassName: 'text-analytics',
+      },
+      {
+        label: 'Uncategorized',
+        count:
+          cookieStats.firstParty.uncategorized +
+          cookieStats.thirdParty.uncategorized,
+        color: COLOR_MAP.uncategorized,
+        countClassName: 'text-uncategorized',
+      },
+    ],
+    firstParty: [
+      {
+        count: cookieStats.firstParty.functional,
+        color: COLOR_MAP.functional,
+      },
+      {
+        count: cookieStats.firstParty.marketing,
+        color: COLOR_MAP.marketing,
+      },
+      {
+        count: cookieStats.firstParty.analytics,
+        color: COLOR_MAP.analytics,
+      },
+      {
+        count: cookieStats.firstParty.uncategorized,
+        color: COLOR_MAP.uncategorized,
+      },
+    ],
+    thirdParty: [
+      {
+        count: cookieStats.thirdParty.functional,
+        color: COLOR_MAP.functional,
+      },
+      {
+        count: cookieStats.thirdParty.marketing,
+        color: COLOR_MAP.marketing,
+      },
+      {
+        count: cookieStats.thirdParty.analytics,
+        color: COLOR_MAP.analytics,
+      },
+      {
+        count: cookieStats.thirdParty.uncategorized,
+        color: COLOR_MAP.uncategorized,
+      },
+    ],
+  };
+};
diff --git a/packages/extension/src/utils/countCookiesByCategory.ts b/packages/extension/src/utils/prepareCookiesCount.ts
similarity index 66%
rename from packages/extension/src/utils/countCookiesByCategory.ts
rename to packages/extension/src/utils/prepareCookiesCount.ts
index cc9b8fd0..c7be4f64 100644
--- a/packages/extension/src/utils/countCookiesByCategory.ts
+++ b/packages/extension/src/utils/prepareCookiesCount.ts
@@ -18,44 +18,44 @@
  * Internal dependencies.
  */
 import type { CookieData } from '../localStore';
-import type { CookieStats } from '../view/popup/types';
+import type { CookiesCount } from '../view/popup/types';
 import isFirstParty from './isFirstParty';
 
 /**
- * Categorize cookies count into 1st party and 3rd party cookies and into functional, marketing, analytics and Uncategorised.
+ * Categorize cookies count into 1st party and 3rd party cookies and then into functional, marketing, analytics and uncategorized.
  * @param {{ [key: string]: CookieData }} cookies Cookies of a tab.
  * @param {string} tabUrl Tab URL
- * @returns CookieStats object with the categorized cookies count.
+ * @returns CookiesCount object with the categorized cookies count.
  */
-const countCookiesByCategory = (
+const prepareCookiesCount = (
   cookies: { [key: string]: CookieData } | null,
-  tabUrl: string
+  tabUrl: string | null
 ) => {
-  const stats: CookieStats = {
+  const cookiesCount: CookiesCount = {
     total: 0,
     firstParty: {
       total: 0,
       functional: 0,
       marketing: 0,
       analytics: 0,
-      uncategorised: 0,
+      uncategorized: 0,
     },
     thirdParty: {
       total: 0,
       functional: 0,
       marketing: 0,
       analytics: 0,
-      uncategorised: 0,
+      uncategorized: 0,
     },
   };
 
-  if (!cookies) {
-    return stats;
+  if (!cookies || !tabUrl) {
+    return cookiesCount;
   }
 
   const cookieList = Object.values(cookies);
 
-  stats.total = cookieList.length;
+  cookiesCount.total = cookieList.length;
 
   for (const cookie of cookieList) {
     const {
@@ -64,19 +64,19 @@ const countCookiesByCategory = (
     } = cookie;
     const isFirstPartyCookie = isFirstParty(domain, tabUrl);
     const category = analytics?.category?.toLowerCase() as
-      | keyof CookieStats['firstParty']
-      | keyof CookieStats['thirdParty']
+      | keyof CookiesCount['firstParty']
+      | keyof CookiesCount['thirdParty']
       | undefined;
 
     if (isFirstPartyCookie) {
-      stats.firstParty.total++;
-      stats.firstParty[category ? category : 'uncategorised']++;
+      cookiesCount.firstParty.total++;
+      cookiesCount.firstParty[category ? category : 'uncategorized']++;
     } else {
-      stats.thirdParty.total++;
-      stats.thirdParty[category ? category : 'uncategorised']++;
+      cookiesCount.thirdParty.total++;
+      cookiesCount.thirdParty[category ? category : 'uncategorized']++;
     }
   }
-  return stats;
+  return cookiesCount;
 };
 
-export default countCookiesByCategory;
+export default prepareCookiesCount;
diff --git a/packages/extension/src/view/design-system/components/circle/circleEmpty.tsx b/packages/extension/src/view/design-system/components/circle/circleEmpty.tsx
index 88de27c6..a3efb339 100644
--- a/packages/extension/src/view/design-system/components/circle/circleEmpty.tsx
+++ b/packages/extension/src/view/design-system/components/circle/circleEmpty.tsx
@@ -24,16 +24,14 @@ import React from 'react';
 import { COLOR_MAP } from '../../theme/colors';
 
 interface CircleEmptyProps {
-  color: string;
+  color?: string;
 }
 
 const CircleEmpty = ({ color = COLOR_MAP.mediumGray }: CircleEmptyProps) => (
   <div
-    className="w-2.5 h-2.5 rounded-full flex items-center justify-center"
-    style={{ backgroundColor: color }}
-  >
-    <div className="w-1.5 h-1.5 rounded-full flex items-center justify-center bg-white" />
-  </div>
+    className="w-2.5 h-2.5 flex-shrink-0 rounded-full border-2 border-solid"
+    style={{ borderColor: color }}
+  />
 );
 
 export default CircleEmpty;
diff --git a/packages/extension/src/view/design-system/components/circle/index.tsx b/packages/extension/src/view/design-system/components/circle/index.tsx
index fdb0ab56..ce95d384 100644
--- a/packages/extension/src/view/design-system/components/circle/index.tsx
+++ b/packages/extension/src/view/design-system/components/circle/index.tsx
@@ -24,7 +24,7 @@ interface CircleProps {
 
 const Circle = ({ color }: CircleProps) => (
   <div
-    className="w-2.5 h-2.5 rounded-full flex items-center justify-center"
+    className="w-2.5 basis-0 h-2.5 rounded-full flex items-center justify-center"
     style={{ backgroundColor: color }}
   />
 );
diff --git a/packages/extension/src/view/design-system/components/circlePieChart/emptyCirclePieChart.tsx b/packages/extension/src/view/design-system/components/circlePieChart/emptyCirclePieChart.tsx
index df6fd6be..f99a4965 100644
--- a/packages/extension/src/view/design-system/components/circlePieChart/emptyCirclePieChart.tsx
+++ b/packages/extension/src/view/design-system/components/circlePieChart/emptyCirclePieChart.tsx
@@ -45,7 +45,7 @@ const EmptyCirclePieChart = ({
     <>
       <div
         className={classNames(
-          'h-full max-w-xs inline-block align-bottom',
+          'max-w-xs inline-block align-bottom',
           containerWidthClass
         )}
       >
diff --git a/packages/extension/src/view/design-system/components/circlePieChart/index.tsx b/packages/extension/src/view/design-system/components/circlePieChart/index.tsx
index 19dfd010..b78b7e01 100644
--- a/packages/extension/src/view/design-system/components/circlePieChart/index.tsx
+++ b/packages/extension/src/view/design-system/components/circlePieChart/index.tsx
@@ -62,10 +62,7 @@ const CirclePieChart = ({
   return (
     <>
       <div
-        className={classNames(
-          'h-full inline-block align-bottom',
-          containerWidthClass
-        )}
+        className={classNames('inline-block align-bottom', containerWidthClass)}
       >
         <div className="w-full h-full relative">
           <VictoryPie
@@ -78,7 +75,7 @@ const CirclePieChart = ({
           />
           <p
             className={classNames(
-              'absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 font-medium',
+              'absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 font-regular dark:text-bright-gray',
               centerTitleClasses
             )}
           >
@@ -87,7 +84,9 @@ const CirclePieChart = ({
         </div>
       </div>
       {title && (
-        <p className="text-xs text-center font-semibold mt-2">{title}</p>
+        <p className="text-xs text-center font-semibold mt-2 leading-relaxed dark:text-bright-gray">
+          {title}
+        </p>
       )}
     </>
   );
diff --git a/packages/extension/src/view/design-system/components/circlePieChart/stories/circlePieChart.stories.tsx b/packages/extension/src/view/design-system/components/circlePieChart/stories/circlePieChart.stories.tsx
index 11417830..81a182ef 100644
--- a/packages/extension/src/view/design-system/components/circlePieChart/stories/circlePieChart.stories.tsx
+++ b/packages/extension/src/view/design-system/components/circlePieChart/stories/circlePieChart.stories.tsx
@@ -52,7 +52,7 @@ export const Primary: StoryObj<typeof meta> = {
       },
       {
         count: 9,
-        color: COLOR_MAP.uncategorised,
+        color: COLOR_MAP.uncategorized,
       },
     ],
   },
@@ -82,7 +82,7 @@ export const Wide: StoryObj<typeof meta> = {
       },
       {
         count: 9,
-        color: COLOR_MAP.uncategorised,
+        color: COLOR_MAP.uncategorized,
       },
     ],
   },
@@ -112,7 +112,7 @@ export const Secondary: StoryObj<typeof meta> = {
       },
       {
         count: 9,
-        color: COLOR_MAP.uncategorised,
+        color: COLOR_MAP.uncategorized,
       },
     ],
   },
diff --git a/packages/extension/src/view/design-system/components/index.ts b/packages/extension/src/view/design-system/components/index.ts
index 24352f12..6e5be9ac 100644
--- a/packages/extension/src/view/design-system/components/index.ts
+++ b/packages/extension/src/view/design-system/components/index.ts
@@ -15,3 +15,8 @@
  */
 export { default as CirclePieChart } from './circlePieChart';
 export { default as Circle } from './circle';
+export { default as MatrixComponent } from './matrix/matrixComponent';
+export { default as MatrixComponentHorizontal } from './matrix/matrixComponent/matrixComponentHorizontal';
+export { default as Matrix } from './matrix';
+
+export type { MatrixComponentProps } from './matrix/matrixComponent';
diff --git a/packages/extension/src/view/design-system/components/matrix/index.tsx b/packages/extension/src/view/design-system/components/matrix/index.tsx
new file mode 100644
index 00000000..d0fa9005
--- /dev/null
+++ b/packages/extension/src/view/design-system/components/matrix/index.tsx
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * 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
+ *
+ *     https://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.
+ */
+/**
+ * External dependencies.
+ */
+import React from 'react';
+
+/**
+ * Internal dependencies.
+ */
+import MatrixComponent, { type MatrixComponentProps } from './matrixComponent';
+
+interface MatrixProps {
+  dataComponents: MatrixComponentProps[];
+}
+
+const Matrix = ({ dataComponents }: MatrixProps) => {
+  if (!dataComponents || !dataComponents.length) {
+    return null;
+  }
+
+  return (
+    <div className="grid grid-cols-2 gap-x-5" data-testid="matrix">
+      {dataComponents.map((dataComponent, index) => (
+        <MatrixComponent
+          key={index}
+          {...dataComponent}
+          containerClasses="p-3.5 border-b border-bright-gray dark:border-quartz"
+          countClassName={
+            dataComponent.countClassName + ' text-xxl leading-none'
+          }
+        />
+      ))}
+    </div>
+  );
+};
+
+export default Matrix;
diff --git a/packages/extension/src/view/design-system/components/matrix/matrixComponent/index.tsx b/packages/extension/src/view/design-system/components/matrix/matrixComponent/index.tsx
new file mode 100644
index 00000000..c1a50ca4
--- /dev/null
+++ b/packages/extension/src/view/design-system/components/matrix/matrixComponent/index.tsx
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * 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
+ *
+ *     https://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.
+ */
+/**
+ * External dependencies.
+ */
+import React from 'react';
+
+/**
+ * Internal dependencies.
+ */
+import Circle from '../../circle';
+
+export interface MatrixComponentProps {
+  color: string;
+  title: string;
+  description?: string;
+  count: number;
+  isExpanded?: boolean;
+  countClassName: string;
+  containerClasses: string;
+}
+
+const MatrixComponent = ({
+  color,
+  title,
+  description = '',
+  count,
+  isExpanded = false,
+  countClassName,
+  containerClasses,
+}: MatrixComponentProps) => {
+  return (
+    <div className={containerClasses}>
+      <div className="flex gap-x-4">
+        <Circle color={color} />
+        <div className="lg:max-w-[80%] lg:mr-8">
+          <h4 className="-mt-[3px] mb-1.5 text-xs font-medium dark:text-bright-gray">
+            {title}
+          </h4>
+          <div className={countClassName}>{count}</div>
+          {description && isExpanded && (
+            <p className="text-xs mt-1.5 text-darkest-gray dark:text-manatee">
+              {description}
+            </p>
+          )}
+        </div>
+      </div>
+    </div>
+  );
+};
+
+export default MatrixComponent;
diff --git a/packages/extension/src/view/design-system/components/matrix/matrixComponent/matrixComponentHorizontal.tsx b/packages/extension/src/view/design-system/components/matrix/matrixComponent/matrixComponentHorizontal.tsx
new file mode 100644
index 00000000..3ceefe3d
--- /dev/null
+++ b/packages/extension/src/view/design-system/components/matrix/matrixComponent/matrixComponentHorizontal.tsx
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * 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
+ *
+ *     https://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.
+ */
+/**
+ * External dependencies.
+ */
+import React from 'react';
+
+/**
+ * Internal dependencies.
+ */
+import CircleEmpty from '../../circle/circleEmpty';
+
+interface MatrixComponentHorizontalProps {
+  title: string;
+  description: string;
+  count: number;
+  expand?: boolean;
+  containerClasses?: string;
+}
+
+const MatrixComponentHorizontal = ({
+  title,
+  description,
+  count,
+  expand = false,
+  containerClasses,
+}: MatrixComponentHorizontalProps) => {
+  return (
+    <div className={containerClasses}>
+      <div className="max-w-[672px]">
+        <div className="flex justify-between items-center">
+          <div className="flex gap-4 items-center">
+            <CircleEmpty />
+            <h4 className="text-xs font-medium dark:text-bright-gray">
+              {title}
+            </h4>
+          </div>
+          <div className="flex gap-4 items-center">
+            <div className="w-[100px] h-1 bg-light-gray dark:bg-cultured" />
+            <div className="text-xs text-dark-gray font-semibold dark:text-bright-gray">
+              {count}
+            </div>
+          </div>
+        </div>
+        {description && expand && (
+          <div className="mt-2 ml-6 pl-px">
+            <p className="text-xs mt-1.5 text-darkest-gray dark:text-manatee">
+              {description}
+            </p>
+          </div>
+        )}
+      </div>
+    </div>
+  );
+};
+
+export default MatrixComponentHorizontal;
diff --git a/packages/extension/src/view/design-system/components/matrix/matrixComponent/stories/MatrixComponent.stories.tsx b/packages/extension/src/view/design-system/components/matrix/matrixComponent/stories/MatrixComponent.stories.tsx
new file mode 100644
index 00000000..e4c2b8f9
--- /dev/null
+++ b/packages/extension/src/view/design-system/components/matrix/matrixComponent/stories/MatrixComponent.stories.tsx
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * 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
+ *
+ *     https://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.
+ */
+/**
+ * External dependencies.
+ */
+import type { Meta, StoryObj } from '@storybook/react';
+
+/**
+ * Internal dependencies.
+ */
+import MatrixComponent from '..';
+import { COLOR_MAP } from '../../../../theme/colors';
+
+const meta: Meta<typeof MatrixComponent> = {
+  title: 'Extension/DesignSystem/Matrix/Component',
+  component: MatrixComponent,
+  tags: ['autodocs'],
+};
+
+export default meta;
+
+export const Primary: StoryObj<typeof meta> = {
+  args: {
+    title: 'Functional Cookies',
+    description:
+      'These are essential cookies that are necessary for a website to function properly. They enable basic functionalities such as page navigation, access to secure areas, and remembering user preferences (e.g., language, font size).',
+    color: COLOR_MAP.functional,
+    isExpanded: true,
+    countClassName: 'text-functional',
+  },
+};
diff --git a/packages/extension/src/view/design-system/components/matrix/matrixComponent/stories/matrixComponentHorizontal.stories.tsx b/packages/extension/src/view/design-system/components/matrix/matrixComponent/stories/matrixComponentHorizontal.stories.tsx
new file mode 100644
index 00000000..7dd89750
--- /dev/null
+++ b/packages/extension/src/view/design-system/components/matrix/matrixComponent/stories/matrixComponentHorizontal.stories.tsx
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * 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
+ *
+ *     https://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.
+ */
+/**
+ * External dependencies.
+ */
+import type { Meta, StoryObj } from '@storybook/react';
+
+/**
+ * Internal dependencies.
+ */
+import MatrixComponentHorizontal from '../matrixComponentHorizontal';
+
+const meta: Meta<typeof MatrixComponentHorizontal> = {
+  title: 'Extension/DesignSystem/Matrix/ComponentHorizontal',
+  component: MatrixComponentHorizontal,
+  tags: ['autodocs'],
+};
+
+export default meta;
+
+export const Default: StoryObj<typeof meta> = {
+  args: {
+    title: 'Invalid Cookies',
+    description:
+      'The cookies which could not be stored in the cookie jar of the browser as they were invalid.',
+    count: 20,
+    expand: true,
+  },
+};
diff --git a/packages/extension/src/view/design-system/components/matrix/stories/matrix.stories.tsx b/packages/extension/src/view/design-system/components/matrix/stories/matrix.stories.tsx
new file mode 100644
index 00000000..a2b1e7df
--- /dev/null
+++ b/packages/extension/src/view/design-system/components/matrix/stories/matrix.stories.tsx
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * 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
+ *
+ *     https://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.
+ */
+/**
+ * External dependencies.
+ */
+import type { Meta, StoryObj } from '@storybook/react';
+
+/**
+ * Internal dependencies.
+ */
+import Matrix from '..';
+
+const meta: Meta<typeof Matrix> = {
+  title: 'Extension/DesignSystem/Matrix',
+  component: Matrix,
+  tags: ['autodocs'],
+};
+
+export default meta;
+
+export const Primary: StoryObj<typeof meta> = {
+  args: {
+    dataComponents: [
+      {
+        count: 7,
+        color: '#5CC971',
+        countClassName: 'text-functional',
+        description:
+          'These are essential cookies that are necessary for a website to function properly. They enable basic functionalities such as page navigation, access to secure areas, and remembering user preferences (e.g., language, font size), etc.',
+        title: 'Functional',
+        isExpanded: true,
+        containerClasses: '',
+      },
+      {
+        count: 9,
+        color: '#F3AE4E',
+        countClassName: 'text-marketing',
+        description:
+          "They are used to track visitors across websites to gather information about their browsing habits. The data collected is often used by advertisers to deliver targeted advertisements that are relevant to the user's interests.",
+        title: 'Marketing',
+        isExpanded: true,
+        containerClasses: '',
+      },
+      {
+        count: 2,
+        color: '#4C79F4',
+        countClassName: 'text-analytics',
+        description:
+          'Used to gather information about how users interact with a website. They provide website owners with insights into user behavior, such as the number of visitors, the most popular pages, and the average time spent on the site. This data helps website owners understand and improve the user experience, optimize content, and identify areas for enhancement.',
+        title: 'Analytics',
+        isExpanded: true,
+        containerClasses: '',
+      },
+      {
+        count: 23,
+        color: '#EC7159',
+        countClassName: 'text-uncategorized',
+        description:
+          'We are unable to categorize certain cookies since we do not possess any relevant information about them. Nonetheless, you may visit sites like cookiedatabase.org and cookiesearch.org to acquire additional details about these cookies.',
+        title: 'Uncategorized',
+        isExpanded: true,
+        containerClasses: '',
+      },
+    ],
+  },
+};
diff --git a/packages/extension/src/view/design-system/theme/colors.ts b/packages/extension/src/view/design-system/theme/colors.ts
index 0f068b4f..89840da8 100644
--- a/packages/extension/src/view/design-system/theme/colors.ts
+++ b/packages/extension/src/view/design-system/theme/colors.ts
@@ -18,7 +18,7 @@ export const COLOR_MAP = {
   functional: '#5CC971',
   marketing: '#F3AE4E',
   analytics: '#4C79F4',
-  uncategorised: '#EC7159',
-  brightGray: '#EBEBEB',
+  uncategorized: '#EC7159',
+  brightGray: '#E8EAED',
   mediumGray: '#BDBDBD',
 };
diff --git a/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/cookiesMatrix/index.tsx b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/cookiesMatrix/index.tsx
new file mode 100644
index 00000000..e73a60c0
--- /dev/null
+++ b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/cookiesMatrix/index.tsx
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * 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
+ *
+ *     https://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.
+ */
+/**
+ * External dependencies.
+ */
+import React, { useState } from 'react';
+
+/**
+ * Internal dependencies.
+ */
+import {
+  MatrixComponentHorizontal,
+  Matrix,
+  type MatrixComponentProps,
+} from '../../../../../../design-system/components';
+import { getInvalidCookies } from '../../utils/getInvalidCookies';
+import { filterFramesWithCookies } from '../../utils/filterFramesWithCookies';
+import type {
+  TabCookies,
+  TabFrames,
+  CookieStatsComponents,
+} from '../../../../../cookies.types';
+
+interface CookiesMatrixProps {
+  tabCookies: TabCookies | null;
+  cookiesStatsComponents: CookieStatsComponents;
+  tabFrames: TabFrames | null;
+}
+
+interface LegendData {
+  [key: string]: {
+    description: string;
+    countClassName: string;
+  };
+}
+
+const LEGEND_DATA: LegendData = {
+  Functional: {
+    description:
+      'These are essential cookies that are necessary for a website to function properly. They enable basic functionalities such as page navigation, access to secure areas, and remembering user preferences (e.g., language, font size), etc.',
+    countClassName: 'text-functional',
+  },
+  Marketing: {
+    description:
+      "They are used to track visitors across websites to gather information about their browsing habits. The data collected is often used by advertisers to deliver targeted advertisements that are relevant to the user's interests.",
+    countClassName: 'text-marketing',
+  },
+  Analytics: {
+    description:
+      'Used to gather information about how users interact with a website. They provide website owners with insights into user behavior, such as the number of visitors, the most popular pages, and the average time spent on the site. This data helps website owners understand and improve the user experience, optimize content, and identify areas for enhancement.',
+    countClassName: 'text-analytics',
+  },
+  Uncategorized: {
+    description:
+      'We are unable to categorize certain cookies since we do not possess any relevant information about them. Nonetheless, you may visit sites like cookiedatabase.org and cookiesearch.org to acquire additional details about these cookies.',
+    countClassName: 'text-uncategorized',
+  },
+};
+
+const CookiesMatrix = ({
+  tabCookies,
+  cookiesStatsComponents,
+  tabFrames,
+}: CookiesMatrixProps) => {
+  const [isExpanded, setIsExpanded] = useState(false);
+
+  const dataComponents: MatrixComponentProps[] =
+    cookiesStatsComponents.legend.map((component) => {
+      const additionalDataComponent = LEGEND_DATA[component.label] || {};
+      const comp = {
+        ...component,
+        ...additionalDataComponent,
+        title: component.label,
+        isExpanded,
+        containerClasses: '',
+      };
+
+      return comp;
+    });
+
+  const invalidCookies = getInvalidCookies(tabCookies);
+  const totalFrames = tabFrames ? Object.keys(tabFrames).length : 0;
+  const framesWithCookies = filterFramesWithCookies(tabCookies, tabFrames);
+
+  const matrixHorizontalComponents = [
+    {
+      title: 'Invalid Cookies',
+      description:
+        "Cookies which were deemed invalid and therefore not saved in the browser's cookie store.",
+      count: invalidCookies ? Object.keys(invalidCookies).length : 0,
+      expand: isExpanded,
+    },
+    {
+      title: 'Number of Frames',
+      description: 'Number of frames found on the page.',
+      count: totalFrames,
+      expand: isExpanded,
+    },
+    {
+      title: 'Number of Frames with Associated Cookies',
+      description: 'Frames that have cookies associated with them',
+      count: framesWithCookies ? Object.keys(framesWithCookies).length : 0,
+      expand: isExpanded,
+    },
+  ];
+
+  return (
+    <div className="w-full" data-testid="cookies-matrix">
+      <div>
+        <div className="flex gap-x-5 justify-between">
+          <h4 className="pb-3 flex-1 grow border-b border-bright-gray dark:border-quartz text-xs font-bold text-darkest-gray dark:text-bright-gray uppercase">
+            Cookies Matrix
+          </h4>
+          <h4 className="pb-3 flex-1 grow border-b border-bright-gray dark:border-quartz text-xs font-bold text-darkest-gray dark:text-bright-gray text-right">
+            <button onClick={() => setIsExpanded((state) => !state)}>
+              {isExpanded ? 'Collapse View' : 'Expand View'}
+            </button>
+          </h4>
+        </div>
+        <Matrix dataComponents={dataComponents} />
+      </div>
+      <div>
+        {matrixHorizontalComponents.map((matrixHorizontalComponent, index) => (
+          <MatrixComponentHorizontal
+            key={index}
+            {...matrixHorizontalComponent}
+            containerClasses="px-3.5 py-4"
+          />
+        ))}
+      </div>
+    </div>
+  );
+};
+
+export default CookiesMatrix;
diff --git a/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/cookiesMatrix/stories/cookiesMatrix.stories.tsx b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/cookiesMatrix/stories/cookiesMatrix.stories.tsx
new file mode 100644
index 00000000..2315d2b7
--- /dev/null
+++ b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/cookiesMatrix/stories/cookiesMatrix.stories.tsx
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * 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
+ *
+ *     https://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.
+ */
+/**
+ * External dependencies.
+ */
+import type { Meta, StoryObj } from '@storybook/react';
+
+/**
+ * Internal dependencies.
+ */
+import CookiesMatrix from '..';
+import cookiesStatsComponents from '../../../../../../../../utils/test-data/cookiesStatsComponents';
+
+const meta: Meta<typeof CookiesMatrix> = {
+  title: 'Extension/DevTools/CookiesLandingPage/CookiesMatrix',
+  component: CookiesMatrix,
+  tags: ['autodocs'],
+};
+
+export default meta;
+
+export const Primary: StoryObj<typeof meta> = {
+  args: {
+    tabCookies: {
+      _GRECAPTCHA: {
+        // @ts-ignore
+        analytics: {
+          category: 'Functional',
+        },
+        isFirstParty: false,
+        // @ts-ignore
+        parsedCookie: {
+          domain: '.google.com',
+        },
+        url: 'https://www.google.com/recaptcha/api2/reload?k=6Le6JpwaAAAAAFkASVap1OUThl-lQSJC0r9kLl2I',
+        isCookieSet: false,
+      },
+      _ga: {
+        // @ts-ignore
+        analytics: {
+          category: 'Analytics',
+        },
+        isFirstParty: true,
+        // @ts-ignore
+        parsedCookie: {
+          domain: '.rtcamp.com',
+        },
+        url: 'https://rtcamp.com/',
+        isCookieSet: true,
+      },
+    },
+    cookiesStatsComponents: cookiesStatsComponents,
+    tabFrames: {
+      'https://example.com': {
+        frameIds: [0, 0],
+      },
+      'https://www.google.com': {
+        frameIds: [6169, 6172, 6169, 6172],
+      },
+    },
+  },
+};
diff --git a/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/index.tsx b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/index.tsx
index ec6a1f58..47481049 100644
--- a/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/index.tsx
+++ b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/index.tsx
@@ -18,8 +18,40 @@
  */
 import React from 'react';
 
+/**
+ * Internal dependencies.
+ */
+import LandingHeader from './landingHeader';
+import CookiesMatrix from './cookiesMatrix';
+import { useCookieStore } from '../../../../stateProviders/syncCookieStore';
+import prepareCookiesCount from '../../../../../../utils/prepareCookiesCount';
+import { prepareCookieStatsComponents } from '../../../../../../utils/prepareCookieStatsComponents';
+
 const CookiesLanding = () => {
-  return <p>Landing page placeholder</p>;
+  const { tabCookies, tabFrames, tabUrl } = useCookieStore(({ state }) => ({
+    tabFrames: state.tabFrames,
+    tabCookies: state.tabCookies,
+    tabUrl: state.tabUrl,
+  }));
+
+  const cookieStats = prepareCookiesCount(tabCookies, tabUrl);
+  const cookiesStatsComponents = prepareCookieStatsComponents(cookieStats);
+
+  return (
+    <div className="h-full w-full" data-testid="cookies-landing">
+      <LandingHeader
+        cookieStats={cookieStats}
+        cookiesStatsComponents={cookiesStatsComponents}
+      />
+      <div className="lg:max-w-[729px] mx-auto flex justify-center mt-10 pb-28 px-4">
+        <CookiesMatrix
+          tabCookies={tabCookies}
+          cookiesStatsComponents={cookiesStatsComponents}
+          tabFrames={tabFrames}
+        />
+      </div>
+    </div>
+  );
 };
 
 export default CookiesLanding;
diff --git a/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/landingHeader/index.tsx b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/landingHeader/index.tsx
new file mode 100644
index 00000000..46736226
--- /dev/null
+++ b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/landingHeader/index.tsx
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * 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
+ *
+ *     https://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.
+ */
+/**
+ * External dependencies.
+ */
+import React from 'react';
+
+/**
+ * Internal dependencies.
+ */
+import { CirclePieChart } from '../../../../../../design-system/components';
+import type { CookiesCount } from '../../../../../../popup/types';
+import type { CookieStatsComponents } from '../../../../../cookies.types';
+
+interface DataMapping {
+  title: string;
+  count: number;
+  data: {
+    count: number;
+    color: string;
+  }[];
+}
+
+interface LandingHeaderProps {
+  cookieStats: CookiesCount;
+  cookiesStatsComponents: CookieStatsComponents;
+}
+
+const LandingHeader = ({
+  cookieStats,
+  cookiesStatsComponents,
+}: LandingHeaderProps) => {
+  const dataMapping: DataMapping[] = [
+    {
+      title: 'Total cookies',
+      count: cookieStats.total,
+      data: cookiesStatsComponents.legend,
+    },
+    {
+      title: '1st party cookies',
+      count: cookieStats.firstParty.total,
+      data: cookiesStatsComponents.firstParty,
+    },
+    {
+      title: '3rd party cookies',
+      count: cookieStats.thirdParty.total,
+      data: cookiesStatsComponents.thirdParty,
+    },
+  ];
+
+  return (
+    <div
+      className="flex justify-center border-b border-hex-gray pt-5 pb-5 dark:border-quartz"
+      data-testid="cookies-landing-header"
+    >
+      <div className="lg:max-w-[729px] flex gap-9 px-4">
+        {dataMapping.map((circleData, index) => {
+          return (
+            <div key={index} className="text-center w-16">
+              <CirclePieChart
+                title={circleData.title}
+                centerCount={circleData.count}
+                data={circleData.data}
+              />
+            </div>
+          );
+        })}
+      </div>
+    </div>
+  );
+};
+
+export default LandingHeader;
diff --git a/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/landingHeader/stories/LandingHeader.stories.tsx b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/landingHeader/stories/LandingHeader.stories.tsx
new file mode 100644
index 00000000..5d0710e7
--- /dev/null
+++ b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/landingHeader/stories/LandingHeader.stories.tsx
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * 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
+ *
+ *     https://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.
+ */
+/*
+ * Copyright 2023 Google LLC
+ *
+ * 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
+ *
+ *     https://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.
+ */
+/**
+ * External dependencies.
+ */
+import type { Meta, StoryObj } from '@storybook/react';
+
+/**
+ * Internal dependencies.
+ */
+import LandingHeader from '..';
+import cookiesStatsComponents from '../../../../../../../../utils/test-data/cookiesStatsComponents';
+import cookieStats from '../../../../../../../../utils/test-data/cookieStats';
+
+const meta: Meta<typeof LandingHeader> = {
+  title: 'Extension/DevTools/CookiesLandingPage/Header',
+  component: LandingHeader,
+};
+
+export default meta;
+
+export const Primary: StoryObj<typeof meta> = {
+  args: {
+    cookieStats,
+    cookiesStatsComponents,
+  },
+};
diff --git a/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/stories/cookiesLanding.stories.tsx b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/stories/cookiesLanding.stories.tsx
new file mode 100644
index 00000000..1002d294
--- /dev/null
+++ b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/stories/cookiesLanding.stories.tsx
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * 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
+ *
+ *     https://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.
+ */
+/**
+ * External dependencies.
+ */
+import type { Meta, StoryObj } from '@storybook/react';
+
+/**
+ * Internal dependencies.
+ */
+import CookiesLanding from '..';
+
+const meta: Meta<typeof CookiesLanding> = {
+  title: 'Extension/DevTools/CookiesLandingPage/Page',
+  component: CookiesLanding,
+  tags: ['autodocs'],
+};
+
+export default meta;
+
+export const Primary: StoryObj<typeof meta> = {
+  args: {},
+};
diff --git a/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/cookieDetails/details.tsx b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/cookieDetails/details.tsx
index 1cf1c510..fd60f144 100644
--- a/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/cookieDetails/details.tsx
+++ b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/cookieDetails/details.tsx
@@ -22,7 +22,7 @@ import React, { useState } from 'react';
 /**
  * Internal dependencies.
  */
-import type { CookieTableData } from '../../../../../stateProviders/syncCookieStore';
+import type { CookieTableData } from '../../../../../cookies.types';
 
 export interface DetailsProps {
   selectedCookie: CookieTableData;
diff --git a/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/cookieDetails/stories/details.stories.ts b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/cookieDetails/stories/details.stories.ts
index 832a8a23..0420520e 100644
--- a/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/cookieDetails/stories/details.stories.ts
+++ b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/cookieDetails/stories/details.stories.ts
@@ -22,7 +22,7 @@ import type { Meta, StoryObj } from '@storybook/react';
  * Internal dependencies.
  */
 import Details from '../details';
-import type { CookieTableData } from '../../../../../../stateProviders/syncCookieStore';
+import type { CookieTableData } from '../../../../../../cookies.types';
 
 const meta = {
   title: 'Extension/DevTools/CookiesPanel/CookieDetails/Details',
diff --git a/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/cookieTable/index.tsx b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/cookieTable/index.tsx
index d3366c1d..ad79658c 100644
--- a/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/cookieTable/index.tsx
+++ b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/cookieTable/index.tsx
@@ -31,7 +31,7 @@ import {
 import Table from '../../../../table';
 import { useContentPanelStore } from '../../../../../stateProviders/contentPanelStore';
 import { Check } from '../../../../../../../icons';
-import type { CookieTableData } from '../../../../../stateProviders/syncCookieStore';
+import type { CookieTableData } from '../../../../../cookies.types';
 
 export interface CookieTableProps {
   cookies: CookieTableData[];
@@ -101,7 +101,7 @@ const tableColumns: ColumnDef<CookieTableData>[] = [
   {
     header: 'Category',
     accessorKey: 'analytics.category',
-    cell: (info) => (info.getValue() ? info.getValue() : 'Uncategorised'),
+    cell: (info) => (info.getValue() ? info.getValue() : 'Uncategorized'),
   },
   {
     header: 'Third Party',
diff --git a/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/cookieTable/stories/tempData.ts b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/cookieTable/stories/tempData.ts
index bc0a7d7d..5de99be9 100644
--- a/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/cookieTable/stories/tempData.ts
+++ b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/cookieTable/stories/tempData.ts
@@ -23,7 +23,7 @@ import type { Cookie as ParsedCookie } from 'simple-cookie';
  * Internal dependencies.
  */
 import type { CookieAnalytics } from '../../../../../../../../utils/fetchCookieDictionary';
-import type { CookieTableData } from '../../../../../../stateProviders/syncCookieStore';
+import type { CookieTableData } from '../../../../../../cookies.types';
 
 export const TempCookieData: CookieTableData[] = [
   {
diff --git a/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/index.tsx b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/index.tsx
index f18b7e8b..1c4d8c92 100644
--- a/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/index.tsx
+++ b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/index.tsx
@@ -22,12 +22,10 @@ import { Resizable } from 're-resizable';
 /**
  * Internal dependencies.
  */
-import {
-  type CookieTableData,
-  useCookieStore,
-} from '../../../../stateProviders/syncCookieStore';
+import { useCookieStore } from '../../../../stateProviders/syncCookieStore';
 import CookieDetails from './cookieDetails';
 import CookieTable from './cookieTable';
+import { filterCookiesByFrame } from '../utils/filterCookiesByFrame';
 
 const CookiesListing = () => {
   const { cookies, selectedFrame, tabFrames } = useCookieStore(({ state }) => ({
@@ -36,19 +34,10 @@ const CookiesListing = () => {
     tabFrames: state.tabFrames,
   }));
 
-  const calculatedCookies = useMemo(() => {
-    const frameFilteredCookies: { [key: string]: CookieTableData } = {};
-    if (cookies && selectedFrame && tabFrames && tabFrames[selectedFrame]) {
-      Object.entries(cookies).forEach(([key, cookie]) => {
-        tabFrames[selectedFrame].frameIds?.forEach((frameId) => {
-          if (cookie.frameIdList?.includes(frameId)) {
-            frameFilteredCookies[key] = cookie;
-          }
-        });
-      });
-    }
-    return Object.values(frameFilteredCookies);
-  }, [cookies, selectedFrame, tabFrames]);
+  const filteredCookies = useMemo(
+    () => filterCookiesByFrame(cookies, tabFrames, selectedFrame),
+    [cookies, selectedFrame, tabFrames]
+  );
 
   return (
     <div className="h-full flex flex-col">
@@ -66,10 +55,7 @@ const CookiesListing = () => {
           left: false,
         }}
       >
-        <CookieTable
-          cookies={calculatedCookies}
-          selectedFrame={selectedFrame}
-        />
+        <CookieTable cookies={filteredCookies} selectedFrame={selectedFrame} />
       </Resizable>
       <div className="w-full h-full border border-gray-300 dark:border-quartz shadow overflow-auto">
         <CookieDetails />
diff --git a/packages/extension/src/view/devtools/components/tabContent/cookies/utils/filterCookiesByFrame.ts b/packages/extension/src/view/devtools/components/tabContent/cookies/utils/filterCookiesByFrame.ts
new file mode 100644
index 00000000..762fb269
--- /dev/null
+++ b/packages/extension/src/view/devtools/components/tabContent/cookies/utils/filterCookiesByFrame.ts
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * 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
+ *
+ *     https://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.
+ */
+/**
+ * Internal dependencies.
+ */
+import { type CookieTableData } from '../../../../cookies.types';
+
+interface Cookies {
+  [key: string]: CookieTableData;
+}
+
+interface TabFrames {
+  [key: string]: { frameIds: number[] };
+}
+
+export const filterCookiesByFrame = (
+  cookies: Cookies | null,
+  tabFrames: TabFrames | null,
+  frameUrl: string | null
+) => {
+  const frameFilteredCookies: { [key: string]: CookieTableData } = {};
+
+  if (cookies && frameUrl && tabFrames && tabFrames[frameUrl]) {
+    Object.entries(cookies).forEach(([key, cookie]) => {
+      tabFrames[frameUrl].frameIds?.forEach((frameId) => {
+        if (cookie.frameIdList?.includes(frameId)) {
+          frameFilteredCookies[key] = cookie;
+        }
+      });
+    });
+  }
+
+  return Object.values(frameFilteredCookies);
+};
diff --git a/packages/extension/src/view/devtools/components/tabContent/cookies/utils/filterFramesWithCookies.ts b/packages/extension/src/view/devtools/components/tabContent/cookies/utils/filterFramesWithCookies.ts
new file mode 100644
index 00000000..e570650c
--- /dev/null
+++ b/packages/extension/src/view/devtools/components/tabContent/cookies/utils/filterFramesWithCookies.ts
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * 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
+ *
+ *     https://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.
+ */
+/**
+ * Internal dependencies.
+ */
+import { filterCookiesByFrame } from './filterCookiesByFrame';
+import type {
+  TabCookies,
+  TabFrames,
+  FramesWithCookies,
+} from '../../../../cookies.types';
+
+export const filterFramesWithCookies = (
+  tabCookies: TabCookies | null,
+  tabFrames: TabFrames | null
+): FramesWithCookies => {
+  const framesWithCookies: FramesWithCookies = {};
+
+  if (!tabCookies || !tabFrames) {
+    return framesWithCookies;
+  }
+
+  Object.keys(tabFrames).forEach((frameUrl) => {
+    const cookies = filterCookiesByFrame(tabCookies, tabFrames, frameUrl);
+
+    if (cookies.length) {
+      framesWithCookies[frameUrl] = tabFrames[frameUrl];
+    }
+  });
+
+  return framesWithCookies;
+};
diff --git a/packages/extension/src/view/devtools/components/tabContent/cookies/utils/getInvalidCookies.ts b/packages/extension/src/view/devtools/components/tabContent/cookies/utils/getInvalidCookies.ts
new file mode 100644
index 00000000..b0f4068c
--- /dev/null
+++ b/packages/extension/src/view/devtools/components/tabContent/cookies/utils/getInvalidCookies.ts
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * 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
+ *
+ *     https://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.
+ */
+/**
+ * Internal dependencies.
+ */
+import type { TabCookies } from '../../../../cookies.types';
+
+export const getInvalidCookies = (cookies: TabCookies | null): TabCookies => {
+  const invalidCookies: TabCookies = {};
+
+  if (cookies) {
+    Object.entries(cookies).forEach(([name, cookie]) => {
+      if (false === cookie.isCookieSet) {
+        invalidCookies[name] = cookie;
+      }
+    });
+  }
+
+  return invalidCookies;
+};
diff --git a/packages/extension/src/view/devtools/components/table/index.tsx b/packages/extension/src/view/devtools/components/table/index.tsx
index ca7bb567..21d65355 100644
--- a/packages/extension/src/view/devtools/components/table/index.tsx
+++ b/packages/extension/src/view/devtools/components/table/index.tsx
@@ -25,7 +25,7 @@ import type { Table as ReactTable } from '@tanstack/react-table';
  */
 import TableHeader from './tableHeader';
 import TableBody from './tableBody';
-import type { CookieTableData } from '../../stateProviders/syncCookieStore';
+import type { CookieTableData } from '../../cookies.types';
 import ColumnMenu from './columnMenu';
 
 export type TableData = CookieTableData;
diff --git a/packages/extension/src/view/devtools/cookies.types.ts b/packages/extension/src/view/devtools/cookies.types.ts
new file mode 100644
index 00000000..36cb5d7f
--- /dev/null
+++ b/packages/extension/src/view/devtools/cookies.types.ts
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * 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
+ *
+ *     https://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.
+ */
+/**
+ * Internal dependencies.
+ */
+import type { CookieData } from '../../localStore';
+
+export type CookieTableData = CookieData & {
+  isIbcCompliant: boolean | null;
+  isCookieSet: boolean | null;
+};
+
+export interface TabCookies {
+  [key: string]: CookieTableData;
+}
+
+export interface TabFrames {
+  [key: string]: { frameIds: number[] };
+}
+
+export interface Legend {
+  label: string;
+  count: number;
+  color: string;
+  countClassName: string;
+}
+
+export interface CookieStatsComponents {
+  legend: Legend[];
+  firstParty: {
+    count: number;
+    color: string;
+  }[];
+  thirdParty: {
+    count: number;
+    color: string;
+  }[];
+}
+
+export interface FramesWithCookies {
+  [key: string]: { frameIds: number[] };
+}
diff --git a/packages/extension/src/view/devtools/stateProviders/contentPanelStore/index.tsx b/packages/extension/src/view/devtools/stateProviders/contentPanelStore/index.tsx
index 693f4153..6673e0dc 100644
--- a/packages/extension/src/view/devtools/stateProviders/contentPanelStore/index.tsx
+++ b/packages/extension/src/view/devtools/stateProviders/contentPanelStore/index.tsx
@@ -27,7 +27,7 @@ import { useContextSelector, createContext } from 'use-context-selector';
 /**
  * Internal dependencies.
  */
-import { type CookieTableData } from '../syncCookieStore';
+import { type CookieTableData } from '../../cookies.types';
 
 export interface ContentPanelStore {
   state: {
diff --git a/packages/extension/src/view/devtools/stateProviders/syncCookieStore/index.tsx b/packages/extension/src/view/devtools/stateProviders/syncCookieStore/index.tsx
index 30f67cc9..3cd6ed81 100644
--- a/packages/extension/src/view/devtools/stateProviders/syncCookieStore/index.tsx
+++ b/packages/extension/src/view/devtools/stateProviders/syncCookieStore/index.tsx
@@ -29,21 +29,13 @@ import React, {
  */
 import type { CookieData } from '../../../../localStore';
 import { checkIbcCompliance } from '../../../../utils/checkIbcCompliance';
-
-export type CookieTableData = CookieData & {
-  isIbcCompliant: boolean | null;
-  isCookieSet: boolean | null;
-};
+import type { TabCookies, TabFrames } from '../../cookies.types';
 
 export interface CookieStoreContext {
   state: {
-    tabCookies: {
-      [key: string]: CookieTableData;
-    } | null;
+    tabCookies: TabCookies | null;
     tabUrl: string | null;
-    tabFrames: {
-      [key: string]: { frameIds: number[] };
-    } | null;
+    tabFrames: TabFrames | null;
     selectedFrame: string | null;
   };
   actions: {
diff --git a/packages/extension/src/view/popup/app.tsx b/packages/extension/src/view/popup/app.tsx
index df76cf2c..ff6b8698 100644
--- a/packages/extension/src/view/popup/app.tsx
+++ b/packages/extension/src/view/popup/app.tsx
@@ -25,8 +25,8 @@ import React from 'react';
 import './app.css';
 import { Legend } from './components';
 import { useCookieStore } from './stateProviders/syncCookieStore';
-import { COLOR_MAP } from '../design-system/theme/colors';
 import { CirclePieChart } from '../design-system/components';
+import { prepareCookieStatsComponents } from '../../utils/prepareCookieStatsComponents';
 
 const App: React.FC = () => {
   const { cookieStats } = useCookieStore(({ state }) => ({
@@ -35,7 +35,7 @@ const App: React.FC = () => {
 
   if (!cookieStats) {
     return (
-      <div className="w-96 h-80 flex justify-center items-center flex-col">
+      <div className="w-96 h-fit p-5 flex justify-center items-center flex-col">
         <p className="font-bold text-lg">
           Please refresh this page to view cookies
         </p>
@@ -48,103 +48,36 @@ const App: React.FC = () => {
     cookieStats.thirdParty.total === 0
   ) {
     return (
-      <div className="w-96 h-80 flex justify-center items-center flex-col">
+      <div className="w-96 h-fit p-5 flex justify-center items-center flex-col">
         <p className="font-bold text-lg">No cookies found on this page</p>
       </div>
     );
   }
-  const legendData = [
-    {
-      label: 'Functional',
-      count:
-        cookieStats.firstParty.functional + cookieStats.thirdParty.functional,
-      color: COLOR_MAP.functional,
-    },
-    {
-      label: 'Marketing',
-      count:
-        cookieStats.firstParty.marketing + cookieStats.thirdParty.marketing,
-      color: COLOR_MAP.marketing,
-    },
-    {
-      label: 'Analytics',
-      count:
-        cookieStats.firstParty.analytics + cookieStats.thirdParty.analytics,
-      color: COLOR_MAP.analytics,
-    },
-    {
-      label: 'Uncategorised',
-      count:
-        cookieStats.firstParty.uncategorised +
-        cookieStats.thirdParty.uncategorised,
-      color: COLOR_MAP.uncategorised,
-    },
-  ];
 
-  const firstPartyPiechartData = [
-    {
-      count: cookieStats.firstParty.functional,
-      color: COLOR_MAP.functional,
-    },
-    {
-      count: cookieStats.firstParty.marketing,
-      color: COLOR_MAP.marketing,
-    },
-    {
-      count: cookieStats.firstParty.analytics,
-      color: COLOR_MAP.analytics,
-    },
-    {
-      count: cookieStats.firstParty.uncategorised,
-      color: COLOR_MAP.uncategorised,
-    },
-  ];
-
-  const thirdPartyPiechartData = [
-    {
-      count: cookieStats.thirdParty.functional,
-      color: COLOR_MAP.functional,
-    },
-    {
-      count: cookieStats.thirdParty.marketing,
-      color: COLOR_MAP.marketing,
-    },
-    {
-      count: cookieStats.thirdParty.analytics,
-      color: COLOR_MAP.analytics,
-    },
-    {
-      count: cookieStats.thirdParty.uncategorised,
-      color: COLOR_MAP.uncategorised,
-    },
-  ];
+  const statsComponents = prepareCookieStatsComponents(cookieStats);
 
   return (
-    <div className="w-96 h-80 flex justify-center items-center flex-col">
-      <div className="w-full flex-1 flex gap-16 px-12">
-        <div className="w-full h-full flex flex-col justify-center items-center">
-          <div className="w-full text-center">
-            <CirclePieChart
-              centerCount={cookieStats.firstParty.total}
-              data={firstPartyPiechartData}
-              title="1st Party Cookies"
-            />
-          </div>
+    <div className="w-96 h-fit p-5 flex justify-center items-center flex-col">
+      <div className="w-full flex gap-x-6 justify-center border-b border-hex-gray pb-3.5">
+        <div className="w-28 text-center">
+          <CirclePieChart
+            centerCount={cookieStats.firstParty.total}
+            data={statsComponents.firstParty}
+            title="1st Party Cookies"
+          />
         </div>
-        <div className="w-full h-full flex flex-col justify-center items-center">
-          <div className="w-full text-center">
-            <CirclePieChart
-              centerCount={cookieStats.thirdParty.total}
-              data={thirdPartyPiechartData}
-              title="3rd Party Cookies"
-            />
-          </div>
+        <div className="w-28 text-center">
+          <CirclePieChart
+            centerCount={cookieStats.thirdParty.total}
+            data={statsComponents.thirdParty}
+            title="3rd Party Cookies"
+          />
         </div>
       </div>
-      <div className="mt-3">
-        <Legend legendItemList={legendData} />
+      <div className="w-full mb-4">
+        <Legend legendItemList={statsComponents.legend} />
       </div>
-      <div className="w-full text-center mt-5 px-3 mb-3">
+      <div className="w-full text-center">
         <p className="text-chart-label text-xs">
           {'Inspect cookies in the "Privacy Sandbox" panel of DevTools'}
         </p>
diff --git a/packages/extension/src/view/popup/components/legend/index.tsx b/packages/extension/src/view/popup/components/legend/index.tsx
index c27f3f33..efe37a24 100644
--- a/packages/extension/src/view/popup/components/legend/index.tsx
+++ b/packages/extension/src/view/popup/components/legend/index.tsx
@@ -21,24 +21,30 @@ import React from 'react';
 /**
  * Internal dependencies.
  */
-import { Circle } from '../../../design-system/components';
+import {
+  Matrix,
+  type MatrixComponentProps,
+} from '../../../design-system/components';
+import { type Legend as LegendProp } from '../../../devtools/cookies.types';
 
 interface LegendProps {
-  legendItemList: { label: string; count: number; color: string }[];
+  legendItemList: LegendProp[];
 }
 
 const Legend = ({ legendItemList }: LegendProps) => {
-  return (
-    <div className="flex flex-col">
-      {legendItemList.map(({ label, count, color }, index) => (
-        <div key={index} className="w-36 flex items-center justify-center my-1">
-          <Circle color={color} />
-          <p className="flex-1 text-chart-label text-xs ml-2">{label}</p>
-          <p className="text-chart-label text-xs">{count}</p>
-        </div>
-      ))}
-    </div>
+  const dataComponents: MatrixComponentProps[] = legendItemList.map(
+    ({ label, count, color, countClassName }) => {
+      return {
+        color,
+        title: label,
+        count,
+        countClassName: countClassName,
+        containerClasses: '',
+      };
+    }
   );
+
+  return <Matrix dataComponents={dataComponents} />;
 };
 
 export default Legend;
diff --git a/packages/extension/src/view/popup/components/legend/stories/legend.stories.tsx b/packages/extension/src/view/popup/components/legend/stories/legend.stories.tsx
index 458948ce..b7e4f91d 100644
--- a/packages/extension/src/view/popup/components/legend/stories/legend.stories.tsx
+++ b/packages/extension/src/view/popup/components/legend/stories/legend.stories.tsx
@@ -35,10 +35,30 @@ export default meta;
 export const Primary: StoryObj<typeof meta> = {
   args: {
     legendItemList: [
-      { label: 'Functional', count: 10, color: COLOR_MAP.functional },
-      { label: 'Marketing', count: 20, color: COLOR_MAP.marketing },
-      { label: 'Analytics', count: 22, color: COLOR_MAP.analytics },
-      { label: 'Uncategorised', count: 11, color: COLOR_MAP.uncategorised },
+      {
+        label: 'Functional',
+        count: 10,
+        color: COLOR_MAP.functional,
+        countClassName: 'text-fuctional',
+      },
+      {
+        label: 'Marketing',
+        count: 20,
+        color: COLOR_MAP.marketing,
+        countClassName: 'text-marketing',
+      },
+      {
+        label: 'Analytics',
+        count: 22,
+        color: COLOR_MAP.analytics,
+        countClassName: 'text-analytics',
+      },
+      {
+        label: 'Uncategorized',
+        count: 11,
+        color: COLOR_MAP.uncategorized,
+        countClassName: 'text-uncategorized',
+      },
     ],
   },
 };
diff --git a/packages/extension/src/view/popup/stateProviders/syncCookieStore/index.tsx b/packages/extension/src/view/popup/stateProviders/syncCookieStore/index.tsx
index c8e02a7c..8bf331ce 100644
--- a/packages/extension/src/view/popup/stateProviders/syncCookieStore/index.tsx
+++ b/packages/extension/src/view/popup/stateProviders/syncCookieStore/index.tsx
@@ -29,12 +29,12 @@ import { useDebouncedCallback } from 'use-debounce';
  * Internal dependencies.
  */
 import { getCurrentTab } from '../../../../utils/getCurrentTabId';
-import type { CookieStats } from '../../types';
-import countCookiesByCategory from '../../../../utils/countCookiesByCategory';
+import type { CookiesCount } from '../../types';
+import prepareCookiesCount from '../../../../utils/prepareCookiesCount';
 
 export interface CookieStoreContext {
   state: {
-    tabCookieStats: CookieStats | null;
+    tabCookieStats: CookiesCount | null;
   };
   actions: object;
 }
@@ -48,14 +48,14 @@ const initialState: CookieStoreContext = {
         functional: 0,
         marketing: 0,
         analytics: 0,
-        uncategorised: 0,
+        uncategorized: 0,
       },
       thirdParty: {
         total: 0,
         functional: 0,
         marketing: 0,
         analytics: 0,
-        uncategorised: 0,
+        uncategorized: 0,
       },
     },
   },
@@ -92,7 +92,7 @@ export const Provider = ({ children }: PropsWithChildren) => {
     ];
 
     if (tabData && tabData.cookies) {
-      setDebouncedStats(countCookiesByCategory(tabData.cookies, _tabUrl));
+      setDebouncedStats(prepareCookiesCount(tabData.cookies, _tabUrl));
     }
   }, [setDebouncedStats]);
 
@@ -105,7 +105,7 @@ export const Provider = ({ children }: PropsWithChildren) => {
         changes[tabId.toString()]?.newValue?.cookies
       ) {
         setDebouncedStats(
-          countCookiesByCategory(
+          prepareCookiesCount(
             changes[tabId.toString()].newValue.cookies,
             tabUrl
           )
diff --git a/packages/extension/src/view/popup/stories/app.stories.tsx b/packages/extension/src/view/popup/stories/app.stories.tsx
new file mode 100644
index 00000000..e5b26486
--- /dev/null
+++ b/packages/extension/src/view/popup/stories/app.stories.tsx
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * 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
+ *
+ *     https://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.
+ */
+/**
+ * External dependencies.
+ */
+import React from 'react';
+import type { Meta, StoryObj } from '@storybook/react';
+
+/**
+ * Internal dependencies.
+ */
+import App from '../app';
+import { Provider as ExternalStoreProvider } from '../stateProviders/syncCookieStore';
+
+const meta: Meta<typeof App> = {
+  title: 'Extension/Popup/Page',
+  component: App,
+  tags: ['autodocs'],
+};
+
+export default meta;
+
+const dummyData = {
+  '2141247110': {
+    cookies: {
+      '1P_JAR': {
+        analytics: {
+          category: 'Marketing',
+        },
+        isFirstParty: false,
+        parsedCookie: {
+          domain: '.google.com',
+        },
+        url: 'https://www.google.com/recaptcha/api2/aframe',
+      },
+      APC: {
+        analytics: {
+          category: '',
+        },
+        isFirstParty: false,
+        parsedCookie: {
+          domain: 'doubleclick.net',
+        },
+        url: 'https://googleads.g.doubleclick.net/pagead/interaction/?ai=&sigh=BpnfxIaauQU&cid=CAQSTgBpAlJWJhG957iiPQM-u9Qi61mWPR6eFTTarfv0pqg0yxpObU1_f5mCWO4La9fQkQf2SlgLdpmUB0N0XlWgQmSnfEk9qN-Hfek6Nz3Jgg&label=window_focus&gqid&qqid=COK0kMOX24ADFZKjZgIdQBMBDQ&fg=1',
+      },
+      AWSALB: {
+        analytics: {
+          category: 'Functional',
+        },
+        isFirstParty: false,
+        parsedCookie: {
+          domain: '.dotmetrics.net',
+        },
+        url: 'https://uk-script.dotmetrics.net/BeaconEvent.dotmetrics?1691982913096',
+      },
+      AWSALBCORS: {
+        analytics: {
+          category: 'Functional',
+        },
+        isFirstParty: false,
+        parsedCookie: {
+          domain: 'uk-script.dotmetrics.net',
+        },
+        url: 'https://uk-script.dotmetrics.net/BeaconEvent.dotmetrics?1691982913096',
+      },
+      AWSALBTG: {
+        analytics: {
+          category: 'Functional',
+        },
+        isFirstParty: false,
+        parsedCookie: {
+          domain: '.the-ozone-project.com',
+        },
+        url: 'https://elb.the-ozone-project.com/cookie_sync',
+      },
+      AWSALBTGCORS: {
+        analytics: {
+          category: 'Functional',
+        },
+        isFirstParty: false,
+        parsedCookie: {
+          domain: 'elb.the-ozone-project.com',
+        },
+        url: 'https://elb.the-ozone-project.com/cookie_sync',
+      },
+    },
+    focusedAt: 1691983869724,
+  },
+};
+
+const withExternalStoreProvider = () => {
+  // @todo Try to use sinon-chrome to mock the chrome API.
+  window.chrome = {
+    /* eslint-disable @typescript-eslint/no-empty-function */
+    storage: {
+      local: {
+        // @ts-ignore
+        onChanged: {
+          addListener: () => {},
+          removeListener: () => {},
+        },
+        // @ts-ignore
+        get() {
+          return dummyData;
+        },
+      },
+    },
+    tabs: {
+      // @ts-ignore
+      onUpdated: {
+        addListener: () => {},
+        removeListener: () => {},
+      },
+      // @ts-ignore
+      query() {
+        return [
+          {
+            id: '2141247110',
+            url: 'www.bbc.com',
+          },
+        ];
+      },
+    },
+    /* eslint-enable @typescript-eslint/no-empty-function */
+  };
+
+  return (
+    <ExternalStoreProvider>
+      <App />
+    </ExternalStoreProvider>
+  );
+};
+
+export const Primary: StoryObj<typeof meta> = {
+  args: {},
+  render: withExternalStoreProvider,
+};
diff --git a/packages/extension/src/view/popup/types.ts b/packages/extension/src/view/popup/types.ts
index 46c07a16..dafa2c68 100644
--- a/packages/extension/src/view/popup/types.ts
+++ b/packages/extension/src/view/popup/types.ts
@@ -14,20 +14,20 @@
  * limitations under the License.
  */
 
-export type CookieStats = {
+export type CookiesCount = {
   total: number;
   firstParty: {
     total: number;
     functional: number;
     marketing: number;
     analytics: number;
-    uncategorised: number;
+    uncategorized: number;
   };
   thirdParty: {
     total: number;
     functional: number;
     marketing: number;
     analytics: number;
-    uncategorised: number;
+    uncategorized: number;
   };
 };
diff --git a/packages/extension/tailwind.config.cjs b/packages/extension/tailwind.config.cjs
index 7f8e0941..8a83596e 100644
--- a/packages/extension/tailwind.config.cjs
+++ b/packages/extension/tailwind.config.cjs
@@ -40,6 +40,7 @@ module.exports = {
     fontSize: {
       ...defaultTheme.fontSize,
       xxxs: '0.625rem', // 10px - Only for edge cases
+      xxl: '1.375rem', // 22px
     },
     textColor: {
       ...colors,
@@ -48,9 +49,16 @@ module.exports = {
       tertiary: '#808080',
       'first-party': '#5FA569',
       'third-party': '#FA752E',
+      functional: '#5CC971',
+      marketing: '#F3AE4E',
+      analytics: '#4C79F4',
+      uncategorized: '#EC7159',
       'chart-label': '#111B21',
       'granite-gray': '#5F6369',
       'outer-space-crayola': '#303942',
+      'dark-gray': '#757575',
+      'darkest-gray': '#616161',
+      'outer-space': '#303942',
       'raisin-black': '#212121',
       manatee: '#9AA0A6',
       'bright-gray': '#E8EAED',
@@ -67,6 +75,7 @@ module.exports = {
       'american-silver': '#CBCDD1',
       'raisin-black': '#212121',
       cultured: '#F6F6F699',
+      'light-gray': '#F1F1F1',
       'charleston-green': '#292A2D',
       quartz: '#494C50',
       'davys-grey': '#5D5D5D99',
@@ -77,6 +86,8 @@ module.exports = {
     borderColor: {
       ...colors,
       'american-silver': '#CBCDD1',
+      'hex-gray': '#E0E0E0',
+      'bright-gray': '#E8EAED',
       quartz: '#494C50',
     },
     stroke: {


Test patch:
diff --git a/packages/extension/src/utils/test-data/cookieMockData.ts b/packages/extension/src/utils/test-data/cookieMockData.ts
new file mode 100644
index 00000000..211ae171
--- /dev/null
+++ b/packages/extension/src/utils/test-data/cookieMockData.ts
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * 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
+ *
+ *     https://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.
+ */
+/**
+ * External dependencies.
+ */
+import { type Cookie as ParsedCookie } from 'simple-cookie';
+
+/**
+ * Internal dependencies.
+ */
+import type { CookieStoreContext } from '../../view/devtools/stateProviders/syncCookieStore';
+import { emptyAnalytics } from '../../worker/findAnalyticsMatch';
+
+const emptyCookie = {
+  name: '',
+  value: '',
+  domain: '',
+  samesite: '',
+  secure: false,
+  httponly: false,
+  path: '',
+  expires: '',
+};
+
+export const uncategorized1pCookie: ParsedCookie = {
+  ...emptyCookie,
+  name: '_cb',
+  value: 'v1%3A168740954476563235',
+  domain: '.cnn.com',
+};
+
+export const uncategorized3pCookie: ParsedCookie = {
+  ...emptyCookie,
+  name: 'pubsyncexp',
+  value: 'uncategorized3pCookie',
+  domain: '.ads.pubmatic.com',
+};
+
+export const known1pCookie: ParsedCookie = {
+  ...emptyCookie,
+  name: '__qca',
+  value: 'known1pCookie',
+  domain: '.cnn.com',
+};
+
+export const known3pCookie: ParsedCookie = {
+  ...emptyCookie,
+  name: 'KRTBCOOKIE_290',
+  value: 'known3pCookie',
+  domain: '.pubmatic.com',
+};
+
+export const known3pCookieWithValue: ParsedCookie = {
+  ...emptyCookie,
+  name: 'KRTBCOOKIE_290',
+  value: 'known3p_Cookie-with%20value',
+  domain: '.pubmatic.com',
+};
+
+const data: {
+  tabCookies: NonNullable<CookieStoreContext['state']['tabCookies']>;
+  tabUrl: NonNullable<CookieStoreContext['state']['tabUrl']>;
+  tabFrames: NonNullable<CookieStoreContext['state']['tabFrames']>;
+  selectedFrame: NonNullable<CookieStoreContext['state']['selectedFrame']>;
+} = {
+  tabCookies: {
+    [uncategorized1pCookie.name]: {
+      parsedCookie: uncategorized1pCookie,
+      analytics: { ...emptyAnalytics },
+      url: 'https://edition.cnn.com/whatever/api',
+      headerType: 'response',
+      isFirstParty: true,
+      isIbcCompliant: true,
+      isCookieSet: true,
+      frameIdList: [1],
+    },
+    [uncategorized3pCookie.name]: {
+      parsedCookie: uncategorized3pCookie,
+      analytics: { ...emptyAnalytics },
+      url: 'https://api.pubmatic.com/whatever/api',
+      headerType: 'response',
+      isFirstParty: false,
+      isIbcCompliant: true,
+      isCookieSet: true,
+      frameIdList: [1],
+    },
+    [known1pCookie.name]: {
+      parsedCookie: known1pCookie,
+      analytics: {
+        platform: 'Quantcast',
+        category: 'Marketing',
+        name: '__qca',
+        domain: "Advertiser's website domain",
+        description:
+          'This cookie is set by Quantcast, who present targeted advertising. Stores browser and HTTP request information.',
+        retention: '1 year',
+        dataController: 'Quantcast',
+        gdprUrl: 'https://www.quantcast.com/privacy/',
+        wildcard: '0',
+      },
+      url: 'https://edition.cnn.com/whatever/api',
+      headerType: 'response',
+      isFirstParty: true,
+      isIbcCompliant: true,
+      isCookieSet: true,
+      frameIdList: [1],
+    },
+    [known3pCookie.name]: {
+      parsedCookie: known3pCookie,
+      analytics: {
+        platform: 'PubMatic',
+        category: 'Marketing',
+        name: 'KRTBCOOKIE_*',
+        domain: 'pubmatic.com',
+        description:
+          "Registers a unique ID that identifies the user's device during return visits across websites that use the same ad network. The ID is used to allow targeted ads.",
+        retention: '29 days',
+        dataController: 'Pubmatic',
+        gdprUrl: 'N/A',
+        wildcard: '1',
+      },
+      url: 'https://api.pubmatic.com/whatever/api',
+      headerType: 'response',
+      isFirstParty: false,
+      isIbcCompliant: true,
+      isCookieSet: true,
+      frameIdList: [1],
+    },
+    [known3pCookieWithValue.name]: {
+      parsedCookie: known3pCookieWithValue,
+      analytics: {
+        platform: 'PubMatic',
+        category: 'Marketing',
+        name: 'KRTBCOOKIE_*',
+        domain: 'pubmatic.com',
+        description:
+          "Registers a unique ID that identifies the user's device during return visits across websites that use the same ad network. The ID is used to allow targeted ads.",
+        retention: '29 days',
+        dataController: 'Pubmatic',
+        gdprUrl: 'N/A',
+        wildcard: '1',
+      },
+      url: 'https://api.pubmatic.com/whatever/api',
+      headerType: 'response',
+      isFirstParty: false,
+      isIbcCompliant: true,
+      isCookieSet: true,
+      frameIdList: [1],
+    },
+  },
+  tabUrl: 'https://edition.cnn.com/',
+  tabFrames: {
+    'https://edition.cnn.com/': {
+      frameIds: [1],
+    },
+  },
+  selectedFrame: 'https://edition.cnn.com/',
+};
+
+export default data;
diff --git a/packages/extension/src/utils/test-data/cookieStats.ts b/packages/extension/src/utils/test-data/cookieStats.ts
new file mode 100644
index 00000000..588c0a18
--- /dev/null
+++ b/packages/extension/src/utils/test-data/cookieStats.ts
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * 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
+ *
+ *     https://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.
+ */
+export default {
+  total: 7,
+  firstParty: {
+    total: 6,
+    functional: 0,
+    marketing: 0,
+    analytics: 2,
+    uncategorized: 4,
+  },
+  thirdParty: {
+    total: 1,
+    functional: 1,
+    marketing: 0,
+    analytics: 0,
+    uncategorized: 0,
+  },
+};
diff --git a/packages/extension/src/utils/test-data/cookiesStatsComponents.ts b/packages/extension/src/utils/test-data/cookiesStatsComponents.ts
new file mode 100644
index 00000000..edd24322
--- /dev/null
+++ b/packages/extension/src/utils/test-data/cookiesStatsComponents.ts
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * 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
+ *
+ *     https://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.
+ */
+export default {
+  legend: [
+    {
+      label: 'Functional',
+      count: 1,
+      color: '#5CC971',
+      countClassName: 'text-functional',
+    },
+    {
+      label: 'Marketing',
+      count: 0,
+      color: '#F3AE4E',
+      countClassName: 'text-marketing',
+    },
+    {
+      label: 'Analytics',
+      count: 2,
+      color: '#4C79F4',
+      countClassName: 'text-analytics',
+    },
+    {
+      label: 'Uncategorized',
+      count: 4,
+      color: '#EC7159',
+      countClassName: 'text-uncategorized',
+    },
+  ],
+  firstParty: [
+    {
+      count: 0,
+      color: '#5CC971',
+    },
+    {
+      count: 0,
+      color: '#F3AE4E',
+    },
+    {
+      count: 2,
+      color: '#4C79F4',
+    },
+    {
+      count: 4,
+      color: '#EC7159',
+    },
+  ],
+  thirdParty: [
+    {
+      count: 1,
+      color: '#5CC971',
+    },
+    {
+      count: 0,
+      color: '#F3AE4E',
+    },
+    {
+      count: 0,
+      color: '#4C79F4',
+    },
+    {
+      count: 0,
+      color: '#EC7159',
+    },
+  ],
+};
diff --git a/packages/extension/src/utils/tests/countCookiesByCategory.ts b/packages/extension/src/utils/tests/prepareCookiesCount.ts
similarity index 83%
rename from packages/extension/src/utils/tests/countCookiesByCategory.ts
rename to packages/extension/src/utils/tests/prepareCookiesCount.ts
index d899ea09..26aa1e69 100644
--- a/packages/extension/src/utils/tests/countCookiesByCategory.ts
+++ b/packages/extension/src/utils/tests/prepareCookiesCount.ts
@@ -17,7 +17,7 @@
 /**
  * Internal dependencies.
  */
-import countCookiesByCategory from '../countCookiesByCategory';
+import prepareCookiesCount from '../prepareCookiesCount';
 
 const functional1pCookie = {
   parsedCookie: {
@@ -58,7 +58,7 @@ const analytics1pCookie = {
   headerType: 'request',
 };
 
-const uncategorised1pCookie = {
+const uncategorized1pCookie = {
   parsedCookie: {
     name: 'cookie_name_4',
     value: 'val',
@@ -108,7 +108,7 @@ const analytics3pCookie = {
   headerType: 'request',
 };
 
-const uncategorised3pCookie = {
+const uncategorized3pCookie = {
   parsedCookie: {
     name: 'cookie_name_8',
     value: 'val',
@@ -126,26 +126,26 @@ const EMPTY_STATS = {
     functional: 0,
     marketing: 0,
     analytics: 0,
-    uncategorised: 0,
+    uncategorized: 0,
   },
   thirdParty: {
     total: 0,
     functional: 0,
     marketing: 0,
     analytics: 0,
-    uncategorised: 0,
+    uncategorized: 0,
   },
 };
 
-describe('countCookiesByCategory : ', () => {
+describe('prepareCookiesCount : ', () => {
   it('Gives empty stats with cookies', () => {
-    expect(countCookiesByCategory({}, 'https://example.com/page')).toEqual(
+    expect(prepareCookiesCount({}, 'https://example.com/page')).toEqual(
       EMPTY_STATS
     );
   });
 
   it('Gives empty stats with null passed as cookies', () => {
-    expect(countCookiesByCategory(null, 'https://example.com/page')).toEqual(
+    expect(prepareCookiesCount(null, 'https://example.com/page')).toEqual(
       EMPTY_STATS
     );
   });
@@ -158,8 +158,8 @@ describe('countCookiesByCategory : ', () => {
       [marketing3pCookie.parsedCookie.name]: marketing3pCookie,
       [analytics1pCookie.parsedCookie.name]: analytics1pCookie,
       [analytics3pCookie.parsedCookie.name]: analytics3pCookie,
-      [uncategorised1pCookie.parsedCookie.name]: uncategorised1pCookie,
-      [uncategorised3pCookie.parsedCookie.name]: uncategorised3pCookie,
+      [uncategorized1pCookie.parsedCookie.name]: uncategorized1pCookie,
+      [uncategorized3pCookie.parsedCookie.name]: uncategorized3pCookie,
     };
 
     const expectedStats = {
@@ -169,19 +169,19 @@ describe('countCookiesByCategory : ', () => {
         functional: 1,
         marketing: 1,
         analytics: 1,
-        uncategorised: 1,
+        uncategorized: 1,
       },
       thirdParty: {
         total: 4,
         functional: 1,
         marketing: 1,
         analytics: 1,
-        uncategorised: 1,
+        uncategorized: 1,
       },
     };
-    //@ts-ignore Missing properties are not requird in the function.
-    expect(countCookiesByCategory(cookies, 'https://example.com/page')).toEqual(
-      expectedStats
-    );
+    expect(
+      //@ts-ignore Missing properties are not required in the function.
+      prepareCookiesCount(cookies, 'https://example.com/page')
+    ).toEqual(expectedStats);
   });
 });
diff --git a/packages/extension/src/view/design-system/components/circle/tests/circleEmpty.tsx b/packages/extension/src/view/design-system/components/circle/tests/circleEmpty.tsx
index fb869546..18b1903a 100644
--- a/packages/extension/src/view/design-system/components/circle/tests/circleEmpty.tsx
+++ b/packages/extension/src/view/design-system/components/circle/tests/circleEmpty.tsx
@@ -33,6 +33,6 @@ describe('CircleEmpty', () => {
 
     // Check if the CircleEmpty div has the correct background color style
     const circleEmptyDiv = container.querySelector('div');
-    expect(circleEmptyDiv).toHaveStyle(`background-color: ${testColor}`);
+    expect(circleEmptyDiv).toHaveStyle(`border-color: ${testColor}`);
   });
 });
diff --git a/packages/extension/src/view/design-system/components/matrix/tests/matrix.tsx b/packages/extension/src/view/design-system/components/matrix/tests/matrix.tsx
new file mode 100644
index 00000000..c9e25792
--- /dev/null
+++ b/packages/extension/src/view/design-system/components/matrix/tests/matrix.tsx
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * 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
+ *
+ *     https://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.
+ */
+/**
+ * External dependencies.
+ */
+import React from 'react';
+import { render, screen } from '@testing-library/react';
+import '@testing-library/jest-dom/extend-expect';
+
+/**
+ * Internal dependencies.
+ */
+import Matrix from '..';
+import { type MatrixComponentProps } from '../matrixComponent';
+
+describe('Matrix', () => {
+  it('renders null when dataComponents is empty', () => {
+    const { container } = render(<Matrix dataComponents={[]} />);
+    expect(container.firstChild).toBeNull();
+  });
+
+  it('renders MatrixComponent for each dataComponent', () => {
+    const mockDataComponents: MatrixComponentProps[] = [
+      {
+        color: 'red',
+        title: 'Test title',
+        count: 10,
+        countClassName: '',
+        containerClasses: '',
+      },
+      {
+        color: 'blue',
+        title: 'Test title',
+        count: 10,
+        countClassName: '',
+        containerClasses: '',
+      },
+    ];
+
+    render(<Matrix dataComponents={mockDataComponents} />);
+
+    const matrixContainer = screen.getByTestId('matrix');
+
+    expect(matrixContainer).toBeInTheDocument();
+  });
+});
diff --git a/packages/extension/src/view/devtools/components/sidebar/tests/index.tsx b/packages/extension/src/view/devtools/components/sidebar/tests/index.tsx
index 561d3036..ede24b54 100644
--- a/packages/extension/src/view/devtools/components/sidebar/tests/index.tsx
+++ b/packages/extension/src/view/devtools/components/sidebar/tests/index.tsx
@@ -38,15 +38,15 @@ const tabNames = [
   'Bounce Tracking',
   'Fingerprinting',
 ];
-const uncategorised1pCookie: ParsedCookie = {
+const uncategorized1pCookie: ParsedCookie = {
   name: '_cb',
-  value: 'uncategorised1pCookie',
+  value: 'uncategorized1pCookie',
   domain: '.cnn.com',
 };
 
-const uncategorised3pCookie: ParsedCookie = {
+const uncategorized3pCookie: ParsedCookie = {
   name: 'pubsyncexp',
-  value: 'uncategorised3pCookie',
+  value: 'uncategorized3pCookie',
   domain: '.ads.pubmatic.com',
 };
 
@@ -70,8 +70,8 @@ const mockResponse: {
   setSelectedFrame: CookieStoreContext['actions']['setSelectedFrame'];
 } = {
   tabCookies: {
-    [uncategorised1pCookie.name]: {
-      parsedCookie: uncategorised1pCookie,
+    [uncategorized1pCookie.name]: {
+      parsedCookie: uncategorized1pCookie,
       analytics: null,
       url: 'https://edition.cnn.com/whatever/api',
       headerType: 'response',
@@ -80,8 +80,8 @@ const mockResponse: {
       isIbcCompliant: true,
       isCookieSet: true,
     },
-    [uncategorised3pCookie.name]: {
-      parsedCookie: uncategorised3pCookie,
+    [uncategorized3pCookie.name]: {
+      parsedCookie: uncategorized3pCookie,
       analytics: null,
       url: 'https://api.pubmatic.com/whatever/api',
       headerType: 'response',
diff --git a/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/cookiesMatrix/tests/cookieMatrix.tsx b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/cookiesMatrix/tests/cookieMatrix.tsx
new file mode 100644
index 00000000..fe7420b9
--- /dev/null
+++ b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/cookiesMatrix/tests/cookieMatrix.tsx
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * 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
+ *
+ *     https://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.
+ */
+/**
+ * External dependencies.
+ */
+import React from 'react';
+import { render } from '@testing-library/react';
+import '@testing-library/jest-dom/extend-expect';
+
+/**
+ * Internal dependencies.
+ */
+import CookiesMatrix from '..';
+import mockResponse from '../../../../../../../../utils/test-data/cookieMockData';
+import cookiesStatsComponents from '../../../../../../../../utils/test-data/cookiesStatsComponents';
+
+describe('CookiesMatrix', () => {
+  it('should render the cookies matrix', () => {
+    const tabCookies = mockResponse.tabCookies;
+    const tabFrames = mockResponse.tabFrames;
+
+    const { getByTestId } = render(
+      <CookiesMatrix
+        tabCookies={tabCookies}
+        cookiesStatsComponents={cookiesStatsComponents}
+        tabFrames={tabFrames}
+      />
+    );
+
+    expect(getByTestId('cookies-matrix')).toBeInTheDocument();
+  });
+});
diff --git a/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/landingHeader/tests/landingHeader.tsx b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/landingHeader/tests/landingHeader.tsx
new file mode 100644
index 00000000..2c371476
--- /dev/null
+++ b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/landingHeader/tests/landingHeader.tsx
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * 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
+ *
+ *     https://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.
+ */
+/**
+ * External dependencies.
+ */
+import React from 'react';
+import { render } from '@testing-library/react';
+import '@testing-library/jest-dom/extend-expect';
+
+/**
+ * Internal dependencies.
+ */
+import LandingHeader from '..';
+import cookiesStatsComponents from '../../../../../../../../utils/test-data/cookiesStatsComponents';
+import cookieStats from '../../../../../../../../utils/test-data/cookieStats';
+
+describe('LandingHeader', () => {
+  it('should render the landing header', () => {
+    const { getByTestId } = render(
+      <LandingHeader
+        cookieStats={cookieStats}
+        cookiesStatsComponents={cookiesStatsComponents}
+      />
+    );
+
+    expect(getByTestId('cookies-landing-header')).toBeInTheDocument();
+  });
+});
diff --git a/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/tests/cookiesLanding.tsx b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/tests/cookiesLanding.tsx
new file mode 100644
index 00000000..671ea73b
--- /dev/null
+++ b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/tests/cookiesLanding.tsx
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * 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
+ *
+ *     https://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.
+ */
+/**
+ * External dependencies.
+ */
+import React from 'react';
+import { render } from '@testing-library/react';
+import '@testing-library/jest-dom/extend-expect';
+
+/**
+ * Internal dependencies.
+ */
+import CookiesLanding from '..';
+import mockRespose from '../../../../../../../utils/test-data/cookieMockData';
+
+jest.mock('../../../../../stateProviders/syncCookieStore', () => {
+  return {
+    useCookieStore: () => {
+      return {
+        cookies: Object.values(mockRespose.tabCookies),
+        tabUrl: mockRespose.tabUrl,
+        tabFrames: mockRespose.tabFrames,
+        selectedFrame: mockRespose.selectedFrame,
+      };
+    },
+  };
+});
+
+describe('CookiesLanding', () => {
+  it('renders CookiesLanding with data', () => {
+    const { getByTestId } = render(<CookiesLanding />);
+
+    expect(getByTestId('cookies-landing')).toBeInTheDocument();
+    expect(getByTestId('cookies-landing-header')).toBeInTheDocument();
+    expect(getByTestId('cookies-matrix')).toBeInTheDocument();
+  });
+});
diff --git a/packages/extension/src/view/devtools/components/tabContent/cookies/tests/cookieTab.tsx b/packages/extension/src/view/devtools/components/tabContent/cookies/tests/cookieTab.tsx
index 4f75cd62..0036e451 100644
--- a/packages/extension/src/view/devtools/components/tabContent/cookies/tests/cookieTab.tsx
+++ b/packages/extension/src/view/devtools/components/tabContent/cookies/tests/cookieTab.tsx
@@ -19,164 +19,20 @@
 import React from 'react';
 import { fireEvent, render, screen, within } from '@testing-library/react';
 import '@testing-library/jest-dom';
-import { type Cookie as ParsedCookie } from 'simple-cookie';
 import SinonChrome from 'sinon-chrome';
 
 /**
  * Internal dependencies.
  */
 import CookieTab from '..';
-import type { CookieStoreContext } from '../../../../stateProviders/syncCookieStore';
-import { emptyAnalytics } from '../../../../../../worker/findAnalyticsMatch';
 import CookieDetails from '../cookiesListing/cookieDetails';
 import { useContentPanelStore } from '../../../../stateProviders/contentPanelStore';
 import Details from '../cookiesListing/cookieDetails/details';
-
-const emptyCookie = {
-  name: '',
-  value: '',
-  domain: '',
-  samesite: '',
-  secure: false,
-  httponly: false,
-  path: '',
-  expires: '',
-};
-
-const uncategorised1pCookie: ParsedCookie = {
-  ...emptyCookie,
-  name: '_cb',
-  value: 'v1%3A168740954476563235',
-  domain: '.cnn.com',
-};
-
-const uncategorised3pCookie: ParsedCookie = {
-  ...emptyCookie,
-  name: 'pubsyncexp',
-  value: 'uncategorised3pCookie',
-  domain: '.ads.pubmatic.com',
-};
-
-const known1pCookie: ParsedCookie = {
-  ...emptyCookie,
-  name: '__qca',
-  value: 'known1pCookie',
-  domain: '.cnn.com',
-};
-
-const known3pCookie: ParsedCookie = {
-  ...emptyCookie,
-  name: 'KRTBCOOKIE_290',
-  value: 'known3pCookie',
-  domain: '.pubmatic.com',
-};
-
-const known3pCookieWithValue: ParsedCookie = {
-  ...emptyCookie,
-  name: 'KRTBCOOKIE_290',
-  value: 'known3p_Cookie-with%20value',
-  domain: '.pubmatic.com',
-};
-
-const mockResponse: {
-  tabCookies: NonNullable<CookieStoreContext['state']['tabCookies']>;
-  tabUrl: NonNullable<CookieStoreContext['state']['tabUrl']>;
-  tabFrames: NonNullable<CookieStoreContext['state']['tabFrames']>;
-  selectedFrame: NonNullable<CookieStoreContext['state']['selectedFrame']>;
-} = {
-  tabCookies: {
-    [uncategorised1pCookie.name]: {
-      parsedCookie: uncategorised1pCookie,
-      analytics: { ...emptyAnalytics },
-      url: 'https://edition.cnn.com/whatever/api',
-      headerType: 'response',
-      isFirstParty: true,
-      isIbcCompliant: true,
-      isCookieSet: true,
-      frameIdList: [1],
-    },
-    [uncategorised3pCookie.name]: {
-      parsedCookie: uncategorised3pCookie,
-      analytics: { ...emptyAnalytics },
-      url: 'https://api.pubmatic.com/whatever/api',
-      headerType: 'response',
-      isFirstParty: false,
-      isIbcCompliant: true,
-      isCookieSet: true,
-      frameIdList: [1],
-    },
-    [known1pCookie.name]: {
-      parsedCookie: known1pCookie,
-      analytics: {
-        platform: 'Quantcast',
-        category: 'Marketing',
-        name: '__qca',
-        domain: "Advertiser's website domain",
-        description:
-          'This cookie is set by Quantcast, who present targeted advertising. Stores browser and HTTP request information.',
-        retention: '1 year',
-        dataController: 'Quantcast',
-        gdprUrl: 'https://www.quantcast.com/privacy/',
-        wildcard: '0',
-      },
-      url: 'https://edition.cnn.com/whatever/api',
-      headerType: 'response',
-      isFirstParty: true,
-      isIbcCompliant: true,
-      isCookieSet: true,
-      frameIdList: [1],
-    },
-    [known3pCookie.name]: {
-      parsedCookie: known3pCookie,
-      analytics: {
-        platform: 'PubMatic',
-        category: 'Marketing',
-        name: 'KRTBCOOKIE_*',
-        domain: 'pubmatic.com',
-        description:
-          "Registers a unique ID that identifies the user's device during return visits across websites that use the same ad network. The ID is used to allow targeted ads.",
-        retention: '29 days',
-        dataController: 'Pubmatic',
-        gdprUrl: 'N/A',
-        wildcard: '1',
-      },
-      url: 'https://api.pubmatic.com/whatever/api',
-      headerType: 'response',
-      isFirstParty: false,
-      isIbcCompliant: true,
-      isCookieSet: true,
-      frameIdList: [1],
-    },
-    [known3pCookieWithValue.name]: {
-      parsedCookie: known3pCookieWithValue,
-      analytics: {
-        platform: 'PubMatic',
-        category: 'Marketing',
-        name: 'KRTBCOOKIE_*',
-        domain: 'pubmatic.com',
-        description:
-          "Registers a unique ID that identifies the user's device during return visits across websites that use the same ad network. The ID is used to allow targeted ads.",
-        retention: '29 days',
-        dataController: 'Pubmatic',
-        gdprUrl: 'N/A',
-        wildcard: '1',
-      },
-      url: 'https://api.pubmatic.com/whatever/api',
-      headerType: 'response',
-      isFirstParty: false,
-      isIbcCompliant: true,
-      isCookieSet: true,
-      frameIdList: [1],
-    },
-  },
-  tabUrl: 'https://edition.cnn.com/',
-  tabFrames: {
-    'https://edition.cnn.com/': {
-      frameIds: [1],
-    },
-  },
-  selectedFrame: 'https://edition.cnn.com/',
-};
+import mockResponse, {
+  uncategorized1pCookie,
+  known1pCookie,
+  known3pCookieWithValue,
+} from '../../../../../../utils/test-data/cookieMockData';
 
 jest.mock('../../../../stateProviders/syncCookieStore', () => {
   return {
@@ -195,7 +51,7 @@ jest.mock('../../../../stateProviders/contentPanelStore');
 const mockUseContentPanelStore = useContentPanelStore as jest.Mock;
 mockUseContentPanelStore.mockReturnValue({
   selectedFrameCookie: {
-    1: mockResponse.tabCookies[uncategorised1pCookie.name],
+    1: mockResponse.tabCookies[uncategorized1pCookie.name],
   },
   setSelectedFrameCookie: jest.fn(),
   tableContainerRef: { current: null },
@@ -213,7 +69,7 @@ describe('CookieTab', () => {
 
     expect((await screen.findAllByTestId('body-row')).length).toBe(4);
 
-    expect((await screen.findAllByText('Uncategorised')).length).toBe(2);
+    expect((await screen.findAllByText('Uncategorized')).length).toBe(2);
     expect((await screen.findAllByText('Marketing')).length).toBe(2);
   });
 
@@ -308,7 +164,7 @@ describe('CookieTab', () => {
   it('should decode cookie value when input show URI decoded is checked', async () => {
     render(
       <Details
-        selectedCookie={mockResponse.tabCookies[uncategorised1pCookie.name]}
+        selectedCookie={mockResponse.tabCookies[uncategorized1pCookie.name]}
       />
     );
 
@@ -318,13 +174,13 @@ describe('CookieTab', () => {
     fireEvent.click(checkbox);
 
     expect(
-      await screen.findByText(decodeURIComponent(uncategorised1pCookie.value))
+      await screen.findByText(decodeURIComponent(uncategorized1pCookie.value))
     ).toBeInTheDocument();
 
     fireEvent.click(checkbox);
 
     expect(
-      await screen.findByText(uncategorised1pCookie.value)
+      await screen.findByText(uncategorized1pCookie.value)
     ).toBeInTheDocument();
   });
 
@@ -375,7 +231,7 @@ describe('CookieTab', () => {
   it('should show a cookie card with no description about cookie', async () => {
     mockUseContentPanelStore.mockReturnValue({
       selectedFrameCookie: {
-        1: mockResponse.tabCookies[uncategorised1pCookie.name],
+        1: mockResponse.tabCookies[uncategorized1pCookie.name],
       },
       tableContainerRef: { current: null },
       tableColumnSize: 100,
@@ -417,14 +273,14 @@ describe('CookieTab', () => {
 
     expect(setStateMock).toHaveBeenCalledWith({
       'https://edition.cnn.com/':
-        mockResponse.tabCookies[uncategorised1pCookie.name],
+        mockResponse.tabCookies[uncategorized1pCookie.name],
     });
 
     fireEvent.keyDown(row, { key: 'ArrowDown', code: 'ArrowDown' });
 
     expect(setStateMock).toHaveBeenCalledWith({
       'https://edition.cnn.com/':
-        mockResponse.tabCookies[uncategorised1pCookie.name],
+        mockResponse.tabCookies[uncategorized1pCookie.name],
     });
 
     const emptyRow = await screen.findByTestId('empty-row');
@@ -444,7 +300,7 @@ describe('CookieTab', () => {
 
     expect(setStateMock).toHaveBeenCalledWith({
       'https://edition.cnn.com/':
-        mockResponse.tabCookies[uncategorised1pCookie.name],
+        mockResponse.tabCookies[uncategorized1pCookie.name],
     });
   });
 
diff --git a/packages/extension/src/view/popup/components/legend/tests/legend.tsx b/packages/extension/src/view/popup/components/legend/tests/legend.tsx
index 0db602e9..df089681 100644
--- a/packages/extension/src/view/popup/components/legend/tests/legend.tsx
+++ b/packages/extension/src/view/popup/components/legend/tests/legend.tsx
@@ -27,8 +27,18 @@ import Legend from '..';
 
 describe('Legend', () => {
   const testData = [
-    { label: 'Functional', count: 10, color: 'red' },
-    { label: 'Marketing', count: 20, color: 'blue' },
+    {
+      label: 'Functional',
+      count: 10,
+      color: 'red',
+      countClassName: 'text-fuctional',
+    },
+    {
+      label: 'Marketing',
+      count: 20,
+      color: 'blue',
+      countClassName: 'text-marketing',
+    },
   ];
 
   it('renders the correct label and count for each legend item', () => {
diff --git a/packages/extension/src/view/popup/tests/index.tsx b/packages/extension/src/view/popup/tests/index.tsx
index 870d5819..6cdf32c9 100644
--- a/packages/extension/src/view/popup/tests/index.tsx
+++ b/packages/extension/src/view/popup/tests/index.tsx
@@ -89,14 +89,14 @@ describe('App', () => {
           analytics: 1,
           marketing: 1,
           functional: 1,
-          uncategorised: 0,
+          uncategorized: 0,
         },
         thirdParty: {
           total: 3,
           analytics: 1,
           marketing: 1,
           functional: 1,
-          uncategorised: 0,
+          uncategorized: 0,
         },
       },
     });