Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions apps/frontpage/app/docs/provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@ import {
cookieLanguageId,
cookiePackageManagerId,
cookieRenderId,
cookieSnippetTabsId,
} from '../../constants';

export interface DocsContextProps {
activeRenderer: null | string;
setRenderer: (id: string) => void;
activeLanguage: null | string;
activeSnippetTabs: null | string[];
setLanguage: (id: string) => void;
activePackageManager: null | string;
setPackageManager: (id: string) => void;
setSnippetTabs: (id: string) => void;
}

export const DocsContext = createContext<DocsContextProps | undefined>(
Expand All @@ -33,11 +36,13 @@ export function DocsProvider({ children }: { children: ReactNode }) {
const [activePackageManager, setActivePackageManager] = useState<
null | string
>(packageManagers[0].id);
const [activeSnippetTabs, setActiveSnippetTabs] = useState<string[]>([]);

useEffect(() => {
const cookieRenderer = getCookie(cookieRenderId);
const cookieLanguage = getCookie(cookieLanguageId);
const cookiePackageManager = getCookie(cookiePackageManagerId);
const cookieSnippetTabs = getCookie(cookieSnippetTabsId);

if (cookieRenderer) {
setActiveRenderer(cookieRenderer);
Expand All @@ -56,6 +61,12 @@ export function DocsProvider({ children }: { children: ReactNode }) {
} else {
setCookie(cookiePackageManagerId, packageManagers[0].id);
}

if (cookieSnippetTabs) {
setActiveSnippetTabs(cookieSnippetTabs.split(',').map(decodeURIComponent));
} else {
setCookie(cookieSnippetTabsId, '');
}
}, []);

const setRenderer = (id: string) => {
Expand All @@ -73,15 +84,25 @@ export function DocsProvider({ children }: { children: ReactNode }) {
setCookie(cookiePackageManagerId, id);
};

const setSnippetTabs = (id: string) => {
setActiveSnippetTabs((prev) => [id, ...prev.filter((tab) => tab !== id)]);
setCookie(
cookieSnippetTabsId,
[id, ...activeSnippetTabs.filter((tab) => tab !== id)].join(','),
);
};

return (
<DocsContext.Provider
value={{
activeRenderer,
setRenderer,
activeLanguage,
activeSnippetTabs,
setLanguage,
activePackageManager,
setPackageManager,
setSnippetTabs,
}}
>
{children}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@ const meta = {
},
args: {
activeRenderer: 'react',
activeLanguage: null,
activePackageManager: null,
activeLanguage: 'js',
activePackageManager: 'npm',
activeSnippetTabs: [],
content: content1,
},
decorators: [
Expand All @@ -76,6 +77,11 @@ const meta = {
.mockImplementation((id) => {
setArgs({ activeRenderer: id });
}),
setSnippetTabs: fn()
.mockName('setSnippetTabs')
.mockImplementation((id) => {
setArgs({ activeSnippetTabs: id });
}),
}}
>
<Story />
Expand All @@ -88,6 +94,7 @@ const meta = {
activeRenderer: string | null;
activePackageManager: string | null;
activeLanguage: string | null;
activeSnippetTabs: string[] | null;
}
>;

Expand All @@ -101,7 +108,6 @@ export const ContentOnly: Story = {
export const PackageNPM: Story = {
args: {
content: content1,
activePackageManager: 'npm',
},
};

Expand All @@ -122,15 +128,13 @@ export const PackagePNPM: Story = {
export const ReactNoLanguage: Story = {
args: {
content: content2,
activeRenderer: 'react',
activeLanguage: null,
},
};

export const ReactJS: Story = {
args: {
content: content2,
activeRenderer: 'react',
activeLanguage: 'js',
},
};

Expand All @@ -145,6 +149,7 @@ export const AngularNoLanguage: Story = {
args: {
content: content2,
activeRenderer: 'angular',
activeLanguage: null,
},
};

Expand All @@ -158,39 +163,41 @@ export const ReactNativeWebFallbackToReact: Story = {
export const MultipleTabs: Story = {
args: {
content: contentMultiTab,
activeLanguage: 'js',
},
};

export const MultipleTabsWithTabFromCookie: Story = {
args: {
content: contentMultiTab,
activeSnippetTabs: ['vite'],
},
};

export const MultipleTabsVue3Only: Story = {
args: {
content: contentMultiTabVue3Only,
activeRenderer: 'vue',
activeLanguage: 'js',
},
};

export const MultipleTabsVue3OnlySuffix: Story = {
args: {
content: contentMultiTabVue3OnlySuffix,
activeRenderer: 'vue',
activeLanguage: 'js',
},
};

export const MultipleTabsVue2And3: Story = {
args: {
content: contentMultiTabVue2And3,
activeRenderer: 'vue',
activeLanguage: 'js',
},
};

export const MultipleTabsVue2And3Suffix: Story = {
args: {
content: contentMultiTabVue2And3Suffix,
activeRenderer: 'vue',
activeLanguage: 'js',
},
};

Expand All @@ -206,7 +213,6 @@ export const NoRenderer: Story = {
args: {
content: content2,
activeRenderer: 'ember',
activeLanguage: 'js',
},
};

Expand Down
32 changes: 27 additions & 5 deletions apps/frontpage/components/docs/mdx/code-snippets/code-snippets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ interface CodeSnippetsClientProps {
content: CodeSnippetsProps[] | null;
}

const getInitialTab = (tabs: Tab[], activeSnippetTabs: string[]) => {
let initialTab: Tab | undefined;

activeSnippetTabs.forEach((localTab) => {
initialTab ??= tabs.find((tab) => tab.id === localTab);
initialTab ??= tabs.find((tab) => tab.id.includes(localTab) || localTab.includes(tab.id));
});
return initialTab;
};

const Error = () => {
return (
<div>
Expand Down Expand Up @@ -62,8 +72,10 @@ export const CodeSnippetsClient: FC<CodeSnippetsClientProps> = ({
activeRenderer: activeRendererIn,
activeLanguage,
activePackageManager,
activeSnippetTabs,
setLanguage,
setPackageManager,
setSnippetTabs,
} = useDocs();
const [activeTab, setActiveTab] = useState<Tab['id'] | null>(null);

Expand All @@ -81,6 +93,11 @@ export const CodeSnippetsClient: FC<CodeSnippetsClientProps> = ({
setPackageManager(id);
};

const handleTabChange = (id: string) => {
setActiveTab(id);
setSnippetTabs(id);
};

// Get possible tabs and their content
const { activeContentTabs, error: errorTabs } = getActiveContentTabs({
content: content ?? [],
Expand Down Expand Up @@ -108,15 +125,20 @@ export const CodeSnippetsClient: FC<CodeSnippetsClientProps> = ({
activeLanguage &&
activePackageManager &&
activeRenderer &&
activeSnippetTabs &&
tabs &&
tabs.length > 0 &&
!activeTab
tabs.length > 0
) {
setActiveTab(tabs[0].id);
const initialTab = activeSnippetTabs?.length > 0 ? getInitialTab(tabs, activeSnippetTabs) : undefined;
if (initialTab) {
setActiveTab(initialTab.id);
} else if (!activeTab) {
setActiveTab(tabs[0].id);
}
} else if (tabs && tabs.length === 0 && activeTab) {
setActiveTab(null);
}
}, [activeTab, tabs, activeLanguage, activePackageManager, activeRenderer]);
}, [activeTab, tabs, activeLanguage, activePackageManager, activeRenderer, activeSnippetTabs]);

if (!content)
return (
Expand All @@ -143,7 +165,7 @@ export const CodeSnippetsClient: FC<CodeSnippetsClientProps> = ({
copy={activeContent?.raw ?? ''}
top={
tabs && tabs.length > 1 ? (
<Tabs activeTab={activeTab} onTabChange={setActiveTab} tabs={tabs} />
<Tabs activeTab={activeTab} onTabChange={handleTabChange} tabs={tabs} />
) : null
}
options={
Expand Down
1 change: 1 addition & 0 deletions apps/frontpage/constants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export const cookieRenderId = 'sb-docs-renderer';
export const cookieLanguageId = 'sb-docs-language';
export const cookiePackageManagerId = 'sb-docs-package-manager';
export const cookieSnippetTabsId = 'sb-docs-snippet-tabs';