From 4aa31719056a96b425bfe76c360fb61da5074b45 Mon Sep 17 00:00:00 2001 From: John Date: Mon, 29 Jul 2024 10:56:18 -0500 Subject: [PATCH 01/12] markdownsteps, add lightmode color to scss --- .../components/MarkdownSteps.module.scss | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/components/shared/MarkdownRenderer/components/MarkdownSteps.module.scss b/src/components/shared/MarkdownRenderer/components/MarkdownSteps.module.scss index 4925a455d..1ca453fe4 100644 --- a/src/components/shared/MarkdownRenderer/components/MarkdownSteps.module.scss +++ b/src/components/shared/MarkdownRenderer/components/MarkdownSteps.module.scss @@ -1,7 +1,12 @@ .markdown-steps { + --steps-border-color: #414141; + --steps-number-border: #414141; + --steps-number-bg: #121212; + --steps-number-color: #fafafa; + margin-left: 1rem; padding-left: 1.5rem; - border-left: 1px solid #414141; + border-left: 1px solid var(--steps-border-color); counter-reset: step; h3 { @@ -21,8 +26,9 @@ width: 33px; height: 33px; left: -41px; - border: 1px solid #414141; - background-color: #121212; + border: 1px solid var(--steps-number-border); + background-color: var(--steps-number-bg); + color: var(--steps-number-color); border-radius: 50%; font-size: 1rem; font-weight: normal; @@ -32,3 +38,10 @@ } } } + +:global(.light) .markdown-steps { + --steps-border-color: #e0e0e0; + --steps-number-border: #e0e0e0; + --steps-number-bg: #ffffff; + --steps-number-color: #333333; +} From e4a512d62cc0f91f0d1f8067ffc4d35eae711313 Mon Sep 17 00:00:00 2001 From: John Date: Mon, 29 Jul 2024 11:17:22 -0500 Subject: [PATCH 02/12] markdowntabs, add tabs/tab component for docs --- package.json | 1 + .../MarkdownRenderer/MarkdownRenderer.tsx | 4 + .../components/MarkdownTabs.module.scss | 56 ++++++++ .../components/MarkdownTabs.tsx | 122 ++++++++++++++++++ .../MarkdownRenderer/components/index.ts | 1 + yarn.lock | 105 +++++++++++++++ 6 files changed, 289 insertions(+) create mode 100644 src/components/shared/MarkdownRenderer/components/MarkdownTabs.module.scss create mode 100644 src/components/shared/MarkdownRenderer/components/MarkdownTabs.tsx diff --git a/package.json b/package.json index 0c43fff61..193ce2b63 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "@builder.io/react": "^3.2.6", "@docsearch/react": "^3.6.0", "@mdx-js/react": "^3.0.1", + "@radix-ui/react-tabs": "^1.1.0", "@shikijs/transformers": "^1.6.0", "@sindresorhus/slugify": "^2.2.1", "@solana-foundation/solana-lib": "^2.38.3", diff --git a/src/components/shared/MarkdownRenderer/MarkdownRenderer.tsx b/src/components/shared/MarkdownRenderer/MarkdownRenderer.tsx index fa10da874..a9b64ff6f 100644 --- a/src/components/shared/MarkdownRenderer/MarkdownRenderer.tsx +++ b/src/components/shared/MarkdownRenderer/MarkdownRenderer.tsx @@ -16,6 +16,8 @@ import { MarkdownPre, MarkdownImage, MarkdownSteps, + MarkdownTabs, + MarkdownTab, } from "./components"; /** @@ -223,6 +225,8 @@ const DEFAULT_COMPONENTS: MDXRemoteProps["components"] = { Callout: MarkdownCallout, Embed: MarkdownEmbed, Steps: MarkdownSteps, + Tabs: MarkdownTabs, + Tab: MarkdownTab, }; type MarkdownRendererProps = { diff --git a/src/components/shared/MarkdownRenderer/components/MarkdownTabs.module.scss b/src/components/shared/MarkdownRenderer/components/MarkdownTabs.module.scss new file mode 100644 index 000000000..f853b6710 --- /dev/null +++ b/src/components/shared/MarkdownRenderer/components/MarkdownTabs.module.scss @@ -0,0 +1,56 @@ +.markdown-tabs { + --tabs-border-color: #414141; + --tabs-bg-color: #1a1a1a; + --tabs-text-color: #a0a0a0; + --tabs-text-hover-color: #ffffff; + --tabs-active-color: #ffffff; + + margin: 1rem 0; + border: 1px solid var(--tabs-border-color); + border-radius: 0.5rem; + overflow: hidden; +} + +.markdown-tabs-list { + display: flex; + overflow-x: auto; + background-color: var(--tabs-bg-color); + border-bottom: 1px solid var(--tabs-border-color); +} + +.markdown-tabs-trigger { + padding: 0.5rem 1rem; + font-size: 0.875rem; + font-weight: 500; + color: var(--tabs-text-color); + background-color: transparent; + border: none; + border-bottom: 2px solid transparent; + cursor: pointer; + transition: + color 0.2s, + border-color 0.2s; + + &:hover { + color: var(--tabs-text-hover-color); + } + + &.active { + color: var(--tabs-active-color); + border-bottom-color: var(--tabs-active-color); + } +} + +.markdown-tabs-content { + padding-left: 1rem; + padding-right: 1rem; + font-size: 1rem; +} + +:global(.light) .markdown-tabs { + --tabs-border-color: #e0e0e0; + --tabs-bg-color: #f5f5f5; + --tabs-text-color: #666666; + --tabs-text-hover-color: #333333; + --tabs-active-color: #333333; +} diff --git a/src/components/shared/MarkdownRenderer/components/MarkdownTabs.tsx b/src/components/shared/MarkdownRenderer/components/MarkdownTabs.tsx new file mode 100644 index 000000000..96dc94de5 --- /dev/null +++ b/src/components/shared/MarkdownRenderer/components/MarkdownTabs.tsx @@ -0,0 +1,122 @@ +import React, { + ReactNode, + useState, + useCallback, + useMemo, + useLayoutEffect, +} from "react"; +import * as TabsPrimitive from "@radix-ui/react-tabs"; +import styles from "./MarkdownTabs.module.scss"; + +interface MarkdownTabsProps { + children: ReactNode; + items?: string[]; + defaultIndex?: number; + groupId?: string; + persist?: boolean; +} + +type ChangeListener = (_v: string) => void; +const listeners = new Map(); + +export function MarkdownTabs({ + children, + items = [], + defaultIndex = 0, + groupId, + persist = false, + ...props +}: MarkdownTabsProps) { + const values = useMemo(() => items.map((item) => toValue(item)), [items]); + const [value, setValue] = useState(values[defaultIndex]); + + useLayoutEffect(() => { + if (!groupId) return; + + const onUpdate: ChangeListener = (v) => { + if (values.includes(v)) setValue(v); + }; + + const previous = persist + ? localStorage.getItem(groupId) + : sessionStorage.getItem(groupId); + + if (previous) onUpdate(previous); + addChangeListener(groupId, onUpdate); + return () => { + removeChangeListener(groupId, onUpdate); + }; + }, [groupId, persist, values]); + + const onValueChange = useCallback( + (v: string) => { + if (groupId) { + update(groupId, v, persist); + } else { + setValue(v); + } + }, + [groupId, persist], + ); + + return ( + + + {values.map((v, i) => ( + + {items[i]} + + ))} + + {children} + + ); +} + +export function MarkdownTab({ + value, + ...props +}: TabsPrimitive.TabsContentProps) { + return ( + + ); +} + +function addChangeListener(groupId: string, listener: ChangeListener): void { + const list = listeners.get(groupId) ?? []; + list.push(listener); + listeners.set(groupId, list); +} + +function removeChangeListener(groupId: string, listener: ChangeListener): void { + const list = listeners.get(groupId) ?? []; + listeners.set( + groupId, + list.filter((item) => item !== listener), + ); +} + +function update(groupId: string, v: string, persist: boolean): void { + listeners.get(groupId)?.forEach((item) => item(v)); + if (persist) localStorage.setItem(groupId, v); + else sessionStorage.setItem(groupId, v); +} + +function toValue(v: string): string { + return v.toLowerCase().replace(/\s/, "-"); +} diff --git a/src/components/shared/MarkdownRenderer/components/index.ts b/src/components/shared/MarkdownRenderer/components/index.ts index f487ccfc5..8db006e42 100644 --- a/src/components/shared/MarkdownRenderer/components/index.ts +++ b/src/components/shared/MarkdownRenderer/components/index.ts @@ -6,4 +6,5 @@ export * from "./MarkdownEmbed"; export * from "./MarkdownPre"; export * from "./MarkdownImage"; export * from "./MarkdownSteps"; +export * from "./MarkdownTabs"; export * from "./CopyToClipBoardButton"; diff --git a/yarn.lock b/yarn.lock index 22506f25d..e76397a0c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1279,6 +1279,11 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/primitive@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.0.tgz#42ef83b3b56dccad5d703ae8c42919a68798bbe2" + integrity sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA== + "@radix-ui/react-arrow@1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz#c24f7968996ed934d57fe6cde5d6ec7266e1d25d" @@ -1287,6 +1292,16 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-primitive" "1.0.3" +"@radix-ui/react-collection@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.1.0.tgz#f18af78e46454a2360d103c2251773028b7724ed" + integrity sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw== + dependencies: + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-slot" "1.1.0" + "@radix-ui/react-compose-refs@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz#7ed868b66946aa6030e580b1ffca386dd4d21989" @@ -1294,6 +1309,11 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-compose-refs@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz#656432461fc8283d7b591dcf0d79152fae9ecc74" + integrity sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw== + "@radix-ui/react-context@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.0.1.tgz#fe46e67c96b240de59187dcb7a1a50ce3e2ec00c" @@ -1301,6 +1321,16 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-context@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.0.tgz#6df8d983546cfd1999c8512f3a8ad85a6e7fcee8" + integrity sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A== + +"@radix-ui/react-direction@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.1.0.tgz#a7d39855f4d077adc2a1922f9c353c5977a09cdc" + integrity sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg== + "@radix-ui/react-dismissable-layer@1.0.4": version "1.0.4" resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.4.tgz#883a48f5f938fa679427aa17fcba70c5494c6978" @@ -1321,6 +1351,13 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-use-layout-effect" "1.0.1" +"@radix-ui/react-id@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.1.0.tgz#de47339656594ad722eb87f94a6b25f9cffae0ed" + integrity sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA== + dependencies: + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-popper@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.1.2.tgz#4c0b96fcd188dc1f334e02dba2d538973ad842e9" @@ -1355,6 +1392,14 @@ "@radix-ui/react-compose-refs" "1.0.1" "@radix-ui/react-use-layout-effect" "1.0.1" +"@radix-ui/react-presence@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.0.tgz#227d84d20ca6bfe7da97104b1a8b48a833bfb478" + integrity sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ== + dependencies: + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-primitive@1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz#d49ea0f3f0b2fe3ab1cb5667eb03e8b843b914d0" @@ -1363,6 +1408,28 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-slot" "1.0.2" +"@radix-ui/react-primitive@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz#fe05715faa9203a223ccc0be15dc44b9f9822884" + integrity sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw== + dependencies: + "@radix-ui/react-slot" "1.1.0" + +"@radix-ui/react-roving-focus@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz#b30c59daf7e714c748805bfe11c76f96caaac35e" + integrity sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-collection" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-slot@1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.0.2.tgz#a9ff4423eade67f501ffb32ec22064bc9d3099ab" @@ -1371,6 +1438,27 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-compose-refs" "1.0.1" +"@radix-ui/react-slot@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.1.0.tgz#7c5e48c36ef5496d97b08f1357bb26ed7c714b84" + integrity sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw== + dependencies: + "@radix-ui/react-compose-refs" "1.1.0" + +"@radix-ui/react-tabs@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-tabs/-/react-tabs-1.1.0.tgz#0a6db1caed56776a1176aae68532060e301cc1c0" + integrity sha512-bZgOKB/LtZIij75FSuPzyEti/XBhJH52ExgtdVqjCIh+Nx/FW+LhnbXtbCzIi34ccyMsyOja8T0thCzoHFXNKA== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-presence" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-roving-focus" "1.1.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-tooltip@^1.0.6": version "1.0.6" resolved "https://registry.yarnpkg.com/@radix-ui/react-tooltip/-/react-tooltip-1.0.6.tgz#87a7786cd9f2b4de957ac645afae1575339c58b0" @@ -1397,6 +1485,11 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-use-callback-ref@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz#bce938ca413675bc937944b0d01ef6f4a6dc5bf1" + integrity sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw== + "@radix-ui/react-use-controllable-state@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz#ecd2ced34e6330caf89a82854aa2f77e07440286" @@ -1405,6 +1498,13 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-use-callback-ref" "1.0.1" +"@radix-ui/react-use-controllable-state@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz#1321446857bb786917df54c0d4d084877aab04b0" + integrity sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw== + dependencies: + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-escape-keydown@1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz#217b840c250541609c66f67ed7bab2b733620755" @@ -1420,6 +1520,11 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-use-layout-effect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz#3c2c8ce04827b26a39e442ff4888d9212268bd27" + integrity sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w== + "@radix-ui/react-use-rect@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.0.1.tgz#fde50b3bb9fd08f4a1cd204572e5943c244fcec2" From e26ad15a04f47c9e04082fa2dbc3d95a948e85e3 Mon Sep 17 00:00:00 2001 From: John Date: Mon, 29 Jul 2024 17:48:39 -0500 Subject: [PATCH 03/12] markdownaccordion, add accordion component for docs --- package.json | 1 + .../MarkdownRenderer/MarkdownRenderer.tsx | 4 + .../components/MarkdownAccordion.module.scss | 105 ++++++++++++++++++ .../components/MarkdownAccordion.tsx | 75 +++++++++++++ .../MarkdownRenderer/components/index.ts | 1 + yarn.lock | 29 +++++ 6 files changed, 215 insertions(+) create mode 100644 src/components/shared/MarkdownRenderer/components/MarkdownAccordion.module.scss create mode 100644 src/components/shared/MarkdownRenderer/components/MarkdownAccordion.tsx diff --git a/package.json b/package.json index 193ce2b63..2f7172a65 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "@builder.io/react": "^3.2.6", "@docsearch/react": "^3.6.0", "@mdx-js/react": "^3.0.1", + "@radix-ui/react-accordion": "^1.2.0", "@radix-ui/react-tabs": "^1.1.0", "@shikijs/transformers": "^1.6.0", "@sindresorhus/slugify": "^2.2.1", diff --git a/src/components/shared/MarkdownRenderer/MarkdownRenderer.tsx b/src/components/shared/MarkdownRenderer/MarkdownRenderer.tsx index a9b64ff6f..92792e670 100644 --- a/src/components/shared/MarkdownRenderer/MarkdownRenderer.tsx +++ b/src/components/shared/MarkdownRenderer/MarkdownRenderer.tsx @@ -18,6 +18,8 @@ import { MarkdownSteps, MarkdownTabs, MarkdownTab, + MarkdownAccordion, + MarkdownAccordionItem, } from "./components"; /** @@ -227,6 +229,8 @@ const DEFAULT_COMPONENTS: MDXRemoteProps["components"] = { Steps: MarkdownSteps, Tabs: MarkdownTabs, Tab: MarkdownTab, + Accordion: MarkdownAccordion, + AccordionItem: MarkdownAccordionItem, }; type MarkdownRendererProps = { diff --git a/src/components/shared/MarkdownRenderer/components/MarkdownAccordion.module.scss b/src/components/shared/MarkdownRenderer/components/MarkdownAccordion.module.scss new file mode 100644 index 000000000..895606742 --- /dev/null +++ b/src/components/shared/MarkdownRenderer/components/MarkdownAccordion.module.scss @@ -0,0 +1,105 @@ +.root { + --accordion-border-color: #414141; + --accordion-bg-color: #171717; + --accordion-text-color: #a0a0a0; + --accordion-text-active-color: #ffffff; + --accordion-content-bg-color: #0e0e0e; + + border-radius: 0.5rem; + width: 100%; + border: 1px solid var(--accordion-border-color); + overflow: hidden; + position: relative; + + h3 { + all: unset; + } +} + +.item { + border-bottom: 1px solid var(--accordion-border-color); + margin-bottom: 0px !important; + + &:last-child { + border-bottom: none; + } +} + +.trigger { + background-color: var(--accordion-bg-color); + color: var(--accordion-text-color); + padding: 0.75rem 1rem; + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; + font-size: 16px; + line-height: 1; + border: none; + transition: + background-color 0.2s ease, + color 0.2s ease; + + &[data-state="open"] { + color: var(--accordion-text-active-color); + } +} + +.chevron { + width: 1.5rem; + height: 1.5rem; + transition: transform 0.2s ease; + + [data-state="open"] > & { + transform: rotate(180deg); + } +} + +.content { + background-color: var(--accordion-content-bg-color); + overflow: hidden; + transition: + height 0.3s ease, + opacity 0.3s ease; + border-top: 1px solid var(--accordion-border-color); + + &[data-state="open"] { + animation: slideDown 300ms cubic-bezier(0.87, 0, 0.13, 1); + } + + &[data-state="closed"] { + animation: slideUp 300ms cubic-bezier(0.87, 0, 0.13, 1); + } +} + +.content-inner { + padding: 0.75rem 1rem; + font-size: 1.25rem; + padding-bottom: 0; +} + +:global(.light) .root { + --accordion-border-color: #e0e0e0; + --accordion-bg-color: #f5f5f5; + --accordion-text-color: #666666; + --accordion-text-active-color: #333333; + --accordion-content-bg-color: #ffffff; +} + +@keyframes slideDown { + from { + height: 0; + } + to { + height: var(--radix-accordion-content-height); + } +} + +@keyframes slideUp { + from { + height: var(--radix-accordion-content-height); + } + to { + height: 0; + } +} diff --git a/src/components/shared/MarkdownRenderer/components/MarkdownAccordion.tsx b/src/components/shared/MarkdownRenderer/components/MarkdownAccordion.tsx new file mode 100644 index 000000000..63730fa2f --- /dev/null +++ b/src/components/shared/MarkdownRenderer/components/MarkdownAccordion.tsx @@ -0,0 +1,75 @@ +import React, { ReactNode, useRef, useEffect } from "react"; +import * as AccordionPrimitive from "@radix-ui/react-accordion"; +import styles from "./MarkdownAccordion.module.scss"; +import AngleDownIcon from "../../../../../public/src/img/icons/Angle-down.inline.svg"; + +interface MarkdownAccordionProps { + children: ReactNode; +} + +export function MarkdownAccordion({ + children, + ...props +}: MarkdownAccordionProps) { + return ( + + {children} + + ); +} + +interface MarkdownAccordionItemProps { + title: string; + value?: string; + children: ReactNode; +} + +export function MarkdownAccordionItem({ + title, + value, + children, +}: MarkdownAccordionItemProps) { + const itemId = value ? value : title.toLowerCase().replace(/\s+/g, "-"); + const contentRef = useRef(null); + + // css for radixui data-state attribute (sometimes) doesn't render on change + // this seems to cause rerender and apply the correct state + useEffect(() => { + const observer = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + if ( + mutation.type === "attributes" && + mutation.attributeName === "data-state" + ) { + const element = mutation.target as HTMLElement; + const newState = element.getAttribute("data-state"); + console.log(newState); + } + }); + }); + + if (contentRef.current) { + observer.observe(contentRef.current, { attributes: true }); + } + + return () => observer.disconnect(); + }, []); + + return ( + + + + {title} + + + + +
{children}
+
+
+ ); +} diff --git a/src/components/shared/MarkdownRenderer/components/index.ts b/src/components/shared/MarkdownRenderer/components/index.ts index 8db006e42..5f519ab0f 100644 --- a/src/components/shared/MarkdownRenderer/components/index.ts +++ b/src/components/shared/MarkdownRenderer/components/index.ts @@ -7,4 +7,5 @@ export * from "./MarkdownPre"; export * from "./MarkdownImage"; export * from "./MarkdownSteps"; export * from "./MarkdownTabs"; +export * from "./MarkdownAccordion"; export * from "./CopyToClipBoardButton"; diff --git a/yarn.lock b/yarn.lock index e76397a0c..255beacc3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1284,6 +1284,21 @@ resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.0.tgz#42ef83b3b56dccad5d703ae8c42919a68798bbe2" integrity sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA== +"@radix-ui/react-accordion@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-accordion/-/react-accordion-1.2.0.tgz#aed0770fcb16285db992d81873ccd7a014c7f17d" + integrity sha512-HJOzSX8dQqtsp/3jVxCU3CXEONF7/2jlGAB28oX8TTw1Dz8JYbEI1UcL8355PuLBE41/IRRMvCw7VkiK/jcUOQ== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-collapsible" "1.1.0" + "@radix-ui/react-collection" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-arrow@1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz#c24f7968996ed934d57fe6cde5d6ec7266e1d25d" @@ -1292,6 +1307,20 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-primitive" "1.0.3" +"@radix-ui/react-collapsible@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-collapsible/-/react-collapsible-1.1.0.tgz#4d49ddcc7b7d38f6c82f1fd29674f6fab5353e77" + integrity sha512-zQY7Epa8sTL0mq4ajSJpjgn2YmCgyrG7RsQgLp3C0LQVkG7+Tf6Pv1CeNWZLyqMjhdPkBa5Lx7wYBeSu7uCSTA== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-presence" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-collection@1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.1.0.tgz#f18af78e46454a2360d103c2251773028b7724ed" From 4d9426cde3ae855b29e35ba82893ab7f2276edc5 Mon Sep 17 00:00:00 2001 From: John Date: Tue, 30 Jul 2024 10:24:58 -0500 Subject: [PATCH 04/12] update docs scrollbar, display onhover only --- .../DevelopersContentPage.module.scss | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/components/developers/DevelopersContentPage/DevelopersContentPage.module.scss b/src/components/developers/DevelopersContentPage/DevelopersContentPage.module.scss index 45ec7d291..15d7109d9 100644 --- a/src/components/developers/DevelopersContentPage/DevelopersContentPage.module.scss +++ b/src/components/developers/DevelopersContentPage/DevelopersContentPage.module.scss @@ -38,6 +38,16 @@ background: var(--scrollbar-thumb-hover); } + @mixin custom-scrollbar { + scrollbar-width: thin; + scrollbar-color: transparent transparent; + transition: scrollbar-color 0.2s ease; + + &:hover { + scrollbar-color: var(--scrollbar-thumb) transparent; + } + } + > * + * { margin-top: 1.5rem; } @@ -343,6 +353,7 @@ max-height: calc(100vh - 8rem); overflow-y: auto; overflow-x: hidden; + @include custom-scrollbar; } @media (max-width: 992px) { @@ -389,6 +400,7 @@ order: 3 !important; position: sticky !important; max-width: 248px; + @include custom-scrollbar; } @media (max-width: 992px) { From c741f17fc6a31348729c7a29e9ed17c0c89b0dfa Mon Sep 17 00:00:00 2001 From: John Date: Tue, 30 Jul 2024 11:39:29 -0500 Subject: [PATCH 05/12] markdownpre, code ui update and add lightmode --- public/src/img/icons/FileDiff.inline.svg | 14 +++ public/src/img/icons/Rust.inline.svg | 14 +++ public/src/img/icons/Terminal.inline.svg | 13 +++ public/src/img/icons/Typescript.inline.svg | 5 + .../components/MarkdownPre.module.scss | 95 ++++++++++++------- .../components/MarkdownPre.tsx | 36 ++++++- src/utils/markdown.ts | 8 +- 7 files changed, 149 insertions(+), 36 deletions(-) create mode 100644 public/src/img/icons/FileDiff.inline.svg create mode 100644 public/src/img/icons/Rust.inline.svg create mode 100644 public/src/img/icons/Terminal.inline.svg create mode 100644 public/src/img/icons/Typescript.inline.svg diff --git a/public/src/img/icons/FileDiff.inline.svg b/public/src/img/icons/FileDiff.inline.svg new file mode 100644 index 000000000..763df2e22 --- /dev/null +++ b/public/src/img/icons/FileDiff.inline.svg @@ -0,0 +1,14 @@ + \ No newline at end of file diff --git a/public/src/img/icons/Rust.inline.svg b/public/src/img/icons/Rust.inline.svg new file mode 100644 index 000000000..42de76f4d --- /dev/null +++ b/public/src/img/icons/Rust.inline.svg @@ -0,0 +1,14 @@ + + + + \ No newline at end of file diff --git a/public/src/img/icons/Terminal.inline.svg b/public/src/img/icons/Terminal.inline.svg new file mode 100644 index 000000000..6d4159641 --- /dev/null +++ b/public/src/img/icons/Terminal.inline.svg @@ -0,0 +1,13 @@ + + + \ No newline at end of file diff --git a/public/src/img/icons/Typescript.inline.svg b/public/src/img/icons/Typescript.inline.svg new file mode 100644 index 000000000..7f495f32e --- /dev/null +++ b/public/src/img/icons/Typescript.inline.svg @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/src/components/shared/MarkdownRenderer/components/MarkdownPre.module.scss b/src/components/shared/MarkdownRenderer/components/MarkdownPre.module.scss index 2d8bf9165..966e1cd17 100644 --- a/src/components/shared/MarkdownRenderer/components/MarkdownPre.module.scss +++ b/src/components/shared/MarkdownRenderer/components/MarkdownPre.module.scss @@ -1,24 +1,52 @@ .wrapper { + --wrapper-border-color: #414141; + --wrapper-bg-color: #0e0e0e; + --header-bg-color: #171717; + --header-text-color: #ededed; + --highlighted-line-bg: #081c2e; + --highlighted-chars-bg: rgba(138, 208, 255, 0.1); + --highlighted-chars-border: var(--bs-link-color); + --diff-add-bg: rgba(44, 246, 75, 0.25); + --diff-remove-bg: rgba(246, 44, 61, 0.25); + overflow: clip; position: relative; border-radius: 0.4rem; - border: 1px solid #414141 !important; + border: 1px solid var(--wrapper-border-color) !important; .header { + display: flex; + align-items: center; + gap: 0.75rem; line-height: 1; font-size: 16px; - background-color: #414141; + background-color: var(--header-bg-color); + border-bottom: 1px solid var(--wrapper-border-color) !important; margin-bottom: 0 !important; - color: #ededed; - padding: 0.8rem; - /* border-bottom: 1px solid #414141 !important; */ + color: var(--header-text-color); + padding: 0.75rem 1rem; font-family: monospace; + + .icon { + width: 1.5rem; + height: 1.5rem; + } + + span { + padding-top: 2px; + } } .copy-button { position: absolute; - top: 4px; - right: 5px; + top: 0.5rem; + right: 0.5rem; + opacity: 0; + transition: opacity 0.2s ease-in-out; + } + + &:hover .copy-button { + opacity: 1; } & > pre { @@ -27,39 +55,24 @@ position: static; padding: 0.5rem 0; margin-bottom: 0 !important; + background-color: var(--wrapper-bg-color) !important; & code > * { padding: 0.06rem 3rem 0.06rem 0.75rem; } - } - // line numbers via css - // :global(code) { - // counter-reset: line; - // } - // :global(code > [data-line]::before) { - // counter-increment: line; - // content: counter(line); - - // /* Other styling */ - // display: inline-block; - // width: 1rem; - // margin-right: 1rem; - // text-align: right; - // color: gray; - // } + & span { + color: var(--shiki-dark); + } + } :global([data-highlighted-line]) { - // background-color: red; - // background-color: rgba(0, 0, 0, 0.3); - // background-color: rgba(146, 76, 189, 0.5); - background-color: rgba(138, 208, 255, 0.1); + background-color: var(--highlighted-line-bg); } :global([data-highlighted-chars]) { - // background-color: rgba(146, 76, 189, 0.7); - background-color: rgba(138, 208, 255, 0.1); - border-bottom: 1px solid var(--bs-link-color); + background-color: var(--highlighted-chars-bg); + border-bottom: 1px solid var(--highlighted-chars-border); border-radius: 0.25rem; padding: 0.1rem 0.4rem; } @@ -69,16 +82,34 @@ } :global(.diff.add) { - background-color: rgba(44, 246, 75, 0.25); + background-color: var(--diff-add-bg); &::before { content: "+"; } } :global(.diff.remove) { - background-color: rgba(246, 44, 61, 0.25); + background-color: var(--diff-remove-bg); &::before { content: "-"; } } } + +:global(.light) .wrapper { + --wrapper-border-color: #e0e0e0; + --wrapper-bg-color: #f6f6f6; + --header-bg-color: #f5f5f5; + --header-text-color: #333333; + --highlighted-line-bg: #e6f7ff; + --highlighted-chars-bg: rgba(3, 102, 214, 0.1); + --highlighted-chars-border: #0366d6; + --diff-add-bg: rgba(46, 160, 67, 0.15); + --diff-remove-bg: rgba(248, 81, 73, 0.15); + + & > pre { + & span { + color: var(--shiki-light); + } + } +} diff --git a/src/components/shared/MarkdownRenderer/components/MarkdownPre.tsx b/src/components/shared/MarkdownRenderer/components/MarkdownPre.tsx index 26783c096..e34d469e1 100644 --- a/src/components/shared/MarkdownRenderer/components/MarkdownPre.tsx +++ b/src/components/shared/MarkdownRenderer/components/MarkdownPre.tsx @@ -1,6 +1,12 @@ +import React from "react"; import styles from "./MarkdownPre.module.scss"; import { CopyToClipBoardButton } from "./CopyToClipBoardButton"; +import RustIcon from "../../../../../public/src/img/icons/Rust.inline.svg"; +import TypescriptIcon from "../../../../../public/src/img/icons/Typescript.inline.svg"; +import TerminalIcon from "../../../../../public/src/img/icons/Terminal.inline.svg"; +import FileDiffIcon from "../../../../../public/src/img/icons/FileDiff.inline.svg"; + /** * Listing of the supported custom metadata that can be attached to parsed components via `attachMetadata` */ @@ -10,14 +16,40 @@ export type CustomPreMetadataProps = { showLineNumbers?: boolean; }; +const languageIcons: Record>> = { + typescript: TypescriptIcon, + javascript: TypescriptIcon, + ts: TypescriptIcon, + js: TypescriptIcon, + rust: RustIcon, + rs: RustIcon, + sh: TerminalIcon, + shell: TerminalIcon, + bash: TerminalIcon, + diff: FileDiffIcon, +}; + +const getIconForLanguage = ( + language: string | undefined, +): React.FC> | undefined => { + if (!language) return undefined; + return languageIcons[language]; +}; + export function MarkdownPre({ children, ...props }: React.ComponentProps<"pre"> & CustomPreMetadataProps) { + const language = props["data-language"]; + const Icon = getIconForLanguage(language); + return (
- {!!props.filename && ( -
{props.filename}
+ {(Icon || props.filename) && ( +
+ {Icon && } + {props.filename} +
)}
         {children}
diff --git a/src/utils/markdown.ts b/src/utils/markdown.ts
index 426398a8c..ba9d97431 100644
--- a/src/utils/markdown.ts
+++ b/src/utils/markdown.ts
@@ -5,7 +5,8 @@ import rehypePrettyCode, {
   Options as RehypePrettyCodeOptions,
 } from "rehype-pretty-code";
 import { transformerNotationDiff } from "@shikijs/transformers";
-import codeTheme from "shiki/themes/github-dark-dimmed.mjs";
+import darkTheme from "shiki/themes/github-dark-dimmed.mjs";
+import lightTheme from "shiki/themes/github-light.mjs";
 // import codeTheme from "shiki/themes/rose-pine-moon.mjs";
 
 // import codeTheme from "shiki/themes/andromeeda.mjs";
@@ -116,7 +117,10 @@ export const rehypePluginConfig: import("unified").PluggableList = [
       defaultLang: {
         block: "text",
       },
-      theme: codeTheme,
+      theme: {
+        dark: darkTheme,
+        light: lightTheme,
+      },
       transformers: [transformerNotationDiff()],
     } as RehypePrettyCodeOptions,
     // rehypeSanitize,

From 364104f70f17b622669838be1c281a34c4341016 Mon Sep 17 00:00:00 2001
From: John 
Date: Tue, 30 Jul 2024 11:51:36 -0500
Subject: [PATCH 06/12] add lightmode to copytoclipboard and move svgs

---
 public/src/img/icons/Copy.inline.svg          | 12 ++++++
 public/src/img/icons/CopyConfirm.inline.svg   | 12 ++++++
 .../CopyToClipBoardButton.module.scss         | 26 +++++++++++--
 .../components/CopyToClipBoardButton.tsx      | 39 +++----------------
 4 files changed, 51 insertions(+), 38 deletions(-)
 create mode 100644 public/src/img/icons/Copy.inline.svg
 create mode 100644 public/src/img/icons/CopyConfirm.inline.svg

diff --git a/public/src/img/icons/Copy.inline.svg b/public/src/img/icons/Copy.inline.svg
new file mode 100644
index 000000000..b52f3a555
--- /dev/null
+++ b/public/src/img/icons/Copy.inline.svg
@@ -0,0 +1,12 @@
+ 
+    
+
\ No newline at end of file
diff --git a/public/src/img/icons/CopyConfirm.inline.svg b/public/src/img/icons/CopyConfirm.inline.svg
new file mode 100644
index 000000000..4572ea5bf
--- /dev/null
+++ b/public/src/img/icons/CopyConfirm.inline.svg
@@ -0,0 +1,12 @@
+
+    
+
\ No newline at end of file
diff --git a/src/components/shared/MarkdownRenderer/components/CopyToClipBoardButton.module.scss b/src/components/shared/MarkdownRenderer/components/CopyToClipBoardButton.module.scss
index f7e53ac10..e01f2ca21 100644
--- a/src/components/shared/MarkdownRenderer/components/CopyToClipBoardButton.module.scss
+++ b/src/components/shared/MarkdownRenderer/components/CopyToClipBoardButton.module.scss
@@ -7,10 +7,28 @@
   border-radius: 0.4rem;
   color: #adbac7;
   background-color: #1b1f25;
+  transition:
+    color 0.2s,
+    background-color 0.2s,
+    border-color 0.2s;
+
+  &:hover {
+    color: #fff;
+    background-color: #2d333b;
+    border-color: #838383 !important;
+  }
 }
 
-.button:hover {
-  color: #fff;
-  background-color: #1b1f25;
-  border-color: #838383 !important;
+:global(.light) {
+  .button {
+    color: #24292e;
+    background-color: #f6f8fa;
+    border-color: #d1d5da !important;
+
+    &:hover {
+      color: #24292e;
+      background-color: #e1e4e8;
+      border-color: #b1b5ba !important;
+    }
+  }
 }
diff --git a/src/components/shared/MarkdownRenderer/components/CopyToClipBoardButton.tsx b/src/components/shared/MarkdownRenderer/components/CopyToClipBoardButton.tsx
index 7c6ced35b..eb8e9b7d5 100644
--- a/src/components/shared/MarkdownRenderer/components/CopyToClipBoardButton.tsx
+++ b/src/components/shared/MarkdownRenderer/components/CopyToClipBoardButton.tsx
@@ -1,8 +1,9 @@
-"use client";
-
 import styles from "./CopyToClipBoardButton.module.scss";
 import { useCallback, useEffect, useRef, useState } from "react";
 
+import CopyIcon from "../../../../../public/src/img/icons/Copy.inline.svg";
+import CopyConfirmIcon from "../../../../../public/src/img/icons/CopyConfirm.inline.svg";
+
 export function CopyToClipBoardButton() {
   const btnRef = useRef(null);
   const [isCopied, setIsCopied] = useState(false);
@@ -35,37 +36,7 @@ export function CopyToClipBoardButton() {
     }
   }, [btnRef]);
 
-  const IconToUse = isCopied ? (
-    
-      
-    
-  ) : (
-    
-      
-    
-  );
+  const IconToUse = isCopied ? CopyConfirmIcon : CopyIcon;
 
   return (
     
   );
 }

From 88b40c02bd466e5198df5cb17ace1e012603eeba Mon Sep 17 00:00:00 2001
From: John 
Date: Tue, 30 Jul 2024 15:02:19 -0500
Subject: [PATCH 07/12] fix doc toc parsing bug

---
 src/utils/contentApi.ts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/utils/contentApi.ts b/src/utils/contentApi.ts
index c457bd316..aff7250de 100644
--- a/src/utils/contentApi.ts
+++ b/src/utils/contentApi.ts
@@ -353,7 +353,7 @@ export default class ContentApi {
 
         // we remove any special characters from the end of the label
         // to make it look cleaner in the UI
-        label = label.split(/[\v{L|N}]*$/)[0];
+        label = label.replace(/[^a-zA-Z0-9]+$/, "");
 
         // if (!duplicator.has(label)) {
         //   duplicator.set(label, 0);
@@ -388,7 +388,7 @@ export default class ContentApi {
         .trim()
         .replace(/\s+/g, "-")
         .replace(/\./g, "")
-        .replace(/[[\v{L|N}]*]+/g, "-")
+        .replace(/[^a-z0-9]+/g, "-")
         .replace(/^-/g, "")
         .replace(/-$/g, "")
         .replace(/--+/g, "-");

From 33a3f9f42997a2a3031e221f70ac1e7983c5a118 Mon Sep 17 00:00:00 2001
From: John 
Date: Tue, 30 Jul 2024 17:38:39 -0500
Subject: [PATCH 08/12] update toc  edit page / scroll to top

---
 .../DevelopersContentPage.module.scss         | 24 +++++++++
 .../DevelopersContentPage.tsx                 | 16 +-----
 .../DevelopersContentPage/TableOfContents.tsx | 51 +++++++++++++++----
 src/pages/docs/[[...slug]].tsx                | 15 +-----
 src/pages/docs/rpc/[[...slug]].tsx            | 13 +----
 5 files changed, 67 insertions(+), 52 deletions(-)

diff --git a/src/components/developers/DevelopersContentPage/DevelopersContentPage.module.scss b/src/components/developers/DevelopersContentPage/DevelopersContentPage.module.scss
index 15d7109d9..a292535f3 100644
--- a/src/components/developers/DevelopersContentPage/DevelopersContentPage.module.scss
+++ b/src/components/developers/DevelopersContentPage/DevelopersContentPage.module.scss
@@ -553,4 +553,28 @@
       }
     }
   }
+
+  .scroll-to-top {
+    opacity: 0;
+    visibility: hidden;
+    transition:
+      opacity 0.2s ease,
+      visibility 0.2s ease;
+
+    &.show {
+      opacity: 1;
+      visibility: visible;
+    }
+  }
+
+  .toc-action-item {
+    justify-content: flex-start;
+    gap: 0.7rem;
+    padding: 0.5rem 1rem;
+    color: inherit;
+  }
+
+  .toc-action-item:hover {
+    background-color: transparent;
+  }
 }
diff --git a/src/components/developers/DevelopersContentPage/DevelopersContentPage.tsx b/src/components/developers/DevelopersContentPage/DevelopersContentPage.tsx
index 0542a32d9..64a10a6f0 100644
--- a/src/components/developers/DevelopersContentPage/DevelopersContentPage.tsx
+++ b/src/components/developers/DevelopersContentPage/DevelopersContentPage.tsx
@@ -5,14 +5,9 @@ import styles from "./DevelopersContentPage.module.scss";
 import { FormattedDate } from "@/components/SolFormattedMessage";
 import MarkdownRenderer from "@/components/shared/MarkdownRenderer/MarkdownRenderer";
 import Link from "next/link";
-import ContentApi from "@/utils/contentApi";
 import Image from "next/image";
-
 import defaultImg from "@@/public/social/solana.jpg";
 import blurImage from "@@/public/img/blurImage.png";
-import ArrowLeft from "@@/public/src/img/icons/ArrowLeft.inline.svg";
-
-import GithubIcon from "@@/public/src/img/footer/github.inline.svg";
 import SocialShareButtons from "@/components/sharedPageSections/SocialShareButtons";
 import { config } from "src/config";
 import { useRouter } from "next/router";
@@ -156,17 +151,8 @@ export default memo(function DevelopersContentPage({
                 !!showSidebar &&
                 styles["developers-content-page__sidebar__active"]
               }
+              githubPath={record._raw.sourceFilePath}
             />
-
-            
-              
-              {t("shared.general.edit-page")}
-              
-            
           
         
       
diff --git a/src/components/developers/DevelopersContentPage/TableOfContents.tsx b/src/components/developers/DevelopersContentPage/TableOfContents.tsx
index b0d7b0b00..18a1bec1f 100644
--- a/src/components/developers/DevelopersContentPage/TableOfContents.tsx
+++ b/src/components/developers/DevelopersContentPage/TableOfContents.tsx
@@ -1,10 +1,11 @@
-import { memo } from "react";
+import { memo, useEffect, useState } from "react";
 import classNames from "classnames";
 import styles from "./DevelopersContentPage.module.scss";
 import Link from "next/link";
 import ContentApi from "@/utils/contentApi";
 import { TOC_HEADING_SIZE } from "@/constants/developerContentConfig";
 import ArrowLeft from "@@/public/src/img/icons/ArrowLeft.inline.svg";
+import GithubIcon from "@@/public/src/img/footer/github.inline.svg";
 import { useTranslation } from "next-i18next";
 
 type TableOfContentsProps = {
@@ -18,6 +19,8 @@ type TableOfContentsProps = {
   content: string;
   /** the current router's path */
   currentPath: string;
+  /** the path to the github repo */
+  githubPath: string;
 };
 
 /**
@@ -31,6 +34,7 @@ export const TableOfContents = memo(
     content = "",
     className = "",
     currentPath = "",
+    githubPath = "",
   }: TableOfContentsProps) => {
     const { t } = useTranslation("common");
 
@@ -42,6 +46,21 @@ export const TableOfContents = memo(
     // show nothing if we are unable to parse the TOC
     // if (!toc || toc?.length <= 0) return <>;
 
+    const [showScrollToTop, setShowScrollToTop] = useState(false);
+
+    useEffect(() => {
+      const checkScroll = () => {
+        setShowScrollToTop(window.scrollY > window.innerHeight);
+      };
+
+      window.addEventListener("scroll", checkScroll);
+      return () => window.removeEventListener("scroll", checkScroll);
+    }, []);
+
+    const scrollToTop = () => {
+      window.scrollTo({ top: 0, behavior: "smooth" });
+    };
+
     return (
       
{!!title &&
{title}
} @@ -69,17 +88,27 @@ export const TableOfContents = memo( ))} - - typeof window != "undefined" && - window.scrollTo({ top: 0, behavior: "instant" }) - } - className={styles["developers-content-page__simpleButton"]} +
  • + + + {t("shared.general.edit-page")} + +
  • + +
  • - - {t("shared.general.scroll-to-top")} - + +
  • ); }, diff --git a/src/pages/docs/[[...slug]].tsx b/src/pages/docs/[[...slug]].tsx index b6e9c8180..ca7f5cf8d 100644 --- a/src/pages/docs/[[...slug]].tsx +++ b/src/pages/docs/[[...slug]].tsx @@ -14,8 +14,6 @@ import MarkdownRenderer from "@/components/shared/MarkdownRenderer/MarkdownRende import Link from "next/link"; import { useRouter } from "next/router"; -import ArrowLeft from "@@/public/src/img/icons/ArrowLeft.inline.svg"; -import GithubIcon from "@@/public/src/img/footer/github.inline.svg"; import DocsNavSidebar from "@/components/developers/DocsNavSidebar"; import { InferGetStaticPropsType } from "next"; import { SidebarToggleButton } from "@/components/developers/DevelopersContentPage/SidebarToggleButton"; @@ -75,19 +73,8 @@ export default function DeveloperDocs({ title={t("shared.general.toc")} currentPath={router.asPath} content={record.body} + githubPath={record._raw.sourceFilePath} /> - - - - {t("shared.general.edit-page")} - -
    - - - - {t("shared.general.edit-page")} - - )} From 427b915e6d03d0cf06da17d13afe7bc21813d3e2 Mon Sep 17 00:00:00 2001 From: John Date: Tue, 30 Jul 2024 18:10:23 -0500 Subject: [PATCH 09/12] reorder docs secondary nav and add stack exchange --- .../DevelopersNav/DevelopersNav.jsx | 42 ++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/src/components/developers/DevelopersNav/DevelopersNav.jsx b/src/components/developers/DevelopersNav/DevelopersNav.jsx index ee5654c4e..c43231a18 100644 --- a/src/components/developers/DevelopersNav/DevelopersNav.jsx +++ b/src/components/developers/DevelopersNav/DevelopersNav.jsx @@ -6,6 +6,7 @@ import CookbookIcon from "../../../../public/src/img/developers/cookbook.inline. import GuidesIcon from "../../../../public/src/img/developers/guides.inline.svg"; import TerminologyIcon from "../../../../public/src/img/developers/terminology.inline.svg"; import CoursesIcon from "../../../../public/src/img/developers/courses.inline.svg"; +import StackExchangeIcon from "../../../../assets/developers/stackexchange.inline.svg"; import { useTranslation } from "next-i18next"; export default function DevelopersNav({ containerClassName }) { @@ -27,20 +28,6 @@ export default function DevelopersNav({ containerClassName }) { {t("developers.nav.documentation")} - - - {t("developers.nav.rpc")} - - - - - {t("developers.nav.cookbook")} - - {t("developers.nav.guides")} + + + + {t("developers.nav.cookbook")} + + {t("developers.nav.terminology")} + + + {t("developers.nav.rpc")} + + + + Stack Exchange + From 1080730dbd6ce385a74c5881ba743093c62588bc Mon Sep 17 00:00:00 2001 From: John Date: Wed, 31 Jul 2024 14:34:37 -0500 Subject: [PATCH 10/12] update svg paths with /@@ --- .../developers/DevelopersNav/DevelopersNav.jsx | 14 +++++++------- .../components/CopyToClipBoardButton.tsx | 4 ++-- .../MarkdownRenderer/components/MarkdownPre.tsx | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/components/developers/DevelopersNav/DevelopersNav.jsx b/src/components/developers/DevelopersNav/DevelopersNav.jsx index c43231a18..45b71227b 100644 --- a/src/components/developers/DevelopersNav/DevelopersNav.jsx +++ b/src/components/developers/DevelopersNav/DevelopersNav.jsx @@ -1,12 +1,12 @@ import styles from "./DevelopersNav.module.scss"; import Link from "@/utils/Link"; -import DocsIcon from "../../../../public/src/img/developers/docs.inline.svg"; -import RpcApiIcon from "../../../../public/src/img/developers/api.inline.svg"; -import CookbookIcon from "../../../../public/src/img/developers/cookbook.inline.svg"; -import GuidesIcon from "../../../../public/src/img/developers/guides.inline.svg"; -import TerminologyIcon from "../../../../public/src/img/developers/terminology.inline.svg"; -import CoursesIcon from "../../../../public/src/img/developers/courses.inline.svg"; -import StackExchangeIcon from "../../../../assets/developers/stackexchange.inline.svg"; +import DocsIcon from "@@/public/src/img/developers/docs.inline.svg"; +import RpcApiIcon from "@@/public/src/img/developers/api.inline.svg"; +import CookbookIcon from "@@/public/src/img/developers/cookbook.inline.svg"; +import GuidesIcon from "@@/public/src/img/developers/guides.inline.svg"; +import TerminologyIcon from "@@/public/src/img/developers/terminology.inline.svg"; +import CoursesIcon from "@@/public/src/img/developers/courses.inline.svg"; +import StackExchangeIcon from "@@/assets/developers/stackexchange.inline.svg"; import { useTranslation } from "next-i18next"; export default function DevelopersNav({ containerClassName }) { diff --git a/src/components/shared/MarkdownRenderer/components/CopyToClipBoardButton.tsx b/src/components/shared/MarkdownRenderer/components/CopyToClipBoardButton.tsx index eb8e9b7d5..0ba1adab7 100644 --- a/src/components/shared/MarkdownRenderer/components/CopyToClipBoardButton.tsx +++ b/src/components/shared/MarkdownRenderer/components/CopyToClipBoardButton.tsx @@ -1,8 +1,8 @@ import styles from "./CopyToClipBoardButton.module.scss"; import { useCallback, useEffect, useRef, useState } from "react"; -import CopyIcon from "../../../../../public/src/img/icons/Copy.inline.svg"; -import CopyConfirmIcon from "../../../../../public/src/img/icons/CopyConfirm.inline.svg"; +import CopyIcon from "@@/public/src/img/icons/Copy.inline.svg"; +import CopyConfirmIcon from "@@/public/src/img/icons/CopyConfirm.inline.svg"; export function CopyToClipBoardButton() { const btnRef = useRef(null); diff --git a/src/components/shared/MarkdownRenderer/components/MarkdownPre.tsx b/src/components/shared/MarkdownRenderer/components/MarkdownPre.tsx index e34d469e1..8be8d0f99 100644 --- a/src/components/shared/MarkdownRenderer/components/MarkdownPre.tsx +++ b/src/components/shared/MarkdownRenderer/components/MarkdownPre.tsx @@ -2,10 +2,10 @@ import React from "react"; import styles from "./MarkdownPre.module.scss"; import { CopyToClipBoardButton } from "./CopyToClipBoardButton"; -import RustIcon from "../../../../../public/src/img/icons/Rust.inline.svg"; -import TypescriptIcon from "../../../../../public/src/img/icons/Typescript.inline.svg"; -import TerminalIcon from "../../../../../public/src/img/icons/Terminal.inline.svg"; -import FileDiffIcon from "../../../../../public/src/img/icons/FileDiff.inline.svg"; +import RustIcon from "@@/public/src/img/icons/Rust.inline.svg"; +import TypescriptIcon from "@@/public/src/img/icons/Typescript.inline.svg"; +import TerminalIcon from "@@/public/src/img/icons/Terminal.inline.svg"; +import FileDiffIcon from "@@/public/src/img/icons/FileDiff.inline.svg"; /** * Listing of the supported custom metadata that can be attached to parsed components via `attachMetadata` From 56ecba143ffe692d8e8e630dab69abf7139d60b9 Mon Sep 17 00:00:00 2001 From: John Date: Wed, 31 Jul 2024 15:22:51 -0500 Subject: [PATCH 11/12] update contentApi regex --- src/utils/contentApi.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/contentApi.ts b/src/utils/contentApi.ts index aff7250de..3e2b2329f 100644 --- a/src/utils/contentApi.ts +++ b/src/utils/contentApi.ts @@ -353,7 +353,7 @@ export default class ContentApi { // we remove any special characters from the end of the label // to make it look cleaner in the UI - label = label.replace(/[^a-zA-Z0-9]+$/, ""); + label = label.replace(/[^\p{L}\p{N}]+$/u, ""); // if (!duplicator.has(label)) { // duplicator.set(label, 0); @@ -388,7 +388,7 @@ export default class ContentApi { .trim() .replace(/\s+/g, "-") .replace(/\./g, "") - .replace(/[^a-z0-9]+/g, "-") + .replace(/[^\p{L}\p{N}]+/gu, "-") .replace(/^-/g, "") .replace(/-$/g, "") .replace(/--+/g, "-"); From 578220740406a68e407502460128c6982ae5a0cd Mon Sep 17 00:00:00 2001 From: John Date: Thu, 1 Aug 2024 10:53:05 -0500 Subject: [PATCH 12/12] tsignore --- src/utils/contentApi.ts | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/utils/contentApi.ts b/src/utils/contentApi.ts index 3e2b2329f..a173bab9c 100644 --- a/src/utils/contentApi.ts +++ b/src/utils/contentApi.ts @@ -353,6 +353,7 @@ export default class ContentApi { // we remove any special characters from the end of the label // to make it look cleaner in the UI + // @ts-ignore label = label.replace(/[^\p{L}\p{N}]+$/u, ""); // if (!duplicator.has(label)) { @@ -380,18 +381,21 @@ export default class ContentApi { */ static slugify(url: string): string { try { - return url - .toString() - .normalize("NFD") - .replace(/[\u0300-\u036f]/g, "") - .toLowerCase() - .trim() - .replace(/\s+/g, "-") - .replace(/\./g, "") - .replace(/[^\p{L}\p{N}]+/gu, "-") - .replace(/^-/g, "") - .replace(/-$/g, "") - .replace(/--+/g, "-"); + return ( + url + .toString() + .normalize("NFD") + .replace(/[\u0300-\u036f]/g, "") + .toLowerCase() + .trim() + .replace(/\s+/g, "-") + .replace(/\./g, "") + // @ts-ignore + .replace(/[^\p{L}\p{N}]+/gu, "-") + .replace(/^-/g, "") + .replace(/-$/g, "") + .replace(/--+/g, "-") + ); } catch (err) { console.error("[slugify error]", err); return "#err";