Skip to content

Commit

Permalink
feat: Add Markdown Tabs
Browse files Browse the repository at this point in the history
  • Loading branch information
cqh963852 committed Jun 30, 2024
1 parent 467a4f0 commit c310565
Show file tree
Hide file tree
Showing 16 changed files with 1,339 additions and 11 deletions.
15 changes: 15 additions & 0 deletions apps/website/app/tutorials/quickstart/page.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Tabs from "@/components/MarkdownTabs";
import TabItem from "@/components/MarkdownTabs/TabItem";

# Install camphora-styled

<Tabs defaultValue="npm">
<TabItem value="npm" label="NPM">
npm i -D camphora-styled@latest
</TabItem>
<TabItem value="yarn" label="YARN">
yarn add -D camphora-styled@latest
</TabItem>
</Tabs>

# camphora-styled Example Repositories
1 change: 1 addition & 0 deletions apps/website/components/Drawer/DrawerContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ interface IProps {}

const DrawerContent = (props: PropsWithChildren<IProps>) => {
const { children } = props;

return <div className={clsx(drawerContent)}>{children}</div>;
};

Expand Down
1 change: 1 addition & 0 deletions apps/website/components/Drawer/DrawerSide.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ interface IProps {

export const DrawerSide = (props: PropsWithChildren<IProps>) => {
const { children, drawerId, overlay } = props;

return (
<div className={drawerSide}>
{overlay ?? <label htmlFor={drawerId} className={drawerOverlay} />}
Expand Down
1 change: 1 addition & 0 deletions apps/website/components/Drawer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ interface IProps {

const Drawer = (props: PropsWithChildren<IProps>) => {
const { children, drawerId } = props;

return (
<div className={clsx(Ia, drawer)}>
<input
Expand Down
31 changes: 31 additions & 0 deletions apps/website/components/MarkdownTabs/TabItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { tab, tabPanel } from "@idealjs/camphora-styled";
import clsx from "clsx";
import React, { Fragment, PropsWithChildren } from "react";

import { getDefaultValue, getGroupName } from "./context";

interface IProps {
label?: string;
value: string;
}

const TabItem = (props: PropsWithChildren<IProps>) => {
const { children, value, label } = props;
const groupName = getGroupName();
const defaultValue = getDefaultValue();

return (
<Fragment>
<input
className={clsx(tab)}
type="radio"
name={groupName}
defaultChecked={value == defaultValue}
aria-label={label ?? value}
/>
<div className={clsx(tabPanel)}>{children}</div>
</Fragment>
);
};

export default TabItem;
29 changes: 29 additions & 0 deletions apps/website/components/MarkdownTabs/context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import serverContext, {
getServerContext,
setServerContext,
} from "../utils/serverContext";

const groupNameContext = serverContext<string | null>(null);

export const getGroupName = () => {
const value = getServerContext(groupNameContext);
if (value == null) {
throw new Error("context not initialized");
}
return value;
};

export const setGroupName = (value: string) => {
setServerContext(groupNameContext, value);
};

const defaultValueContext = serverContext<string | null>(null);

export const getDefaultValue = () => {
const value = getServerContext(defaultValueContext);
return value;
};

export const setDefaultValue = (value: string) => {
setServerContext(defaultValueContext, value);
};
21 changes: 21 additions & 0 deletions apps/website/components/MarkdownTabs/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { paper, paperSecondary, tabs } from "@idealjs/camphora-styled";
import clsx from "clsx";
import { nanoid } from "nanoid";
import React, { PropsWithChildren } from "react";

import { setDefaultValue, setGroupName } from "./context";

interface IProps {
defaultValue?: string;
groupName?: string;
}

const Tabs = (props: PropsWithChildren<IProps>) => {
const { children, groupName, defaultValue } = props;
setGroupName(groupName ?? nanoid());
defaultValue != null && setDefaultValue(defaultValue);

return <div className={clsx(tabs, paper, paperSecondary)}>{children}</div>;
};

export default Tabs;
27 changes: 27 additions & 0 deletions apps/website/components/utils/serverContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import "server-only";

import { cache } from "react";

const serverContext = <T>(defaultValue: T) => {
const context = cache(() => ({ current: defaultValue }));
return context;
};

export default serverContext;

export const getServerContext = <T>(
context: () => {
current: T;
}
) => {
return context().current;
};

export const setServerContext = <T>(
context: () => {
current: T;
},
value: T
) => {
context().current = value;
};
2 changes: 1 addition & 1 deletion apps/website/features/LayoutDrawer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const LayoutDrawer = (props: PropsWithChildren<IProps>) => {
<li style={{ height: "8px" }}></li>
<li>
<Link
href={"/tutorial/quickstart"}
href={"/tutorials/quickstart"}
className={clsx(menuItem, button, buttonGhost)}
>
quick start
Expand Down
7 changes: 7 additions & 0 deletions apps/website/mdx-components.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { MDXComponents } from "mdx/types";

export function useMDXComponents(components: MDXComponents): MDXComponents {
return {
...components,
};
}
8 changes: 6 additions & 2 deletions apps/website/next.config.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
const { createVanillaExtractPlugin } = require("@vanilla-extract/next-plugin");
const withVanillaExtract = createVanillaExtractPlugin();
const createMDXPlugin = require("@next/mdx");
const { version } = require("./package.json");

const withMDX = createMDXPlugin();
const withVanillaExtract = createVanillaExtractPlugin();

/** @type {import('next').NextConfig} */
const nextConfig = {
pageExtensions: ["js", "jsx", "mdx", "ts", "tsx"],
publicRuntimeConfig: {
version,
},
};

module.exports = withVanillaExtract(nextConfig);
module.exports = withVanillaExtract(withMDX(nextConfig));
5 changes: 5 additions & 0 deletions apps/website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,19 @@
},
"dependencies": {
"@idealjs/camphora-styled": "workspace:^",
"@mdx-js/loader": "^3.0.1",
"@mdx-js/react": "^3.0.1",
"@next/mdx": "^14.2.4",
"clsx": "^2.1.1",
"nanoid": "^5.0.7",
"next": "14.2.4",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@playwright/test": "^1.45.0",
"@testing-library/react": "^16.0.0",
"@types/mdx": "^2.0.13",
"@types/node": "^20.14.9",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
Expand Down
1 change: 1 addition & 0 deletions packages/camphora-styled/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ export * from "./interactive.css";
export * from "./menu.css";
export * from "./navbar.css";
export * from "./paper.css";
export * from "./tabs.css";
export * from "./themes";
export * from "./tooltip.css";
2 changes: 1 addition & 1 deletion packages/camphora-styled/src/interactive.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export const Ia = style({});

export const IaData = style({
selectors: {
[`${Ia} > &`]: {
[`${Ia} &`]: {
display: "none",
},
},
Expand Down
41 changes: 41 additions & 0 deletions packages/camphora-styled/src/tabs.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { style } from "@vanilla-extract/css";

import { vars } from "./themes";

export const tabs = style({
display: "grid",
vars: {},
selectors: {},
});

export const tab = style({
selectors: {
[`${tabs} &`]: {
appearance: "none",
gridRowStart: 1,
margin: "0px",
backgroundColor: vars.colors.primary.bg,
color: vars.colors.primary.content,
},
[`${tabs} &:checked`]: {
backgroundColor: vars.colors.primary.focus,
},
["&:after"]: {
content: "attr(aria-label)",
},
},
});

export const tabPanel = style({
selectors: {
[`${tabs} &`]: {
gridColumnStart: 1,
gridRowStart: 2,
gridColumnEnd: "span 9999",
display: "none",
},
[`${tab}:checked+&`]: {
display: "block",
},
},
});
Loading

0 comments on commit c310565

Please sign in to comment.