diff --git a/nx-dev/ui-fence/src/lib/fence.tsx b/nx-dev/ui-fence/src/lib/fence.tsx
index 8f75a26b1a..43cdc7e079 100644
--- a/nx-dev/ui-fence/src/lib/fence.tsx
+++ b/nx-dev/ui-fence/src/lib/fence.tsx
@@ -4,6 +4,7 @@ import {
ClipboardDocumentIcon,
SparklesIcon,
} from '@heroicons/react/24/outline';
+import cx from 'classnames';
import { JSX, ReactNode, useEffect, useState } from 'react';
// @ts-ignore
import { CopyToClipboard } from 'react-copy-to-clipboard';
@@ -31,6 +32,7 @@ function CodeWrapper(options: {
title: string;
path: string;
language: string;
+ isWithinTab?: boolean;
children: string; // intentionally typed as such
}): ({ children }: { children: ReactNode }) => JSX.Element {
return ({ children }: { children: ReactNode }) =>
@@ -49,7 +51,11 @@ function CodeWrapper(options: {
title={options.title}
/>
) : (
-
+
);
}
@@ -92,6 +98,7 @@ export interface FenceProps {
skipRescope?: boolean;
selectedLineGroup?: string;
onLineGroupSelectionChange?: (selection: string) => void;
+ isWithinTab?: boolean;
}
export function Fence({
@@ -107,6 +114,7 @@ export function Fence({
selectedLineGroup,
skipRescope,
onLineGroupSelectionChange,
+ isWithinTab,
}: FenceProps) {
if (highlightLines) {
highlightLines = processHighlightLines(highlightLines);
@@ -168,7 +176,12 @@ export function Fence({
}
return (
-
+
{enableCopy && enableCopy === true && (
@@ -182,7 +195,7 @@ export function Fence({
type="button"
className={
'not-prose flex border border-slate-200 bg-slate-50/50 p-2 opacity-0 transition-opacity group-hover:opacity-100 dark:border-slate-700 dark:bg-slate-800/60' +
- (highlightOptions && highlightOptions[0]
+ ((highlightOptions && highlightOptions[0]) || isWithinTab
? ''
: ' rounded-tr-lg')
}
@@ -197,7 +210,7 @@ export function Fence({
)}
{highlightOptions && highlightOptions[0] && (
diff --git a/nx-dev/ui-fence/src/lib/fences/code-output.tsx b/nx-dev/ui-fence/src/lib/fences/code-output.tsx
index 6a20c8b186..d2c9f9ee70 100644
--- a/nx-dev/ui-fence/src/lib/fences/code-output.tsx
+++ b/nx-dev/ui-fence/src/lib/fences/code-output.tsx
@@ -1,14 +1,22 @@
import { JSX, ReactNode } from 'react';
+import cx from 'classnames';
export function CodeOutput({
content,
fileName,
+ isWithinTab,
}: {
content: ReactNode;
fileName: string;
+ isWithinTab?: boolean;
}): JSX.Element {
return (
-
+
{!!fileName && (
{fileName}
diff --git a/nx-dev/ui-markdoc/src/lib/nodes/fence-wrapper.component.tsx b/nx-dev/ui-markdoc/src/lib/nodes/fence-wrapper.component.tsx
index f7d2996bed..47c11fe26c 100644
--- a/nx-dev/ui-markdoc/src/lib/nodes/fence-wrapper.component.tsx
+++ b/nx-dev/ui-markdoc/src/lib/nodes/fence-wrapper.component.tsx
@@ -34,7 +34,7 @@ export function FenceWrapper(props: FenceProps) {
};
return (
-
+
);
diff --git a/nx-dev/ui-markdoc/src/lib/tags/tabs.component.tsx b/nx-dev/ui-markdoc/src/lib/tags/tabs.component.tsx
index 7843cd2146..fd5d75d548 100644
--- a/nx-dev/ui-markdoc/src/lib/tags/tabs.component.tsx
+++ b/nx-dev/ui-markdoc/src/lib/tags/tabs.component.tsx
@@ -1,12 +1,12 @@
'use client';
-// TODO@ben: refactor to use HeadlessUI tabs
import cx from 'classnames';
-import {
+import React, {
createContext,
ReactNode,
useContext,
useEffect,
useState,
+ cloneElement,
} from 'react';
export const TabContext = createContext('');
@@ -20,7 +20,8 @@ export function Tabs({
labels: string[];
children: ReactNode;
}) {
- const [currentTab, setCurrentTab] = useState(labels[0]);
+ const [currentTab, setCurrentTab] = useState
(labels[0]);
+
useEffect(() => {
const handleTabSelectedEvent = () => {
const selectedTab = localStorage.getItem(SELECTED_TAB_KEY);
@@ -28,43 +29,49 @@ export function Tabs({
setCurrentTab(selectedTab);
}
};
+
handleTabSelectedEvent();
window.addEventListener(TAB_SELECTED_EVENT, handleTabSelectedEvent);
return () =>
window.removeEventListener(TAB_SELECTED_EVENT, handleTabSelectedEvent);
}, [labels]);
+ const handleTabClick = (label: string) => {
+ localStorage.setItem(SELECTED_TAB_KEY, label);
+ window.dispatchEvent(new Event(TAB_SELECTED_EVENT));
+ setCurrentTab(label);
+ };
+
return (
-
-
-
-
-
-
+
+
{children}
-
+
);
}
@@ -77,14 +84,23 @@ export function Tab({
children: ReactNode;
}) {
const currentTab = useContext(TabContext);
+ const isActive = label === currentTab;
- if (label !== currentTab) {
- return null;
- }
+ const passPropsToChildren = (children: ReactNode) => {
+ return React.Children.map(children, (child) => {
+ if (React.isValidElement(child) && typeof child.type !== 'string') {
+ return cloneElement(child, { isWithinTab: true });
+ }
+ return child;
+ });
+ };
return (
-
- {children}
+
+ {isActive && passPropsToChildren(children)}
);
}