Skip to content

Commit d281158

Browse files
hturanharshil1712
authored andcommitted
[Docs Site] Product Directory Refresh (#18133)
* Update Products directory * Fix changes to 1.1.1.1 icon * Fixed client-side node imports * Added dark colors * Design tweaks for truncated product names * Fix types, add category deep-links
1 parent 76f4c39 commit d281158

28 files changed

+252
-219
lines changed

src/components/ProductCatalog.tsx

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
import { useEffect, useState, type ChangeEvent } from "react";
2+
import type { CollectionEntry } from "astro:content";
3+
import type { IconifyIconBuildResult } from "@iconify/utils";
4+
5+
export type ProductData = CollectionEntry<"products"> & {
6+
icon?: IconifyIconBuildResult;
7+
groups: string[];
8+
};
9+
10+
const ProductCatalog = ({ products }: { products: ProductData[] }) => {
11+
const [filters, setFilters] = useState<{
12+
search: string;
13+
groups: string[];
14+
}>({
15+
search: "",
16+
groups: [],
17+
});
18+
19+
const groups = [...new Set(products.map((product) => product.groups).flat())];
20+
21+
const productList = products.filter((product) => {
22+
if (filters.groups.length > 0) {
23+
if (
24+
filters.groups.filter((val) => product.groups.includes(val)).length ===
25+
0
26+
) {
27+
return false;
28+
}
29+
}
30+
31+
if (filters.search) {
32+
if (
33+
!product.data.name.toLowerCase().includes(filters.search.toLowerCase())
34+
) {
35+
return false;
36+
}
37+
}
38+
39+
return true;
40+
});
41+
42+
useEffect(() => {
43+
// On component load, check for deep-links to groups in the query param
44+
const params = new URLSearchParams(window.location.search);
45+
const groups = params.get("product-group");
46+
47+
if (!groups) return;
48+
49+
setFilters({
50+
...filters,
51+
groups: [groups],
52+
});
53+
}, []);
54+
55+
return (
56+
<div className="md:flex">
57+
<div className="md:w-1/4 w-full mr-8">
58+
<input
59+
type="text"
60+
className="w-full mb-8 rounded-md bg-white dark:bg-black border-2 border-gray-200 dark:border-gray-700 px-2 py-2"
61+
placeholder="Search products"
62+
value={filters.search}
63+
onChange={(e) => setFilters({ ...filters, search: e.target.value })}
64+
/>
65+
66+
<div className="!mb-8 md:block hidden">
67+
<span className="uppercase text-gray-600 dark:text-gray-200 text-sm font-bold">
68+
Groups
69+
</span>
70+
71+
{groups.map((group) => (
72+
<label key={group} className="block !my-2">
73+
<input
74+
type="checkbox"
75+
className="mr-2"
76+
value={group}
77+
checked={filters.groups.includes(group)}
78+
onChange={(e: ChangeEvent<HTMLInputElement>) => {
79+
if (e.target.checked) {
80+
setFilters({
81+
...filters,
82+
groups: [...filters.groups, e.target.value],
83+
});
84+
} else {
85+
setFilters({
86+
...filters,
87+
groups: filters.groups.filter(
88+
(f) => f !== e.target.value,
89+
),
90+
});
91+
}
92+
}}
93+
/>{" "}
94+
{group}
95+
</label>
96+
))}
97+
</div>
98+
</div>
99+
100+
<div className="grid lg:grid-cols-3 md:grid-cols-2 grid-cols-1 gap-2 lg:gap-4 lg:w-3/4 w-full items-stretch self-start !mt-0">
101+
{productList.length === 0 && (
102+
<div className="border lg:col-span-3 md:col-span-2 bg-gray-50 dark:bg-gray-800 dark:border-gray-500 rounded-md w-full flex-col flex align-middle justify-center text-center py-6">
103+
<span className="text-lg !font-bold">No products found</span>
104+
<p>
105+
Try a different search term, or broaden your search by removing
106+
filters.
107+
</p>
108+
</div>
109+
)}
110+
{productList.map((product) => {
111+
return (
112+
<a
113+
href={product.data.product.url}
114+
className="self-stretch p-3 border-gray-200 dark:border-gray-700 border-solid border rounded-md block !text-inherit no-underline hover:bg-gray-50 dark:hover:bg-black"
115+
>
116+
<div className="flex items-start">
117+
{product.icon && (
118+
<div className="rounded-full p-1 bg-orange-50 mr-2 text-orange-500 dark:bg-orange-950">
119+
<svg
120+
{...product.icon.attributes}
121+
width={24}
122+
height={24}
123+
dangerouslySetInnerHTML={{ __html: product.icon.body }}
124+
/>
125+
</div>
126+
)}
127+
{!product.icon && (
128+
<div className="flex items-center justify-center leading-none rounded-full p-1 bg-orange-50 dark:bg-orange-950 mr-2 text-[color:var(--orange-accent-200)] text-lg font-bold w-8 h-8">
129+
{product.data.name.substr(0, 1)}
130+
</div>
131+
)}
132+
<span className="font-semibold text-md mt-0.5">
133+
{product.data.name}
134+
</span>
135+
</div>
136+
{product.data.meta && (
137+
<p className="!mt-2 line-clamp-2 text-sm leading-6">
138+
{product.data.meta.description}
139+
</p>
140+
)}
141+
</a>
142+
);
143+
})}
144+
</div>
145+
</div>
146+
);
147+
};
148+
149+
export default ProductCatalog;

src/components/ThreeCardGrid.astro

Lines changed: 0 additions & 35 deletions
This file was deleted.

src/components/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ export { default as ResourcesBySelector } from "./ResourcesBySelector.astro";
4949
export { default as RuleID } from "./RuleID.astro";
5050
export { default as SpotlightAuthorDetails } from "./SpotlightAuthorDetails.astro";
5151
export { default as Stream } from "./Stream.astro";
52-
export { default as ThreeCardGrid } from "./ThreeCardGrid.astro";
5352
export { default as TroubleshootingList } from "./TroubleshootingList.astro";
5453
export { default as TunnelCalculator } from "./TunnelCalculator.astro";
5554
export { default as Type } from "./Type.astro";

src/content/products/access.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,8 @@ product:
44
title: Access
55
group: Cloudflare One
66
url: /cloudflare-one/policies/access/
7-
grid_placeholder: true
7+
8+
meta:
9+
title: Cloudflare Access
10+
description: Determine who can reach your application using policies.
11+
author: "@cloudflare"

src/content/products/account-billing.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ product:
44
title: Account and Billing
55
group: Cloudflare essentials
66
url: /fundamentals/subscriptions-and-billing/
7-
grid_placeholder: true
7+
8+
meta:
9+
description: Manage account billing and subscriptions.

src/content/products/browser-isolation.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ product:
44
title: Browser Isolation
55
group: Cloudflare One
66
url: /cloudflare-one/policies/browser-isolation/
7-
grid_placeholder: true
7+
8+
meta:
9+
description: Cloudflare Browser Isolation executes active webpage content in a secure isolated browser.

src/content/products/cache-reserve.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ product:
44
title: Cache Reserve
55
group: Application performance
66
url: /cache/advanced-configuration/cache-reserve/
7-
grid_placeholder: true
7+
8+
meta:
9+
description: Cache Reserve is a large, persistent data store implemented on top of R2.

src/content/products/casb.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ product:
44
title: CASB
55
group: Cloudflare One
66
url: /cloudflare-one/applications/scan-apps/
7-
grid_placeholder: true
7+
8+
meta:
9+
description: Scan SaaS applications for misconfigurations, unauthorized user activity, shadow IT, and other data security issues that can occur after a user has successfully logged in.

src/content/products/cloudflare-for-saas.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ product:
55
group: Application performance
66
additional_groups: [Application security]
77
url: /cloudflare-for-platforms/cloudflare-for-saas/
8-
grid_placeholder: true
8+
99
preview_tryout: true
1010

11+
meta:
12+
description: Cloudflare for SaaS allows you to extend the security and performance benefits of Cloudflare’s network to your customers via their own custom or vanity domains.
13+
1114
resources:
1215
dashboard_link: https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/custom-hostnames

src/content/products/cloudflare-tunnel.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ product:
44
title: Cloudflare Tunnel
55
group: Cloudflare One
66
url: /cloudflare-one/connections/connect-networks/
7-
grid_placeholder: true
7+
8+
meta:
9+
description: Cloudflare Tunnel provides you with a secure way to connect your resources to Cloudflare without a publicly routable IP address

0 commit comments

Comments
 (0)