Skip to content

Commit 06a54ac

Browse files
authored
Merge pull request #879 from IABTechLab/ibg-CORPWEB-3558-update-custom-tags
ibg-CORPWEB-3558-update-custom-tags
2 parents b785a28 + e9c545b commit 06a54ac

File tree

9 files changed

+218
-3
lines changed

9 files changed

+218
-3
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@
1818
npm-debug.log*
1919
yarn-debug.log*
2020
yarn-error.log*
21+
.aider*

README.md

+30-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,39 @@
11
# UID2 Documentation
22

3-
>Note: The new location for viewing UID2 documentation content is on the Unified ID website: [Unified ID 2.0 Overview](https://unifiedid.com/docs/intro).
3+
> Note: The new location for viewing UID2 documentation content is on the Unified ID website: [Unified ID 2.0 Overview](https://unifiedid.com/docs/intro).
44
55
This repository contains all the content files and supporting site infrastructure for the [Unified ID 2.0 website](https://unifiedid.com). Site content is available in the following languages:
66

77
- English (US)
88
- Japanese
99

1010
For information about build tools and about contributing to this repository, see [CONTRIBUTING.md](CONTRIBUTING.md).
11+
12+
## Adding custom tags
13+
14+
1. Add imports to top of markdown file body
15+
16+
```ts
17+
import CustomTagsFilters from "@site/src/components/CustomTags/CustomTagsFilters";
18+
import CustomTagsContainer from "@site/src/components/CustomTags/CustomTagsContainer";
19+
```
20+
21+
2. Render `CustomTagsFilters` in desired location - probably at top of page below heading.
22+
23+
```tsx
24+
<CustomTagsFilters />
25+
```
26+
27+
3. Wrap tagged section with CustomTagsContainer and add desired tags, comma-separated
28+
29+
```mdx
30+
<CustomTagsContainer tags="tag one, tag two">
31+
32+
### My Tagged Section
33+
34+
The body of my tagged section. <a href="">An example link.</a>
35+
36+
</CustomTagsContainer>
37+
```
38+
39+
4. All added tags should now appear as clickable tag buttons at the top of the page. Clicking a tag will filter only results that match that tag. Clicking the tag again should toggle all content to be visible.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import styles from "./styles.module.scss";
2+
import { ReactNode, useContext, useEffect } from "react";
3+
import { CustomTagsContext } from "./CustomTagsContext";
4+
5+
export interface CustomTagsContainerProps {
6+
tags: string; // comma-separated values
7+
title: string;
8+
children: ReactNode;
9+
}
10+
11+
export default function CustomTagsContainer({
12+
tags = "",
13+
children,
14+
}: CustomTagsContainerProps) {
15+
const [{ filter }, setState] = useContext(CustomTagsContext);
16+
17+
const tagList = tags.split(",").map((tag) => tag.trim());
18+
19+
useEffect(() => {
20+
setState((state) => ({
21+
...state,
22+
// create unique array of all tags
23+
tags: Array.from(new Set([...state.tags, ...tagList])),
24+
}));
25+
}, [tags]);
26+
27+
return (
28+
<div
29+
className={
30+
tagList.includes(filter) ? styles["custom-tags-container-visible"] : ""
31+
}
32+
>
33+
{children}
34+
</div>
35+
);
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import {
2+
createContext,
3+
Dispatch,
4+
PropsWithChildren,
5+
SetStateAction,
6+
useState,
7+
} from "react";
8+
9+
type TagState = {
10+
tags: string[];
11+
filter: string | undefined;
12+
};
13+
14+
type TagContext = [TagState, Dispatch<SetStateAction<TagState>>];
15+
16+
export const CustomTagsContext = createContext<TagContext>(undefined);
17+
18+
export function CustomTagsContextProvider({ children }: PropsWithChildren) {
19+
const [state, setState] = useState<TagState>({
20+
tags: [],
21+
filter: undefined,
22+
});
23+
24+
return (
25+
<CustomTagsContext.Provider value={[state, setState]}>
26+
{children}
27+
</CustomTagsContext.Provider>
28+
);
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { CSSProperties, useContext } from "react";
2+
import styles from "./styles.module.scss";
3+
import { CustomTagsContext } from "./CustomTagsContext";
4+
5+
interface CustomTagsFilterListProps {
6+
tags: string[];
7+
style?: CSSProperties;
8+
subtitle?: string;
9+
}
10+
11+
export function CustomTagsFilterList({
12+
tags,
13+
style,
14+
subtitle,
15+
}: CustomTagsFilterListProps) {
16+
const [{ filter }, setState] = useContext(CustomTagsContext);
17+
18+
if (tags.length < 1) return null;
19+
20+
const onClickFilter = (update: string) => {
21+
if (filter === update) update = undefined; // toggle off
22+
23+
setState((state) => ({ ...state, filter: update }));
24+
25+
const article = document.querySelector("article");
26+
27+
if (article) {
28+
article.classList[update ? "add" : "remove"](
29+
styles["custom-tag-toggled"],
30+
);
31+
}
32+
};
33+
34+
return (
35+
<div className={styles["custom-tags-filters"]} style={style}>
36+
{subtitle && <b>{subtitle}</b>}
37+
38+
<ul>
39+
{tags.map((tag) => (
40+
<li
41+
key={tag}
42+
className={filter === tag ? styles["custom-tags-active"] : ""}
43+
>
44+
<button onClick={() => onClickFilter(tag)}>{tag}</button>
45+
</li>
46+
))}
47+
</ul>
48+
</div>
49+
);
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { useContext } from "react";
2+
import { CustomTagsContext } from "./CustomTagsContext";
3+
import { CustomTagsFilterList } from "./CustomTagsFilterList";
4+
5+
export default function CustomTagsFilters() {
6+
const [{ tags }] = useContext(CustomTagsContext);
7+
8+
return <CustomTagsFilterList tags={tags} subtitle="Tags: " />;
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
.custom-tags-filters {
2+
display: flex;
3+
flex-flow: row;
4+
gap: 0.5em;
5+
margin: 0 0 1.5em 0;
6+
padding: 0;
7+
8+
ul {
9+
margin: 0;
10+
padding: 0;
11+
display: flex;
12+
flex-flow: row;
13+
gap: 0.5em;
14+
}
15+
16+
li {
17+
margin: 0 !important;
18+
list-style-type: none;
19+
20+
button {
21+
cursor: pointer;
22+
background-color: inherit;
23+
24+
// styles coppied from /blog theme tag
25+
border-radius: var(--ifm-global-radius);
26+
padding: 0.2rem 0.5rem 0.3rem;
27+
font-size: 90%;
28+
border: 1px solid var(--docusaurus-tag-list-border);
29+
transition: border var(--ifm-transition-fast);
30+
color: var(--ifm-link-color);
31+
32+
&:hover {
33+
--docusaurus-tag-list-border: var(--ifm-link-color);
34+
}
35+
}
36+
}
37+
}
38+
39+
.custom-tags-active {
40+
button {
41+
--docusaurus-tag-list-border: var(--ifm-link-color);
42+
}
43+
}
44+
45+
.custom-tags-container-visible {
46+
display: block;
47+
}
48+
49+
.custom-tag-toggled {
50+
// all siblings after first paragraph, except for tags and filtered container
51+
p:first-of-type
52+
~ *:not(.custom-tags-filters):not(.custom-tags-container-visible):not(
53+
.custom-tags-container-visible *
54+
) {
55+
display: none;
56+
}
57+
}

src/theme/Layout/Provider/index.tsx

+5-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
PluginHtmlClassNameProvider,
1414
} from "@docusaurus/theme-common/internal";
1515
import { DocsPreferredVersionContextProvider } from "@docusaurus/plugin-content-docs/client";
16+
import { CustomTagsContextProvider } from "@site/src/components/CustomTags/CustomTagsContext";
1617

1718
const Provider = composeProviders([
1819
ColorModeProvider,
@@ -38,8 +39,10 @@ export default function LayoutProvider({ children }) {
3839

3940
return (
4041
<Provider>
41-
{isDocsPage ? <RestoreTheme></RestoreTheme> : null}
42-
{children}
42+
<CustomTagsContextProvider>
43+
{isDocsPage ? <RestoreTheme></RestoreTheme> : null}
44+
{children}
45+
</CustomTagsContextProvider>
4346
</Provider>
4447
);
4548
}

tsconfig.json

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"compilerOptions": {
55
"baseUrl": ".",
66
"resolveJsonModule": true,
7+
"jsx": "react-jsx",
78
"paths": {
89
"@site/*": ["./*"]
910
}

0 commit comments

Comments
 (0)