diff --git a/package-lock.json b/package-lock.json index cf57eae..6b5c835 100644 --- a/package-lock.json +++ b/package-lock.json @@ -58,7 +58,6 @@ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -469,7 +468,6 @@ "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -2695,7 +2693,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz", "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -2813,7 +2810,6 @@ "integrity": "sha512-3xP4XzzDNQOIqBMWogftkwxhg5oMKApqY0BAflmLZiFYHqyhSOxv/cd/zPQLTcCXr4AkaKb25joocY0BD1WC6A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.51.0", "@typescript-eslint/types": "8.51.0", @@ -3184,7 +3180,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "devOptional": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3207,7 +3202,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -3411,7 +3405,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -3853,7 +3846,6 @@ "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", "license": "ISC", - "peer": true, "engines": { "node": ">=12" } @@ -4175,7 +4167,6 @@ "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -4988,7 +4979,6 @@ "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", "license": "MIT", - "peer": true, "bin": { "jiti": "lib/jiti-cli.mjs" } @@ -5133,7 +5123,6 @@ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz", "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==", "license": "MPL-2.0", - "peer": true, "dependencies": { "detect-libc": "^2.0.3" }, @@ -6425,7 +6414,6 @@ "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.53.0.tgz", "integrity": "sha512-0WNThgC6CMWNXXBxTbaYYcunj08iB5rnx4/G56UOPeL9UVIUGGHA1GR0EWIh9Ebabj7NpCRawQ5b0hfN1jQmYQ==", "license": "MIT", - "peer": true, "dependencies": { "@types/trusted-types": "^1.0.6" } @@ -6765,7 +6753,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -6894,7 +6881,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -6907,7 +6893,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -6954,7 +6939,6 @@ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", "license": "MIT", - "peer": true, "dependencies": { "@types/use-sync-external-store": "^0.0.6", "use-sync-external-store": "^1.4.0" @@ -7055,8 +7039,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/redux-thunk": { "version": "3.1.0", @@ -7584,8 +7567,7 @@ "version": "4.1.18", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz", "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/tapable": { "version": "2.3.0", @@ -7606,7 +7588,6 @@ "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", "devOptional": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", @@ -7773,7 +7754,6 @@ "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", "devOptional": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -7996,7 +7976,6 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", @@ -10386,7 +10365,6 @@ "packages/oc-spec-site/node_modules/react": { "version": "19.2.0", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } diff --git a/packages/oc-docs/src/components/Docs/CodeSnippets/CodeSnippets.tsx b/packages/oc-docs/src/components/Docs/CodeSnippets/CodeSnippets.tsx index 1470bac..2cf350d 100644 --- a/packages/oc-docs/src/components/Docs/CodeSnippets/CodeSnippets.tsx +++ b/packages/oc-docs/src/components/Docs/CodeSnippets/CodeSnippets.tsx @@ -1,5 +1,6 @@ -import React, { useState } from 'react'; -import { TabGroup, CompactCodeView } from '../../../ui/MinimalComponents'; +import React from 'react'; +import { TabGroup } from '../../../ui/MinimalComponents'; +import { Code } from '../../../ui/Code/Code'; import { StyledWrapper } from './StyledWrapper'; import { generateCurlCommand, generateJavaScriptCode, generatePythonCode } from './generateCodeSnippets'; @@ -70,46 +71,12 @@ const ExampleCodeContent: React.FC<{ code: string; language: string }> = ({ code, language }) => { - const [copied, setCopied] = useState(false); - - const handleCopy = async () => { - if (typeof navigator !== 'undefined' && navigator?.clipboard?.writeText) { - try { - await navigator.clipboard.writeText(code || ''); - setCopied(true); - setTimeout(() => setCopied(false), 2000); - } catch (error) { - console.error('Failed to copy code snippet', error); - } - } - }; - return (
- -
); }; diff --git a/packages/oc-docs/src/components/Docs/CodeSnippets/StyledWrapper.ts b/packages/oc-docs/src/components/Docs/CodeSnippets/StyledWrapper.ts index 19579a9..9801fb8 100644 --- a/packages/oc-docs/src/components/Docs/CodeSnippets/StyledWrapper.ts +++ b/packages/oc-docs/src/components/Docs/CodeSnippets/StyledWrapper.ts @@ -4,13 +4,13 @@ export const StyledWrapper = styled.div` .code-example-section { display: flex; flex-direction: column; - gap: 0.5rem; + gap: 0.375rem; } .code-example-card { border-radius: 8px; - border: 1px solid var(--border-color); overflow: hidden; + background-color: var(--code-bg); } .code-example-card .compact-code-view { @@ -34,23 +34,23 @@ export const StyledWrapper = styled.div` overflow-x: auto; } - /* Tab styling based on reference design */ .tab-header { padding-inline: 16px; - padding-top: 6px; - + padding-top: 8px; + background-color: #ebeef1; + .tab-button { padding: 6px 0px; border: none; border-bottom: solid 2px transparent; margin-right: 1.25rem; margin-left: 0; - color: var(--oc-tabs-color); + color: #687385; cursor: pointer; background: none; font-size: 0.75rem; font-weight: 500; - transition: color 0.2s ease, border-color 0.2s ease; + transition: color 0.15s ease, border-color 0.15s ease; &:focus, &:active, @@ -62,11 +62,11 @@ export const StyledWrapper = styled.div` } &:hover { - color: var(--oc-tabs-active-color); + color: #30313d; } &.active { - color: var(--oc-tabs-active-color) !important; + color: #30313d !important; border-bottom: solid 2px var(--primary-color) !important; } } @@ -85,57 +85,21 @@ export const StyledWrapper = styled.div` .code-example-code-wrapper .compact-code-view .code-content { padding: 32px 16px 16px; background-color: var(--code-bg); - border-top: 1px solid var(--border-color); + border-top: 1px solid #ebeef1; } .code-example-code-wrapper .compact-code-view pre { margin: 0; } - .code-copy-button { - position: absolute; - top: 12px; - right: 16px; - display: inline-flex; - align-items: center; - gap: 0.25rem; - padding: 0.35rem 0.5rem; - border-radius: 0.375rem; - font-size: 0.7rem; - font-weight: 500; - color: var(--text-secondary); - background-color: rgba(0, 0, 0, 0.04); - border: none; - cursor: pointer; - opacity: 0; - pointer-events: none; - transform: translateY(-4px); - transition: background-color 0.2s ease, color 0.2s ease, opacity 0.2s ease, transform 0.2s ease; - } - - .code-example-code-wrapper:hover .code-copy-button, - .code-copy-button:focus, - .code-copy-button:focus-visible, - .code-copy-button.copied { - opacity: 1; - pointer-events: auto; - transform: translateY(0); - } - - .code-copy-button:hover { - background-color: rgba(0, 0, 0, 0.08); - color: var(--text-primary); - } - - .code-copy-button.copied { - color: #15803d; - background-color: rgba(34, 197, 94, 0.15); - } - @media (max-width: 1100px) { .code-samples-container { position: static; } } -`; + .code-content-wrapper { + border-top-left-radius: 0; + border-top-right-radius: 0; + } +`; diff --git a/packages/oc-docs/src/components/Docs/Docs.tsx b/packages/oc-docs/src/components/Docs/Docs.tsx index d254c41..03a2146 100644 --- a/packages/oc-docs/src/components/Docs/Docs.tsx +++ b/packages/oc-docs/src/components/Docs/Docs.tsx @@ -5,7 +5,7 @@ import Sidebar from './Sidebar/Sidebar'; import Item from './Item/Item'; import FetchInBrunoButton from './Sidebar/FetchInBrunoButton'; import { getItemId, generateSafeId } from '../../utils/itemUtils'; -import { isFolder } from '../../utils/schemaHelpers'; +import { isFolder, getItemName } from '../../utils/schemaHelpers'; import { useAppSelector, useAppDispatch } from '../../store/hooks'; import { selectSelectedItemId, selectItem } from '../../store/slices/docs'; import { selectGitCollectionUrl } from '../../store/slices/app'; @@ -71,29 +71,32 @@ const Docs: React.FC = ({ }, [selectedItemId, filteredCollectionItems]); // Flatten all items recursively for rendering - const flattenItems = (items: any[], parentPath = ''): any[] => { + const breadcrumbMap = useRef>>(new Map()); + + const flattenItems = (items: any[], breadcrumbPath: Array<{ name: string; uuid: string }> = []): any[] => { const result: any[] = []; - + for (const item of items) { - const itemId = getItemId(item); - const itemPath = parentPath ? `${parentPath}/${itemId}` : itemId; - - // Add the item itself + const itemName = getItemName(item) || ''; + const itemUuid = (item as any).uuid || getItemId(item); + + breadcrumbMap.current.set(itemUuid, breadcrumbPath); + result.push(item); - - // If it's a folder, recursively add its children + if (isFolder(item)) { const folder = item as any; if (folder.items && folder.items.length > 0) { - result.push(...flattenItems(folder.items, itemPath)); + result.push(...flattenItems(folder.items, [...breadcrumbPath, { name: itemName, uuid: itemUuid }])); } } } - + return result; }; const allItems = useMemo(() => { + breadcrumbMap.current.clear(); const items = flattenItems(filteredCollectionItems); return items; }, [filteredCollectionItems]); @@ -105,7 +108,8 @@ const Docs: React.FC = ({ style={{ width: 'var(--sidebar-width)', transition: 'width 0.3s ease', - borderRight: '1px solid var(--border-color)' + borderRight: '1px solid var(--border-color)', + backgroundColor: 'var(--oc-sidebar-bg)' }} > @@ -114,15 +118,26 @@ const Docs: React.FC = ({
-
+
{docsCollection?.info?.name && (

{docsCollection.info.name}

@@ -140,12 +155,11 @@ const Docs: React.FC = ({ {/* Collection-level documentation/introduction */} {docsCollection?.docs && (
@@ -175,12 +189,39 @@ const Docs: React.FC = ({
{ + dispatch(selectItem(targetUuid)); + // Find the target item to get its safe ID for scrolling + const findTarget = (searchItems: any[]): string | null => { + for (const searchItem of searchItems) { + const searchUuid = (searchItem as any).uuid || getItemId(searchItem); + if (searchUuid === targetUuid) { + return generateSafeId(getItemId(searchItem)); + } + if (isFolder(searchItem) && searchItem.items) { + const found = findTarget(searchItem.items); + if (found) return found; + } + } + return null; + }; + const targetSafeId = findTarget(filteredCollectionItems); + if (targetSafeId) { + setTimeout(() => { + const element = document.getElementById(`section-${targetSafeId}`); + if (element) { + element.scrollIntoView({ behavior: 'smooth', block: 'start' }); + } + }, 100); + } + }} onTryClick={() => { // Select the item by UUID dispatch(selectItem(itemUuid)); diff --git a/packages/oc-docs/src/components/Docs/Item/Item.tsx b/packages/oc-docs/src/components/Docs/Item/Item.tsx index dfd5d94..9acd246 100644 --- a/packages/oc-docs/src/components/Docs/Item/Item.tsx +++ b/packages/oc-docs/src/components/Docs/Item/Item.tsx @@ -1,4 +1,4 @@ -import React, { memo } from 'react'; +import React, { memo, useState } from 'react'; import 'prismjs/components/prism-bash'; import 'prismjs/components/prism-http'; import 'prismjs/components/prism-graphql'; @@ -28,9 +28,9 @@ import { } from '../../../utils/schemaHelpers'; import { MinimalDataTable, - CompactCodeView, StatusBadge } from '../../../ui/MinimalComponents'; +import { Code } from '../../../ui/Code/Code'; import { CodeSnippets } from '../CodeSnippets/CodeSnippets'; import { StyledWrapper } from './StyledWrapper'; import { Scripts } from './Scripts/Scripts'; @@ -50,20 +50,47 @@ const methodColors: Record = { const Item = memo(({ item, parentPath = '', + breadcrumb = [], collection, toggleRunnerMode, - onTryClick + onTryClick, + onBreadcrumbClick }: { item: any; parentPath?: string; + breadcrumb?: Array<{ name: string; uuid: string }>; collection?: any; toggleRunnerMode?: () => void; onTryClick?: () => void; + onBreadcrumbClick?: (uuid: string) => void; }) => { const md = useMarkdownRenderer(); + const [bodyScriptsView, setBodyScriptsView] = useState<'body' | 'scripts'>('body'); const itemId = getItemId(item); const sectionId = generateSectionId(item, parentPath); + const renderBreadcrumb = () => { + if (breadcrumb.length === 0) return null; + return ( +
+ {breadcrumb.map((segment, i) => ( + + {i > 0 && /} + onBreadcrumbClick?.(segment.uuid)} + > + + + + {segment.name} + + + ))} +
+ ); + }; + if (isFolder(item)) { const folderItem = item as any; const folderName = getItemName(folderItem) || 'Untitled Folder'; @@ -78,14 +105,14 @@ const Item = memo(({ id={`section-${sectionId}`} >
+ {renderBreadcrumb()}
-
- +

+ - Folder -

-

{folderName}

+ {folderName} +
@@ -145,6 +172,7 @@ const Item = memo(({ id={`section-${sectionId}`} >
+ {renderBreadcrumb()}
@@ -158,7 +186,7 @@ const Item = memo(({
{scriptItem.script && ( - @@ -196,30 +224,33 @@ const Item = memo(({ id={`section-${sectionId}`} >
+ {renderBreadcrumb()}

{endpoint.name}

{endpoint.method} - {endpoint.url} - {(onTryClick || toggleRunnerMode) && ( - - )} +
+ {endpoint.url} + {(onTryClick || toggleRunnerMode) && ( + + )} +
@@ -256,49 +287,109 @@ const Item = memo(({ /> )} - {endpoint.body && typeof endpoint.body === 'object' && 'data' in endpoint.body && ( -
-

Body

- { - const bodyData = (endpoint.body as any).data; - const bodyType = (endpoint.body as any).type; - - // Handle different body types - if (bodyType === 'form-urlencoded' && Array.isArray(bodyData)) { - // Convert FormUrlEncodedEntry[] to string - return bodyData - .filter((entry: any) => entry.disabled !== true) - .map((entry: any) => `${encodeURIComponent(entry.name)}=${encodeURIComponent(entry.value)}`) - .join('&'); - } else if (bodyType === 'multipart-form' && Array.isArray(bodyData)) { - // Convert MultipartFormEntry[] to readable format - return bodyData - .filter((entry: any) => entry.disabled !== true) - .map((entry: any) => `${entry.name}: ${entry.value}`) - .join('\n'); - } else if (typeof bodyData === 'string') { - // Handle string data (json, text, xml, etc.) - return bodyData; - } else { - // Fallback: stringify objects - return JSON.stringify(bodyData, null, 2); - } - })()} - language={(() => { - const bodyType = (endpoint.body as any).type; - if (bodyType === 'form-urlencoded') return 'text'; - if (bodyType === 'multipart-form') return 'text'; - return bodyType || 'json'; - })()} - /> -
- )} + {(() => { + const hasBody = endpoint.body && typeof endpoint.body === 'object' && 'data' in endpoint.body; + const hasScripts = !!(endpoint.script?.preRequest || endpoint.script?.postResponse); - + if (!hasBody && !hasScripts) return null; + if (!hasBody && hasScripts) { + return ( + + ); + } + + if (hasBody && !hasScripts) { + return ( +
+

Body

+ { + const bodyData = (endpoint.body as any).data; + const bodyType = (endpoint.body as any).type; + if (bodyType === 'form-urlencoded' && Array.isArray(bodyData)) { + return bodyData + .filter((entry: any) => entry.disabled !== true) + .map((entry: any) => `${encodeURIComponent(entry.name)}=${encodeURIComponent(entry.value)}`) + .join('&'); + } else if (bodyType === 'multipart-form' && Array.isArray(bodyData)) { + return bodyData + .filter((entry: any) => entry.disabled !== true) + .map((entry: any) => `${entry.name}: ${entry.value}`) + .join('\n'); + } else if (typeof bodyData === 'string') { + return bodyData; + } else { + return JSON.stringify(bodyData, null, 2); + } + })()} + language={(() => { + const bodyType = (endpoint.body as any).type; + if (bodyType === 'form-urlencoded') return 'text'; + if (bodyType === 'multipart-form') return 'text'; + return bodyType || 'json'; + })()} + /> +
+ ); + } + + return ( +
+
+

setBodyScriptsView('body')} + > + Body +

+

setBodyScriptsView('scripts')} + > + Scripts +

+
+ {bodyScriptsView === 'body' ? ( + { + const bodyData = (endpoint.body as any).data; + const bodyType = (endpoint.body as any).type; + if (bodyType === 'form-urlencoded' && Array.isArray(bodyData)) { + return bodyData + .filter((entry: any) => entry.disabled !== true) + .map((entry: any) => `${encodeURIComponent(entry.name)}=${encodeURIComponent(entry.value)}`) + .join('&'); + } else if (bodyType === 'multipart-form' && Array.isArray(bodyData)) { + return bodyData + .filter((entry: any) => entry.disabled !== true) + .map((entry: any) => `${entry.name}: ${entry.value}`) + .join('\n'); + } else if (typeof bodyData === 'string') { + return bodyData; + } else { + return JSON.stringify(bodyData, null, 2); + } + })()} + language={(() => { + const bodyType = (endpoint.body as any).type; + if (bodyType === 'form-urlencoded') return 'text'; + if (bodyType === 'multipart-form') return 'text'; + return bodyType || 'json'; + })()} + /> + ) : ( + + )} +
+ ); + })()}
diff --git a/packages/oc-docs/src/components/Docs/Item/Scripts/Scripts.tsx b/packages/oc-docs/src/components/Docs/Item/Scripts/Scripts.tsx index 8f99c62..0868ae0 100644 --- a/packages/oc-docs/src/components/Docs/Item/Scripts/Scripts.tsx +++ b/packages/oc-docs/src/components/Docs/Item/Scripts/Scripts.tsx @@ -1,15 +1,18 @@ import React, { useState } from 'react'; -import { TabGroup, CompactCodeView } from '../../../../ui/MinimalComponents'; +import { TabGroup } from '../../../../ui/MinimalComponents'; +import { Code } from '../../../../ui/Code/Code'; import { StyledWrapper } from './StyledWrapper'; interface ScriptsProps { preRequest?: string | null; postResponse?: string | null; + hideTitle?: boolean; } export const Scripts: React.FC = ({ preRequest, - postResponse + postResponse, + hideTitle = false }) => { const tabs = [ ...(preRequest ? [{ id: 'pre', label: 'Pre-request', code: preRequest }] : []), @@ -25,7 +28,7 @@ export const Scripts: React.FC = ({ return (
-

Scripts

+ {!hideTitle &&

Scripts

}
({ id, label }))} @@ -62,8 +65,7 @@ const ScriptsCodeContent: React.FC<{ code: string }> = ({ code }) => { return (
- diff --git a/packages/oc-docs/src/components/Docs/Item/Scripts/StyledWrapper.ts b/packages/oc-docs/src/components/Docs/Item/Scripts/StyledWrapper.ts index 57fce6f..78d9539 100644 --- a/packages/oc-docs/src/components/Docs/Item/Scripts/StyledWrapper.ts +++ b/packages/oc-docs/src/components/Docs/Item/Scripts/StyledWrapper.ts @@ -4,19 +4,20 @@ export const StyledWrapper = styled.div` .scripts-section { display: flex; flex-direction: column; - gap: 0.75rem; + gap: 0.375rem; } .scripts-card { - border: 1px solid var(--border-color); border-radius: 8px; overflow: hidden; - background-color: var(--background-color); + background-color: var(--code-bg); + border: 1px solid #ebeef1; } .scripts-card .tab-header { padding-inline: 16px; - padding-top: 6px; + padding-top: 8px; + background-color: #ebeef1; } .scripts-card .tab-header .tab-button { @@ -25,11 +26,11 @@ export const StyledWrapper = styled.div` border-bottom: 2px solid transparent; margin-right: 1.25rem; background: none; - color: var(--oc-tabs-color); + color: #687385; cursor: pointer; font-size: 0.75rem; font-weight: 500; - transition: color 0.2s ease, border-color 0.2s ease; + transition: color 0.15s ease, border-color 0.15s ease; } .scripts-card .tab-header .tab-button:focus, @@ -42,17 +43,17 @@ export const StyledWrapper = styled.div` } .scripts-card .tab-header .tab-button:hover { - color: var(--oc-tabs-active-color); + color: #30313d; } .scripts-card .tab-header .tab-button.active { - color: var(--oc-tabs-active-color) !important; + color: #30313d !important; border-bottom-color: var(--primary-color) !important; } .scripts-card .tab-content { border-top: none; - background-color: var(--background-color); + background-color: var(--code-bg); } .scripts-code-wrapper { @@ -68,7 +69,7 @@ export const StyledWrapper = styled.div` .scripts-code-wrapper .compact-code-view .code-content { padding: 32px 16px 16px; background-color: var(--code-bg); - border-top: 1px solid var(--border-color); + border-top: 1px solid #ebeef1; } .scripts-copy-button { @@ -79,17 +80,17 @@ export const StyledWrapper = styled.div` align-items: center; gap: 0.25rem; padding: 0.35rem 0.5rem; - border-radius: 0.375rem; + border-radius: 4px; font-size: 0.7rem; font-weight: 500; - color: var(--text-secondary); - background-color: rgba(0, 0, 0, 0.04); + color: #687385; + background-color: transparent; border: none; cursor: pointer; opacity: 0; pointer-events: none; transform: translateY(-4px); - transition: background-color 0.2s ease, color 0.2s ease, opacity 0.2s ease, transform 0.2s ease; + transition: all 0.15s ease; } .scripts-code-wrapper:hover .scripts-copy-button, @@ -102,18 +103,16 @@ export const StyledWrapper = styled.div` } .scripts-copy-button:hover { - background-color: rgba(0, 0, 0, 0.08); - color: var(--text-primary); + background-color: rgba(0, 0, 0, 0.04); + color: #30313d; } .scripts-copy-button.copied { - color: #15803d; - background-color: rgba(34, 197, 94, 0.15); + color: #059669; + background-color: rgba(5, 150, 105, 0.08); } - .scripts-card .compact-code-view pre { margin: 0; } `; - diff --git a/packages/oc-docs/src/components/Docs/Item/StyledWrapper.ts b/packages/oc-docs/src/components/Docs/Item/StyledWrapper.ts index a338392..fa7bf43 100644 --- a/packages/oc-docs/src/components/Docs/Item/StyledWrapper.ts +++ b/packages/oc-docs/src/components/Docs/Item/StyledWrapper.ts @@ -3,10 +3,43 @@ import styled from '@emotion/styled'; export const StyledWrapper = styled.div` width: 100%; max-width: 80rem; - margin-right: 0; .item-header-minimal { - margin-bottom: 0.75rem; + margin-bottom: 1.25rem; + } + + .item-breadcrumb { + font-size: 0.75rem; + color: var(--text-tertiary); + margin-bottom: 0.25rem; + display: flex; + align-items: center; + flex-wrap: wrap; + } + + .breadcrumb-sep { + margin: 0 0.3rem; + opacity: 0.5; + } + + .breadcrumb-link { + display: inline-flex; + align-items: center; + gap: 0.2rem; + cursor: pointer; + transition: color 0.15s ease; + border-radius: 3px; + padding: 0.05rem 0.2rem; + } + + .breadcrumb-link:hover { + color: var(--text-secondary); + background-color: rgba(0, 0, 0, 0.04); + } + + .breadcrumb-icon { + flex-shrink: 0; + opacity: 0.6; } .item-title-section { @@ -20,20 +53,23 @@ export const StyledWrapper = styled.div` display: inline-flex; align-items: center; gap: 0.375rem; - padding: 0.25rem 0.625rem; - border-radius: 9999px; - font-size: 0.75rem; - font-weight: 500; + padding: 0.2rem 0.5rem; + border-radius: 4px; + font-size: 0.6875rem; + font-weight: 600; + letter-spacing: 0.04em; + text-transform: uppercase; + font-family: var(--font-mono); } .item-type-badge.folder { - background-color: #e0e7ff; - color: #3730a3; + background-color: rgba(99, 102, 241, 0.1); + color: #6366f1; } .item-type-badge.script { - background-color: #dcfce7; - color: #047857; + background-color: rgba(16, 185, 129, 0.1); + color: #10b981; } .item-title { @@ -41,187 +77,114 @@ export const StyledWrapper = styled.div` font-size: 1.25rem; font-weight: 600; color: var(--text-primary); + letter-spacing: -0.02em; + line-height: 1.3; + display: flex; + align-items: center; + gap: 0.375rem; + } + + .item-title-icon { + flex-shrink: 0; + color: var(--text-tertiary); } .item-subtitle { margin: 0; - font-size: 0.75rem; - color: var(--text-secondary); + font-size: 0.8125rem; + color: var(--text-tertiary); } + /* ============================================================ + DOCS / PROSE + ============================================================ */ + .item-docs { max-width: none; margin-bottom: 1.5rem; - font-size: 0.875rem; - color: var(--text-primary); - } - - .item-docs h1 { - margin: 0 0 0.75rem; - font-size: 1.5rem; - font-weight: 700; - color: var(--text-primary); - } - - .item-docs h2 { - margin: 1rem 0 0.5rem; - font-size: 1.25rem; - font-weight: 600; - color: var(--text-primary); - } - - .item-docs h3 { - margin: 0.75rem 0 0.5rem; - font-size: 1.1rem; - font-weight: 600; - color: var(--text-primary); - } - - .item-docs p { - margin: 0 0 0.75rem; - } - - .item-docs a { - color: var(--primary-color); - text-decoration: underline; - transition: opacity 0.2s ease; - } - - .item-docs a:hover { - opacity: 0.8; - } - - .item-docs code { - display: inline-block; - padding: 0.125rem 0.375rem; - border-radius: 0.25rem; - font-size: 0.875rem; - font-family: var(--font-mono); - background-color: var(--code-bg); - color: var(--code-text); - } - - .item-docs pre { - margin: 0 0 0.75rem; - padding: 0.75rem; - border-radius: 0.75rem; - overflow-x: auto; - background-color: var(--code-bg); - color: var(--code-text); - } - - .item-docs ul, - .item-docs ol { - margin: 0 0 0.75rem; - padding-left: 1rem; - } + font-size: 0.9375rem; + color: var(--text-secondary); + line-height: 1.7; + } + + .item-docs h1 { margin: 0 0 0.75rem; font-size: 1.375rem; font-weight: 600; color: var(--text-primary); letter-spacing: -0.02em; } + .item-docs h2 { margin: 1rem 0 0.5rem; font-size: 1.125rem; font-weight: 600; color: var(--text-primary); } + .item-docs h3 { margin: 0.75rem 0 0.375rem; font-size: 1rem; font-weight: 600; color: var(--text-primary); } + .item-docs p { margin: 0 0 0.75rem; } + .item-docs a { color: var(--prose-links); text-decoration: none; transition: color 0.15s ease; } + .item-docs a:hover { color: var(--prose-links-hover); text-decoration: underline; text-underline-offset: 3px; } + .item-docs code { display: inline-block; padding: 0.1rem 0.35rem; border-radius: 4px; font-size: 0.85em; font-family: var(--font-mono); background-color: var(--prose-code-bg); color: var(--prose-code-text); } + .item-docs pre { margin: 0 0 0.75rem; padding: 1rem 1.25rem; border-radius: 8px; overflow-x: auto; background-color: var(--code-bg); color: var(--code-text); } + .item-docs ul, .item-docs ol { margin: 0 0 0.75rem; padding-left: 1.25rem; } + .item-docs ul { list-style: disc inside; } + .item-docs ol { list-style: decimal inside; } + .item-docs li { margin: 0.2rem 0; } + .item-docs blockquote { margin: 0.75rem 0; padding: 0.625rem 1rem; border-left: 3px solid var(--prose-blockquote-border); color: var(--text-secondary); background-color: rgba(217, 119, 6, 0.04); border-radius: 0 6px 6px 0; } + + /* ============================================================ + CONTENT LAYOUT + ============================================================ */ + + .item-content-grid { display: flex; flex-direction: column; gap: 1rem; } + .item-content-main { display: flex; flex-direction: column; gap: 1.5rem; } + .request-details { display: flex; flex-direction: column; gap: 1rem; } + .request-body-section { display: flex; flex-direction: column; gap: 0.375rem; } - .item-docs ul { - list-style: disc inside; + @media (min-width: 1024px) { + .item-content-main { flex-direction: row; } + .request-details { flex: 4; min-width: 0; } + .code-snippets-wrapper { flex: 3; min-width: 0; } } - .item-docs ol { - list-style: decimal inside; - } + /* ============================================================ + ENDPOINT BADGES + ============================================================ */ - .item-docs li { - margin: 0.25rem 0; - } + .endpoint-badges { display: flex; align-items: stretch; flex-wrap: wrap; } - .item-docs blockquote { - margin: 1rem 0; - padding-left: 1rem; - border-left: 4px solid var(--border-color); - font-style: italic; - color: var(--text-secondary); - } + .badge-method { font-size: 0.6875rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; font-family: var(--font-sans); padding: 0.25rem 0.625rem; display: inline-flex; align-items: center; color: white !important; border-radius: 6px 0 0 6px; } - .item-content-grid { - display: flex; - flex-direction: column; - gap: 1rem; + .endpoint-url-container { + display: inline-flex; + align-items: stretch; + border-radius: 0 6px 6px 0; + border: 1px solid var(--border-color); + border-left: none; + background-color: white; + overflow: hidden; } - .item-content-main { - display: flex; - flex-direction: column; - gap: 1.5rem; - } + .badge-url { font-size: 0.8125rem; font-family: var(--font-mono); color: var(--text-secondary); font-weight: 400; padding: 0.25rem 0.625rem; display: inline-flex; align-items: center; } + .badge-try { display: inline-flex; align-items: center; gap: 0.25rem; padding: 0.25rem 0.625rem; margin-left: auto; font-size: 0.75rem; font-weight: 500; color: var(--primary-color); background-color: rgba(217, 119, 6, 0.06); border: none; border-left: 1px solid var(--border-color); cursor: pointer; transition: all 0.15s ease; } + .badge-try:hover { background-color: rgba(217, 119, 6, 0.12); } - .request-details { - display: flex; - flex-direction: column; - gap: 1rem; - } + /* ============================================================ + SECTION TITLE TABS (Body / Scripts switcher) + ============================================================ */ - .request-body-section { - display: flex; - flex-direction: column; - gap: 0.5rem; - } - - .endpoint-badges { + .section-title-tabs { display: flex; align-items: center; - gap: 0.5rem; - flex-wrap: wrap; + gap: 0.75rem; } - .badge-method { - display: inline-flex; - align-items: center; - padding: 0.25rem 0.625rem; - border-radius: 0.375rem; - font-size: 0.75rem; - font-weight: 700; - text-transform: uppercase; - color: white; - } - - .badge-url { - display: inline-flex; - align-items: center; - padding: 0.25rem 0.625rem; - border-radius: 0.375rem; - font-size: 0.75rem; - font-family: var(--font-mono); - background-color: var(--badge-bg); - color: #313131; - } - - .badge-try { - display: inline-flex; - align-items: center; - gap: 0.25rem; - padding: 0.25rem 0.625rem; - border-radius: 0.375rem; - font-size: 0.75rem; + .section-title-tab { + font-size: 0.8125rem; font-weight: 500; - color: #1d4ed8; - background-color: #dbeafe; - border: none; cursor: pointer; - transition: background-color 0.2s ease, color 0.2s ease; + color: var(--text-tertiary); + transition: color 0.15s ease; + margin: 0; + padding-bottom: 2px; + border-bottom: 1.5px dashed transparent; } - .badge-try:hover { - background-color: #bfdbfe; + .section-title-tab:hover { + color: var(--text-secondary); } - @media (min-width: 1024px) { - .item-content-main { - flex-direction: row; - } - - .request-details { - flex: 4; - min-width: 0; - } - - .code-snippets-wrapper { - flex: 3; - min-width: 0; - } + .section-title-tab.active { + color: var(--text-primary); + border-bottom-color: var(--text-tertiary); } `; - diff --git a/packages/oc-docs/src/components/Docs/Method/StyledWrapper.ts b/packages/oc-docs/src/components/Docs/Method/StyledWrapper.ts index 2acdbda..27f1053 100644 --- a/packages/oc-docs/src/components/Docs/Method/StyledWrapper.ts +++ b/packages/oc-docs/src/components/Docs/Method/StyledWrapper.ts @@ -5,41 +5,42 @@ export const StyledWrapper = styled.div` align-items: center; justify-content: center; padding: 0.1rem 0.4rem; - font-size: 10px; - font-weight: 600; - border-radius: 4px; + font-size: 9px; + font-weight: 700; + border-radius: 3px; text-transform: uppercase; font-family: var(--font-sans); - min-width: 42px; + min-width: 36px; margin-right: 8px; + letter-spacing: 0.05em; &.get { - background-color: #e6f0ff; - color: #0057b7; + background-color: rgba(37, 99, 235, 0.1); + color: #2563eb; } &.post { - background-color: #e6f9e6; - color: #00824d; + background-color: rgba(22, 163, 74, 0.1); + color: #16a34a; } &.put { - background-color: #fff0e6; - color: #b74600; + background-color: rgba(217, 119, 6, 0.1); + color: #d97706; } &.delete { - background-color: #ffe6e6; - color: #b70000; + background-color: rgba(220, 38, 38, 0.1); + color: #dc2626; } &.patch { - background-color: #f9e6f9; - color: #6b0082; + background-color: rgba(147, 51, 234, 0.1); + color: #9333ea; } &.options, &.head { - background-color: #f0f0f0; - color: #4a4a4a; + background-color: rgba(107, 114, 128, 0.1); + color: #6b7280; } -`; \ No newline at end of file +`; diff --git a/packages/oc-docs/src/components/Docs/Sidebar/Sidebar.tsx b/packages/oc-docs/src/components/Docs/Sidebar/Sidebar.tsx index be53f33..db664df 100644 --- a/packages/oc-docs/src/components/Docs/Sidebar/Sidebar.tsx +++ b/packages/oc-docs/src/components/Docs/Sidebar/Sidebar.tsx @@ -123,9 +123,15 @@ const Sidebar: React.FC = () => { return ( {/* Collection name at top */} -
+
-

+

{collection?.info?.name || 'API Collection'}

diff --git a/packages/oc-docs/src/components/Docs/Sidebar/StyledWrapper.ts b/packages/oc-docs/src/components/Docs/Sidebar/StyledWrapper.ts index 50efde7..88cbb09 100644 --- a/packages/oc-docs/src/components/Docs/Sidebar/StyledWrapper.ts +++ b/packages/oc-docs/src/components/Docs/Sidebar/StyledWrapper.ts @@ -4,15 +4,14 @@ export const SidebarContainer = styled.div` height: 100%; display: flex; flex-direction: column; - + &.compact { min-width: var(--sidebar-width-compact); max-width: var(--sidebar-width-compact); } - /* Sidebar scrollbar styling */ & ::-webkit-scrollbar { - width: 6px; + width: 0; } & ::-webkit-scrollbar-track { @@ -20,11 +19,13 @@ export const SidebarContainer = styled.div` } & ::-webkit-scrollbar-thumb { - background-color: rgba(0, 0, 0, 0.2); - border-radius: 10px; + background-color: transparent; + } + + &:hover ::-webkit-scrollbar-thumb { + background-color: rgba(0, 0, 0, 0.12); } - /* Sidebar Logo styling */ & .logo { padding: 0 8px 12px 8px; border-bottom: 1px solid rgba(0, 0, 0, 0.06); @@ -37,7 +38,7 @@ export const SidebarContainer = styled.div` `; export const SidebarItems = styled.div` - padding: 0; + padding: 0 6px; overflow-y: auto; flex-grow: 1; @@ -48,16 +49,16 @@ export const SidebarItems = styled.div` export const SidebarItem = styled.div` cursor: pointer; - transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1); - border-radius: 0; + transition: all 0.12s ease; + border-radius: 6px; margin-bottom: 0; position: relative; overflow: hidden; - padding: 6px 12px; + padding: 5px 10px; display: flex; align-items: center; -// font-size: 13px; - color: #212121; + color: var(--text-secondary); + font-size: 13px; ${SidebarContainer}.compact & { padding: 4px 8px; @@ -67,36 +68,41 @@ export const SidebarItem = styled.div` &:hover, &.hovered { background-color: rgba(0, 0, 0, 0.04); - color: #212121; + color: var(--text-primary); } &.active { - background-color: rgba(0, 0, 0, 0.08); - color: #212121; + background-color: rgba(217, 119, 6, 0.08); + color: var(--text-primary); font-weight: 500; } &.active:hover { - background-color: rgba(0, 0, 0, 0.1); + background-color: rgba(217, 119, 6, 0.1); + } + + &.folder { + color: var(--text-primary); + font-weight: 500; + font-size: 12.5px; } &.folder:hover { background-color: transparent; - color: #212121; } & .method-badge { - font-size: 10px; - padding: 3px 6px; - border-radius: 4px; - font-weight: 600; - min-width: 42px; + font-size: 9px; + padding: 2px 5px; + border-radius: 3px; + font-weight: 700; + min-width: 36px; text-align: center; - letter-spacing: 0.03em; - transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1); + letter-spacing: 0.05em; + transition: all 0.12s ease; text-transform: uppercase; margin-right: 8px; - opacity: 0.85; + font-family: var(--font-mono); } ${SidebarContainer}.compact & .method-badge { @@ -105,11 +111,10 @@ export const SidebarItem = styled.div` font-size: 10px; } - /* Fix for click events */ & * { pointer-events: none; } - + & svg { pointer-events: all; } @@ -119,4 +124,3 @@ export const SidebarItem = styled.div` height: 14px; } `; - diff --git a/packages/oc-docs/src/standalone.ts b/packages/oc-docs/src/standalone.ts index 02b4574..0070936 100644 --- a/packages/oc-docs/src/standalone.ts +++ b/packages/oc-docs/src/standalone.ts @@ -41,9 +41,9 @@ export class OpenCollectionRenderer { const links = [ { rel: 'preconnect', href: 'https://fonts.googleapis.com' }, { rel: 'preconnect', href: 'https://fonts.gstatic.com', crossOrigin: 'anonymous' }, - { + { rel: 'stylesheet', - href: 'https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap' + href: 'https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=JetBrains+Mono:wght@400;500;600;700&display=swap' } ]; diff --git a/packages/oc-docs/src/styles/index.css b/packages/oc-docs/src/styles/index.css index 89be27f..514b78d 100644 --- a/packages/oc-docs/src/styles/index.css +++ b/packages/oc-docs/src/styles/index.css @@ -6,103 +6,105 @@ --secondary-color: #0ea5e9; /* Radius */ - --oc-radius: 3px; + --oc-radius: 6px; /* Tabs */ - --oc-tabs-color: rgb(155, 155, 155); - --oc-tabs-active-color: rgb(50, 46, 44) !important; - + --oc-tabs-color: #8c8c8c; + --oc-tabs-active-color: #1a1a1a !important; + /* Background colors */ - --oc-sidebar-bg: rgb(250, 250, 250); + --oc-sidebar-bg: #fafafa; --background-light: #ffffff; - + --content-bg: #ffffff; + /* Text colors */ - --oc-text-primary: rgb(52, 52, 52); - --text-light: rgb(52, 52, 52); - + --oc-text-primary: #1a1a1a; + --text-light: #1a1a1a; + /* Border colors */ - --border-light: #e8e8e8; - - /* Code colors */ - --code-bg-light: #ffffff; - --code-text-light: #515151; - + --border-light: #e5e5e5; + + /* Code colors - light theme inspired by Stripe */ + --code-bg-light: #f6f8fa; + --code-text-light: #30313d; + /* Sidebar colors */ - --sidebar-bg-light: #FCFCFC; - --sidebar-color-light: rgb(52, 52, 52); - + --sidebar-bg-light: #fafafa; + --sidebar-color-light: #1a1a1a; + /* Table colors */ --table-header-bg-light: #fafafa; --table-row-odd-bg-light: #ffffff; - --table-row-even-bg-light: #ffffff; - + --table-row-even-bg-light: #fafafa; + /* Status colors */ - --success-color: #22c55e; - --warning-color: #eab308; - --info-color: #3b82f6; - --error-color: #ef4444; - + --success-color: #16a34a; + --warning-color: #ca8a04; + --info-color: #2563eb; + --error-color: #dc2626; + /* Method colors */ - --method-get-bg: #61affe; - --method-post-bg: #49cc90; - --method-put-bg: #fca130; - --method-delete-bg: #f93e3e; - --method-patch-bg: #50e3c2; - --method-options-bg: #a47fdc; - + --method-get-bg: #2563eb; + --method-post-bg: #16a34a; + --method-put-bg: #d97706; + --method-delete-bg: #dc2626; + --method-patch-bg: #9333ea; + --method-options-bg: #6b7280; + /* Input and badge colors */ --input-bg-light: #fafafa; --badge-bg-light: #f5f5f5; - --badge-text-light: #4b5563; - + --badge-text-light: #3d3d3d; + /* Apple colors for method badges */ - --apple-blue-100: #e6f1ff; - --apple-blue-900: #0050d4; - --apple-green-100: #e6f7ed; - --apple-green-900: #056e3c; - --apple-orange-100: #fef4e6; - --apple-orange-900: #804c00; - --apple-red-100: #fee6e6; - --apple-red-900: #b01212; - --apple-purple-100: #f3e6ff; - --apple-purple-900: #6b0099; - --apple-gray-100: #f0f0f0; - --apple-gray-900: #333333; - + --apple-blue-100: #eff6ff; + --apple-blue-900: #1e40af; + --apple-green-100: #f0fdf4; + --apple-green-900: #166534; + --apple-orange-100: #fffbeb; + --apple-orange-900: #92400e; + --apple-red-100: #fef2f2; + --apple-red-900: #991b1b; + --apple-purple-100: #faf5ff; + --apple-purple-900: #581c87; + --apple-gray-100: #f3f4f6; + --apple-gray-900: #1f2937; + /* Prose colors */ - --prose-links: #0071e3; - --prose-links-hover: #0058b0; - --prose-blockquote-border: rgba(0, 0, 0, 0.1); - --prose-hr-color: rgba(0, 0, 0, 0.1); - + --prose-links: #d97706; + --prose-links-hover: #b45309; + --prose-blockquote-border: #d97706; + --prose-hr-color: #e5e5e5; + /* Layout dimensions */ --sidebar-width: 260px; --header-height: 60px; --item-padding-compact: 4px; --item-height-compact: 28px; - + /* Z-index layers */ --z-header: 10; --z-sidebar: 5; --z-overlay: 50; - + /* Shadows */ - --shadow-sm: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.08); - --shadow-md: 0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -1px rgba(0,0,0,0.06); - + --shadow-sm: 0 1px 2px rgba(0,0,0,0.05); + --shadow-md: 0 4px 6px -1px rgba(0,0,0,0.07), 0 2px 4px -1px rgba(0,0,0,0.04); + /* Fonts */ - --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + --font-mono: "JetBrains Mono", "SF Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; --font-sans: "Inter", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; - + /* Theme variables */ --background-color: var(--background-light); --text-primary: var(--text-light); - --text-secondary: #6e6e6e; + --text-secondary: #6b6b6b; + --text-tertiary: #a1a1a1; --border-color: var(--border-light); --code-bg: var(--code-bg-light); --code-text: var(--code-text-light); - --prose-code-bg: var(--code-bg); - --prose-code-text: var(--code-text); + --prose-code-bg: #f5f5f5; + --prose-code-text: #d97706; --table-header-bg: var(--table-header-bg-light); --table-row-odd-bg: var(--table-row-odd-bg-light); --table-row-even-bg: var(--table-row-even-bg-light); @@ -111,12 +113,29 @@ --badge-text: var(--badge-text-light); } +/* ================================================================ + BASE + ================================================================ */ + +html, body { + font-kerning: normal; + text-rendering: optimizeLegibility; + letter-spacing: -0.011em; + margin: 0; + padding: 0; + font-size: 1rem; + overflow-x: hidden; + font-family: var(--font-sans) !important; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + /* Main playground container */ .oc-playground { width: 100%; height: 100vh !important; overflow: hidden; - font-family: Inter, -apple-system, BlinkMacSystemFont, "San Francisco", "Segoe UI", Roboto, "Helvetica Neue", sans-serif; + font-family: var(--font-sans); color: var(--text-primary); background-color: var(--background-color); position: relative; @@ -126,30 +145,30 @@ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; font-size: 14px; - line-height: 1.5; + line-height: 1.6; + letter-spacing: -0.011em; +} + +.oc-playground * { + box-sizing: border-box; } -/* Header styling */ +/* ================================================================ + HEADER + ================================================================ */ + .glass-header { height: var(--header-height); - backdrop-filter: blur(8px); - -webkit-backdrop-filter: blur(8px); - background-color: rgba(255, 255, 255, 0.8); + backdrop-filter: saturate(180%) blur(20px); + -webkit-backdrop-filter: saturate(180%) blur(20px); + background-color: rgba(255, 255, 255, 0.9); border-bottom: 1px solid var(--border-color); } -html, body { - font-kerning: none; - text-rendering: optimizeSpeed; - letter-spacing: normal; - margin: 0; - padding: 0; - font-size: 1rem; - overflow-x: hidden; - font-family: Inter, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif !important; -} +/* ================================================================ + DESKTOP LAYOUT + ================================================================ */ -/* Desktop Layout */ @media (min-width: 1024px) { .oc-playground { display: flex; @@ -169,7 +188,7 @@ html, body { overflow-y: auto; background-color: var(--oc-sidebar-bg); color: var(--sidebar-color-light); - padding: 12px 0 0 0; + padding: 14px 0 0 0; } .playground-content { @@ -177,6 +196,7 @@ html, body { overflow-y: auto; scroll-behavior: smooth; padding: 0; + background-color: var(--content-bg); } .playground-runner { @@ -196,25 +216,37 @@ html, body { transition: width 0.3s ease; } - /* All Endpoints View Styles */ + /* All Endpoints View */ .all-endpoints-view { - max-width: 1200px; + max-width: 1100px; margin: 0 auto; - padding: 1.5rem; + padding: 2.5rem 3rem; } + /* Endpoint sections - NO cards, clean flowing layout with dividers */ .endpoint-section { scroll-margin-top: 2rem; - transition: all 0.2s ease; + padding: 2.5rem 0; + border-bottom: 1px solid var(--border-color); + } + + .endpoint-section:first-child { + padding-top: 0; + } + + .endpoint-section:last-child { + border-bottom: none; } .endpoint-section.selected { position: relative; } - } -/* Mobile Layout */ +/* ================================================================ + MOBILE LAYOUT + ================================================================ */ + @media (max-width: 1023px) { .oc-playground { flex-direction: column; @@ -253,88 +285,195 @@ html, body { } } -/* Method badge styling */ +/* ================================================================ + METHOD BADGES + ================================================================ */ + .method-badge { display: inline-flex; align-items: center; justify-content: center; - padding: 0.2rem 0.4rem; - font-size: 0.65rem; - font-weight: 600; + padding: 0.15rem 0.45rem; + font-size: 0.625rem; + font-weight: 700; border-radius: 4px; text-transform: uppercase; - letter-spacing: 0.03em; - font-family: var(--font-sans); - min-width: 42px; + letter-spacing: 0.05em; + font-family: var(--font-mono); + min-width: 40px; } .method-badge.get { - background-color: rgba(0, 112, 243, 0.09); - color: #0057b7; + background-color: rgba(37, 99, 235, 0.1); + color: #2563eb; } .method-badge.post { - background-color: rgba(0, 155, 0, 0.09); - color: #00824d; + background-color: rgba(22, 163, 74, 0.1); + color: #16a34a; } .method-badge.put { - background-color: rgba(243, 112, 0, 0.09); - color: #b74600; + background-color: rgba(217, 119, 6, 0.1); + color: #d97706; } .method-badge.delete { - background-color: rgba(243, 0, 0, 0.09); - color: #b70000; + background-color: rgba(220, 38, 38, 0.1); + color: #dc2626; } .method-badge.patch { - background-color: rgba(155, 0, 155, 0.09); - color: #6b0082; + background-color: rgba(147, 51, 234, 0.1); + color: #9333ea; } -.method-badge.options, +.method-badge.options, .method-badge.head { - background-color: rgba(100, 100, 100, 0.09); - color: #4a4a4a; + background-color: rgba(107, 114, 128, 0.1); + color: #6b7280; } -/* Code block styling */ +/* ================================================================ + CODE BLOCKS - DARK THEME + ================================================================ */ + .code-block { - border-radius: 6px; + border-radius: 8px; background: var(--code-bg); position: relative; transition: all 0.2s ease; overflow: hidden; color: var(--code-text); min-height: 80px; - border: 1px solid var(--border-color); + border: none; } .code-block pre { margin: 0; - padding: 0.75rem; + padding: 1rem 1.25rem; overflow: auto; font-family: var(--font-mono); - font-size: 12px; - line-height: 1.5; + font-size: 13px; + line-height: 1.65; scrollbar-width: thin; } -/* Copy button styling */ -.copy-button { - opacity: 0.7; - transition: all 0.2s ease; - backdrop-filter: blur(8px); - -webkit-backdrop-filter: blur(8px); - color: var(--text-primary); +/* ================================================================ + CODE SNIPPET OVERRIDES — right-side code snippets & example cards + Light theme inspired by Stripe + ================================================================ */ + +.code-snippets-wrapper .compact-code-view, +.code-example-card .compact-code-view { + background-color: var(--code-bg); + border: 1px solid #ebeef1; } -.copy-button:hover { - opacity: 1; - transform: scale(1.05); +.code-snippets-wrapper .code-header, +.code-example-card .code-header { + border-bottom: 1px solid #ebeef1; + background-color: #ebeef1; +} + +.code-snippets-wrapper .code-tab, +.code-example-card .code-tab { + color: #687385; +} +.code-snippets-wrapper .code-tab:hover, +.code-example-card .code-tab:hover { + color: #30313d; + background-color: rgba(0, 0, 0, 0.04); +} +.code-snippets-wrapper .code-tab.active, +.code-example-card .code-tab.active { + color: #30313d; + background-color: white; +} + +.code-snippets-wrapper .copy-button, +.code-example-card .copy-button { + color: #687385; +} +.code-snippets-wrapper .copy-button:hover, +.code-example-card .copy-button:hover { + color: #30313d; + background-color: rgba(0, 0, 0, 0.04); +} + +.code-snippets-wrapper .code-content, +.code-example-card .code-content { + background-color: var(--code-bg); + color: var(--code-text); +} + +.code-snippets-wrapper .code-content pre, +.code-snippets-wrapper .code-content code, +.code-example-card .code-content pre, +.code-example-card .code-content code { + color: var(--code-text); +} + +/* ================================================================ + SYNTAX HIGHLIGHTING - LIGHT THEME (default for body/scripts) + ================================================================ */ + +.token.comment, +.token.prolog, +.token.doctype, +.token.cdata { + color: #6a737d; + font-style: italic; } +.token.punctuation { color: #24292e; } +.token.property { color: #005cc5; } + +.token.tag, +.token.boolean, +.token.number, +.token.constant, +.token.symbol { color: #005cc5; } + +.token.selector, +.token.attr-name, +.token.string, +.token.char, +.token.builtin { color: #032f62; } + +.token.operator, +.token.entity, +.token.url, +.language-css .token.string, +.style .token.string { color: #d73a49; } + +.token.variable { color: #e36209; } + +.token.atrule, +.token.attr-value, +.token.keyword { color: #d73a49; } + +.token.function, +.token.class-name { color: #6f42c1; } + +.token.regex, +.token.important { color: #e36209; } + +.token.parameter { color: #24292e; } + +.token.important, +.token.bold { font-weight: bold; } + +.token.italic { font-style: italic; } +.token.entity { cursor: help; } +.token.deleted { color: #d73a49; } +.token.inserted { color: #22863a; } + + +/* ================================================================ + TABLES + ================================================================ */ + /* API table styling */ .api-table { width: 100%; @@ -346,22 +485,23 @@ html, body { padding: 0.5rem 0.75rem; background-color: var(--table-header-bg); border-bottom: 1px solid var(--border-color); - color: var(--text-primary); - font-size: 0.8rem; + color: var(--text-secondary); + font-size: 0.6875rem; font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.06em; } .api-table td { padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--border-color); - font-size: 0.8rem; + font-size: 0.8125rem; } .api-table tr:last-child td { border-bottom: none; } -/* Table row styling */ tr.themed-row:nth-child(odd) { background-color: var(--table-row-odd-bg) !important; } @@ -370,214 +510,185 @@ tr.themed-row:nth-child(even) { background-color: var(--table-row-even-bg) !important; } -/* Apple-style rounded corners */ -.rounded-apple { - border-radius: 10px; -} - -/* Apple-inspired shadows */ -.shadow-apple-sm { - box-shadow: 0 2px 6px rgba(0, 0, 0, 0.04), 0 0.5px 2px rgba(0, 0, 0, 0.06); -} - -.shadow-apple-md { - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05), 0 1px 3px rgba(0, 0, 0, 0.08); +/* Minimal Table Styles */ +.minimal-table { + display: flex; + flex-direction: column; + gap: 0.375rem; } -/* Apple-style scrollbars */ -.oc-playground ::-webkit-scrollbar { - width: 8px; - height: 8px; +.table-wrapper { + @apply border rounded-lg overflow-hidden; + border-color: var(--border-color); } -.oc-playground ::-webkit-scrollbar-track { - background: transparent; +.minimal-table table { + @apply w-full text-sm; } -.oc-playground ::-webkit-scrollbar-thumb { - background-color: #d1d5db; - border-radius: 20px; - border: 2px solid transparent; - background-clip: content-box; +.minimal-table thead { + background-color: var(--table-header-bg); } -.oc-playground ::-webkit-scrollbar-thumb:hover { - background-color: #5a5a5a; +.minimal-table th { + @apply px-3 py-1.5 text-left font-semibold uppercase; + color: var(--text-tertiary); + font-size: 0.625rem; + letter-spacing: 0.08em; } -/* Skeleton loading effect */ -.skeleton { - background: linear-gradient( - 90deg, - rgba(0, 0, 0, 0.06) 25%, - rgba(0, 0, 0, 0.12) 37%, - rgba(0, 0, 0, 0.06) 63% - ); - background-size: 400% 100%; - animation: skeleton 1.4s ease infinite; +.minimal-table td { + @apply px-3 py-2 border-t; + border-color: var(--border-color); + font-size: 0.8125rem; } -@keyframes skeleton { - 0% { background-position: 100% 50%; } - 100% { background-position: 0 50%; } -} +.minimal-table tbody tr { + @apply transition-colors; -/* Hover lift effect */ -.hover-lift { - transition: transform 0.2s ease, box-shadow 0.2s ease; + &:hover { + background-color: var(--table-row-even-bg); + } } -.hover-lift:hover { - transform: translateY(-2px); - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05), 0 1px 3px rgba(0, 0, 0, 0.1); +.table-value { + @apply font-mono; + font-size: 0.75rem; + color: var(--text-primary); } -/* Ensure consistent box-sizing */ -.oc-playground * { - box-sizing: border-box; +.section-title { + @apply text-xs font-semibold mb-2 uppercase; + color: var(--text-tertiary); + font-size: 0.625rem; + letter-spacing: 0.1em; } -/* Animation for tab indicator */ -@keyframes fadeIn { - from { opacity: 0; } - to { opacity: 1; } -} +/* ================================================================ + SCROLLBARS + ================================================================ */ -.fade-in { - animation: fadeIn 0.3s ease-in-out; +.oc-playground ::-webkit-scrollbar { + width: 6px; + height: 6px; } -/* Smooth Software Syntax Highlighting - Light Theme */ -.token.comment, -.token.prolog, -.token.doctype, -.token.cdata { - color: #6d82a3; /* Cool gray */ - font-style: italic; +.oc-playground ::-webkit-scrollbar-track { + background: transparent; } -.token.punctuation { - color: #4f678a; /* Slate blue */ +.oc-playground ::-webkit-scrollbar-thumb { + background-color: rgba(0, 0, 0, 0.1); + border-radius: 20px; } -.token.property { - color: #2d66bb; /* Bold azure - for JSON properties */ +.oc-playground ::-webkit-scrollbar-thumb:hover { + background-color: rgba(0, 0, 0, 0.2); } -.token.tag, -.token.boolean, -.token.number, -.token.constant, -.token.symbol { - color: #1a9b7d; /* Bold jade */ -} +/* ================================================================ + BUTTONS + ================================================================ */ -.token.selector, -.token.attr-name, -.token.string, -.token.char, -.token.builtin { - color: #c55e1e; /* Bold bronze */ +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + font-weight: 500; + padding: 0.5rem 1rem; + border-radius: 6px; + transition: all 0.15s ease; + cursor: pointer; + font-size: 0.8125rem; } -.token.operator, -.token.entity, -.token.url, -.language-css .token.string, -.style .token.string { - color: #4f678a; /* Slate blue */ +.btn-primary { + background-color: var(--primary-color); + color: white; } -.token.variable { - color: #1a8468; /* Bold teal */ +.btn-primary:hover { + background-color: #b45309; } -.token.atrule, -.token.attr-value, -.token.keyword { - color: #d93d4f; /* Bold ruby */ +.btn-secondary { + background-color: var(--badge-bg); + color: var(--text-primary); } -.token.function, -.token.class-name { - color: #2d66bb; /* Bold azure */ +.btn-secondary:hover { + background-color: #ebebeb; } -.token.regex, -.token.important { - color: #c55e1e; /* Bold bronze */ -} +/* ================================================================ + STATUS BADGES + ================================================================ */ -.token.parameter { - color: #6844c0; /* Bold plum */ +.status-badge { + @apply inline-flex items-center px-1.5 py-0.5 rounded text-xs font-semibold; + transition: all 0.15s ease; + font-size: 0.6875rem; } -.token.important, -.token.bold { - font-weight: bold; -} +/* ================================================================ + ICON BUTTONS + ================================================================ */ -.token.italic { - font-style: italic; -} +.icon-button { + @apply p-2 rounded transition-colors; + color: var(--text-secondary); -.token.entity { - cursor: help; + &:hover { + background-color: var(--input-bg); + color: var(--text-primary); + } } -.token.deleted { - color: #d93d4f; /* Bold ruby */ -} +.icon-button-small { @apply p-1; } +.icon-button-large { @apply p-3; } -.token.inserted { - color: #39bd7d; /* Bold sage */ -} +/* ================================================================ + TABS + ================================================================ */ -/* Focus styles for accessibility */ -:focus-visible { - outline: 2px solid var(--primary-color); - outline-offset: 2px; +.tab-group { + @apply space-y-0; } -/* Button styling */ -.btn { - display: inline-flex; - align-items: center; - justify-content: center; - font-weight: 500; - padding: 0.5rem 1rem; - border-radius: 0.5rem; - transition: all 0.2s ease; - cursor: pointer; +.tab-header { + @apply flex gap-0; } -.btn-primary { - background-color: var(--primary-color); - color: white; -} +.tab-button { + @apply px-3 py-2 text-xs font-medium transition-all border-b-2 border-transparent; + color: var(--text-tertiary); -.btn-primary:hover { - background-color: #005bbf; + &:hover { + color: var(--text-primary); + } } -.btn-secondary { - background-color: #f3f4f6; - color: #1f2937; +.tab-button.active { + color: var(--text-primary); + border-color: var(--primary-color); + font-weight: 600; } -.btn-secondary:hover { - background-color: #e5e7eb; +.tab-content { + background-color: var(--background-color); } +/* ================================================================ + MARKDOWN / PROSE + ================================================================ */ -/* Markdown documentation styles */ .markdown-documentation { color: var(--text-primary) !important; max-width: none !important; - line-height: 1.6 !important; + line-height: 1.7 !important; + font-size: 0.9375rem !important; } -/* Specific heading styles */ .markdown-documentation h1, .markdown-documentation h2, .markdown-documentation h3, @@ -585,87 +696,94 @@ tr.themed-row:nth-child(even) { .markdown-documentation h5, .markdown-documentation h6 { color: var(--text-primary) !important; - margin-top: 1.25rem !important; - margin-bottom: 0.75rem !important; + margin-top: 1.5rem !important; + margin-bottom: 0.625rem !important; font-weight: 600 !important; + letter-spacing: -0.02em !important; + line-height: 1.3 !important; } .markdown-documentation h1.heading-1 { font-size: 1.5rem !important; - line-height: 2rem !important; font-weight: 700 !important; margin-top: 0 !important; margin-bottom: 0.75rem !important; - color: var(--text-primary) !important; + letter-spacing: -0.025em !important; } .markdown-documentation h2.heading-2 { font-size: 1.25rem !important; - line-height: 1.75rem !important; font-weight: 600 !important; - margin-top: 1.25rem !important; + margin-top: 1.5rem !important; margin-bottom: 0.5rem !important; } .markdown-documentation h3.heading-3 { - font-size: 1.1rem !important; + font-size: 1.0625rem !important; font-weight: 600 !important; - margin-top: 1rem !important; + margin-top: 1.25rem !important; margin-bottom: 0.5rem !important; } .markdown-documentation h4.heading-4 { - font-size: 1rem !important; + font-size: 0.9375rem !important; font-weight: 600 !important; - margin-top: 0.75rem !important; + margin-top: 1rem !important; margin-bottom: 0.4rem !important; } +.markdown-documentation p { + margin-bottom: 0.75rem !important; +} + .markdown-documentation a { text-decoration: none !important; - transition: color 0.15s ease-in-out !important; + transition: all 0.15s ease !important; color: var(--prose-links) !important; + font-weight: 500 !important; } .markdown-documentation a:hover { text-decoration: underline !important; color: var(--prose-links-hover) !important; + text-underline-offset: 3px !important; } .markdown-documentation code { font-family: var(--font-mono) !important; - padding: 0.15em 0.35em !important; - border-radius: 3px !important; - font-size: 0.9em !important; + padding: 0.125em 0.375em !important; + border-radius: 4px !important; + font-size: 0.85em !important; background-color: var(--prose-code-bg) !important; color: var(--prose-code-text) !important; } .markdown-documentation pre { - padding: 0.75em !important; - background-color: var(--prose-code-bg) !important; + padding: 1rem 1.25rem !important; + background-color: var(--code-bg) !important; border-radius: 8px !important; overflow-x: auto !important; - margin: 0.75em 0 !important; - color: var(--prose-code-text) !important; + margin: 1rem 0 !important; + color: var(--code-text) !important; + border: none !important; } .markdown-documentation pre code { background-color: transparent !important; padding: 0 !important; border-radius: 0 !important; - font-size: 0.9em !important; + font-size: 0.85em !important; color: inherit !important; } .markdown-documentation img { margin: 1em 0 !important; - border-radius: 6px !important; + border-radius: 8px !important; } .markdown-documentation ul, .markdown-documentation ol { margin-left: 1.25em !important; - margin-top: 0.75em !important; + margin-top: 0.5em !important; margin-bottom: 0.75em !important; } @@ -675,16 +793,21 @@ tr.themed-row:nth-child(even) { } .markdown-documentation blockquote { - border-left-width: 0.25em !important; + border-left-width: 3px !important; border-left-color: var(--prose-blockquote-border) !important; - padding-left: 0.75em !important; - font-style: italic !important; + padding: 0.625rem 1rem !important; + font-style: normal !important; margin: 0.75em 0 !important; + color: var(--text-secondary) !important; + background-color: rgba(217, 119, 6, 0.04) !important; + border-radius: 0 6px 6px 0 !important; } .markdown-documentation hr { margin: 1.5em 0 !important; - border-color: var(--prose-hr-color) !important; + border: none !important; + height: 1px !important; + background-color: var(--border-color) !important; } .markdown-documentation table { @@ -692,6 +815,9 @@ tr.themed-row:nth-child(even) { border-collapse: collapse !important; margin: 1em 0 !important; font-size: 0.875em !important; + border: 1px solid var(--border-color) !important; + border-radius: 6px !important; + overflow: hidden !important; } .markdown-documentation th, @@ -704,7 +830,7 @@ tr.themed-row:nth-child(even) { .markdown-documentation th { background-color: var(--table-header-bg) !important; font-weight: 600 !important; - color: var(--text-primary) !important; + color: var(--text-secondary) !important; } .markdown-documentation tr:nth-child(even) { @@ -725,120 +851,25 @@ tr.themed-row:nth-child(even) { color: var(--text-secondary) !important; } -/* Console animations */ -.console-container { - transition: opacity 0.2s ease-in-out, transform 0.2s ease-in-out; - will-change: opacity, transform; - min-height: 300px; - display: flex; - flex-direction: column; - height: 100%; -} - -.console-container.fade-in { - animation: fadeIn 0.3s ease forwards; -} - -.console-container.fade-out { - opacity: 0; - transition: opacity 0.2s ease; -} - -/* Make console sticky in appropriate places */ -.playground-console .sticky { - position: sticky; - top: 0; - max-height: 100vh; - overflow-y: auto; - z-index: 10; -} - -/* Flash effect for code updates */ -@keyframes codeFlash { - 0% { - background-color: var(--primary-color); - opacity: 0.2; - } - 100% { - background-color: transparent; - opacity: 1; - } -} - -.code-updated { - animation: codeFlash 0.5s ease-out; -} - -/* Loading indicator for console */ -.console-view.is-loading .code-block::after { - content: ''; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: rgba(0,0,0,0.1); - display: flex; - justify-content: center; - align-items: center; - z-index: 10; -} - -/* Endpoint info styling */ -.endpoint-info { - padding: 8px 0; - border-top: 1px solid var(--border-color); - margin-top: 12px; -} - -/* Section highlight animation */ -@keyframes sectionHighlight { - 0% { - background-color: rgba(59, 130, 246, 0.08); - box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.08); - } - 50% { - background-color: rgba(59, 130, 246, 0.12); - box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.12); - } - 100% { - background-color: transparent; - box-shadow: 0 0 0 0 transparent; - } -} - -.section-highlight { - animation: sectionHighlight 2s ease-out; - border-radius: 8px; -} - -/* Hide scrollbar but keep functionality */ -.hide-scrollbar::-webkit-scrollbar { - width: 0; - height: 0; - display: none; -} - -.hide-scrollbar { - -ms-overflow-style: none; /* IE and Edge */ - scrollbar-width: none; /* Firefox */ -} +/* ================================================================ + ENDPOINT STYLES + ================================================================ */ .endpoint-content { max-width: 100%; } -/* Original styles */ .endpoint-header { margin-bottom: 1rem; - border-bottom: 1px solid var(--border-color, #e2e8f0); + border-bottom: 1px solid var(--border-color); padding-bottom: 0.75rem; } .endpoint-name { - font-size: 1.5rem; + font-size: 1.375rem; font-weight: 600; color: var(--text-primary); + letter-spacing: -0.02em; } .endpoint-method-url { @@ -849,16 +880,16 @@ tr.themed-row:nth-child(even) { } .endpoint-url { - font-family: monospace; - background: var(--code-bg); + font-family: var(--font-mono); + background: var(--prose-code-bg); border-radius: 4px; - padding: 0.3rem 0.4rem; + padding: 0.2rem 0.4rem; margin-left: 0.25rem; overflow-x: auto; word-break: break-all; max-width: 100%; - color: var(--code-text); - font-size: 0.85rem; + color: var(--text-primary); + font-size: 0.8125rem; } .endpoint-description { @@ -869,8 +900,8 @@ tr.themed-row:nth-child(even) { .endpoint-grid { display: grid; grid-template-columns: 1fr 37%; - gap: 1rem; - margin-top: 0.75rem; + gap: 1.5rem; + margin-top: 1rem; width: 100%; max-width: 100%; } @@ -887,7 +918,7 @@ tr.themed-row:nth-child(even) { } .code-tab { - transition: all 0.2s ease; + transition: all 0.15s ease; } .code-tab:hover { @@ -901,215 +932,136 @@ tr.themed-row:nth-child(even) { } .param-name, .param-value { - font-family: monospace; + font-family: var(--font-mono); word-break: break-all; + font-size: 0.8125rem; } .param-name { font-weight: 600; } -.section-title { - @apply text-xs font-semibold mb-2 uppercase tracking-wide; - color: var(--text-secondary); -} - -/* Minimal Table Styles */ -.minimal-table { - display: flex; - flex-direction: column; - gap: 0.5rem; -} - -.table-wrapper { - @apply border rounded-lg overflow-hidden; - border-color: var(--border-color); -} - -.minimal-table table { - @apply w-full text-sm; -} - -.minimal-table thead { - background-color: var(--table-header-bg); -} - -.minimal-table th { - @apply px-3 py-1.5 text-left font-medium text-xs uppercase tracking-wider; - color: var(--text-secondary); -} - -.minimal-table td { - @apply px-3 py-2 border-t; - border-color: var(--border-color); -} - -.minimal-table tbody tr { - @apply transition-colors; - - &:hover { - background-color: var(--table-row-odd-bg); - opacity: 0.8; - } -} - -.table-value { - @apply font-mono text-xs; - color: var(--text-primary); -} - -/* Compact Code View */ -.compact-code-view { - @apply overflow-hidden; - background-color: var(--background-color); - border: 1px solid var(--border-color); - border-radius: 8px; -} - -.code-header { - @apply flex items-center justify-between px-3 py-1.5 border-b; - border-color: var(--border-color); - background-color: var(--background-color); -} - -.code-tabs { - @apply flex gap-1; -} - -.code-tab { - @apply px-2 py-1 text-xs font-medium transition-colors rounded; - color: var(--text-secondary); - - &:hover { - color: var(--text-primary); - background-color: rgba(0, 0, 0, 0.03); - } +.endpoint-info { + padding: 8px 0; + border-top: 1px solid var(--border-color); + margin-top: 12px; } -.code-tab.active { - color: var(--primary-color); - background-color: rgba(0, 112, 243, 0.1); -} +/* ================================================================ + ANIMATIONS + ================================================================ */ -.copy-button { - @apply flex items-center gap-1 px-2 py-1 text-xs transition-colors rounded; - color: var(--text-secondary); - - &:hover { - color: var(--text-primary); - background-color: rgba(0, 0, 0, 0.03); - } +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } } -.code-content { - @apply p-3 overflow-x-auto; - background-color: var(--code-bg); - color: var(--code-text); +.fade-in { + animation: fadeIn 0.3s ease-in-out; } -/* Scrollbar styles - hidden by default, visible on hover */ -.code-content::-webkit-scrollbar { - width: 8px; - height: 8px; +@keyframes skeleton { + 0% { background-position: 100% 50%; } + 100% { background-position: 0 50%; } } -.code-content::-webkit-scrollbar-track { - background: transparent; +.skeleton { + background: linear-gradient( + 90deg, + rgba(0, 0, 0, 0.06) 25%, + rgba(0, 0, 0, 0.1) 37%, + rgba(0, 0, 0, 0.06) 63% + ); + background-size: 400% 100%; + animation: skeleton 1.4s ease infinite; } -.code-content::-webkit-scrollbar-thumb { - background-color: transparent; - border-radius: 4px; - transition: background-color 0.2s ease; +@keyframes sectionHighlight { + 0% { background-color: rgba(217, 119, 6, 0.04); } + 100% { background-color: transparent; } } -.code-content:hover::-webkit-scrollbar-thumb { - background-color: #d1d5db; +.section-highlight { + animation: sectionHighlight 2s ease-out; } -.code-content::-webkit-scrollbar-thumb:hover { - background-color: #9ca3af; +@keyframes codeFlash { + 0% { background-color: var(--primary-color); opacity: 0.2; } + 100% { background-color: transparent; opacity: 1; } } -/* Firefox scrollbar */ -.code-content { - scrollbar-width: thin; - scrollbar-color: transparent transparent; +.code-updated { + animation: codeFlash 0.5s ease-out; } -.code-content:hover { - scrollbar-color: #d1d5db transparent; -} +/* ================================================================ + HOVER EFFECTS + ================================================================ */ -.code-content pre { - @apply m-0 text-xs leading-relaxed; - color: var(--code-text); +.hover-lift { + transition: transform 0.2s ease, box-shadow 0.2s ease; } -.code-content code { - @apply font-mono; - color: var(--code-text); +.hover-lift:hover { + transform: translateY(-2px); + box-shadow: var(--shadow-md); } -/* Status Badge */ -.status-badge { - @apply inline-flex items-center px-1.5 py-0.5 rounded text-xs font-semibold; - transition: all 0.2s ease; -} +/* ================================================================ + UTILITY + ================================================================ */ -.status-badge:hover { - transform: translateY(-1px); - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); -} +.rounded-apple { border-radius: 10px; } +.shadow-apple-sm { box-shadow: var(--shadow-sm); } +.shadow-apple-md { box-shadow: var(--shadow-md); } -/* Icon Button */ -.icon-button { - @apply p-2 rounded transition-colors; - color: var(--text-secondary); - - &:hover { - background-color: var(--input-bg); - color: var(--text-primary); - } +:focus-visible { + outline: 2px solid var(--primary-color); + outline-offset: 2px; } -.icon-button-small { - @apply p-1; -} +.hide-scrollbar::-webkit-scrollbar { width: 0; height: 0; display: none; } +.hide-scrollbar { -ms-overflow-style: none; scrollbar-width: none; } -.icon-button-large { - @apply p-3; -} +/* ================================================================ + CONSOLE + ================================================================ */ -/* Tab Group */ -.tab-group { - @apply space-y-0; +.console-container { + transition: opacity 0.2s ease-in-out, transform 0.2s ease-in-out; + will-change: opacity, transform; + min-height: 300px; + display: flex; + flex-direction: column; + height: 100%; } -.tab-header { - @apply flex gap-0; -} +.console-container.fade-in { animation: fadeIn 0.3s ease forwards; } +.console-container.fade-out { opacity: 0; transition: opacity 0.2s ease; } -.tab-button { - @apply px-3 py-2 text-xs font-medium transition-colors border-b-2 border-transparent; - color: var(--text-secondary); - - &:hover { - color: var(--text-primary); - background-color: rgba(0, 0, 0, 0.02); - } +.playground-console .sticky { + position: sticky; + top: 0; + max-height: 100vh; + overflow-y: auto; + z-index: 10; } -.tab-button.active { - color: var(--primary-color); - border-color: var(--primary-color); +.console-view.is-loading .code-block::after { + content: ''; + position: absolute; + top: 0; left: 0; right: 0; bottom: 0; + background: rgba(0,0,0,0.1); + display: flex; + justify-content: center; + align-items: center; + z-index: 10; } -.tab-content { - background-color: var(--background-color); -} +/* ================================================================ + FOLDER ITEM CARDS + ================================================================ */ -/* Folder Items Grid */ .folder-items-section { @apply mt-6 space-y-3; } @@ -1119,12 +1071,13 @@ tr.themed-row:nth-child(even) { } .folder-item-card { - @apply relative p-3 border border-gray-200 rounded-lg hover:border-blue-500 transition-all cursor-pointer; + @apply relative p-3 border rounded-lg transition-all cursor-pointer; + border-color: var(--border-color); } .folder-item-card:hover { - @apply shadow-sm; - transform: translateY(-1px); + border-color: var(--primary-color); + background-color: rgba(217, 119, 6, 0.02); } .folder-item-card:hover .item-card-arrow { @@ -1156,4 +1109,3 @@ tr.themed-row:nth-child(even) { transform: translateY(-50%); opacity: 0; } - diff --git a/packages/oc-docs/src/ui/Code/Code.tsx b/packages/oc-docs/src/ui/Code/Code.tsx new file mode 100644 index 0000000..76550b2 --- /dev/null +++ b/packages/oc-docs/src/ui/Code/Code.tsx @@ -0,0 +1,62 @@ +import React, { useEffect, useRef, useState } from 'react'; +import { StyledWrapper } from './StyledWrapper'; + +import Prism from 'prismjs'; +import 'prismjs/components/prism-javascript'; +import 'prismjs/components/prism-bash'; +import 'prismjs/components/prism-python'; +import 'prismjs/components/prism-json'; +import 'prismjs/components/prism-xml-doc'; + +interface CodeProps { + code?: string; + language?: string; +} + +export const Code: React.FC = ({ + code, + language = 'text' +}) => { + const [copied, setCopied] = useState(false); + const codeRef = useRef(null); + + useEffect(() => { + if (codeRef.current) { + Prism.highlightAllUnder(codeRef.current); + } + }, [code, language]); + + const handleCopy = () => { + if (code) { + navigator.clipboard.writeText(code); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + } + }; + + return ( + +
+ +
+
+            
+              {code || ''}
+            
+          
+
+
+
+ ); +}; \ No newline at end of file diff --git a/packages/oc-docs/src/ui/Code/StyledWrapper.ts b/packages/oc-docs/src/ui/Code/StyledWrapper.ts new file mode 100644 index 0000000..bcc7c75 --- /dev/null +++ b/packages/oc-docs/src/ui/Code/StyledWrapper.ts @@ -0,0 +1,72 @@ +import styled from '@emotion/styled'; + +export const StyledWrapper = styled.div` + background-color: var(--code-bg); + border: 1px solid #ebeef1; + border-radius: 8px; + + .code-copy-floating { + position: absolute; + top: 8px; + right: 8px; + z-index: 1; + display: inline-flex; + align-items: center; + justify-content: center; + padding: 0.3rem; + border-radius: 4px; + border: none; + color: #687385; + background-color: rgba(0, 0, 0, 0.04); + cursor: pointer; + opacity: 0; + transition: all 0.15s ease; + } + + &:hover .code-copy-floating { + opacity: 1; + } + + .code-copy-floating:hover { + color: #30313d; + background-color: rgba(0, 0, 0, 0.08); + } + + .code-content { + background-color: var(--code-bg); + color: var(--text-primary); + } + + .code-content::-webkit-scrollbar { + width: 6px; + height: 6px; + } + + .code-content::-webkit-scrollbar-track { + background: transparent; + } + + .code-content::-webkit-scrollbar-thumb { + background-color: rgba(0, 0, 0, 0.1); + border-radius: 4px; + } + + .code-content:hover::-webkit-scrollbar-thumb { + background-color: rgba(0, 0, 0, 0.2); + } + + .code-content::-webkit-scrollbar-thumb:hover { + background-color: rgba(0, 0, 0, 0.3); + } + + .code-content pre { + font-size: 13px; + color: var(--text-primary); + line-height: 1.65; + } + + .code-content code { + color: var(--text-primary); + font-size: 13px; + } +`; \ No newline at end of file diff --git a/packages/oc-docs/src/ui/MinimalComponents.tsx b/packages/oc-docs/src/ui/MinimalComponents.tsx index 4eba336..2335d8a 100644 --- a/packages/oc-docs/src/ui/MinimalComponents.tsx +++ b/packages/oc-docs/src/ui/MinimalComponents.tsx @@ -1,10 +1,4 @@ -import React, { useState, useEffect, useRef } from 'react'; -import Prism from 'prismjs'; -import 'prismjs/components/prism-javascript'; -import 'prismjs/components/prism-bash'; -import 'prismjs/components/prism-python'; -import 'prismjs/components/prism-json'; -import 'prismjs/components/prism-xml-doc'; +import React, { useState } from 'react'; interface Column { key: string; @@ -61,93 +55,6 @@ export const MinimalDataTable: React.FC = ({ ); }; -interface CompactCodeViewProps { - code?: string; - language?: string; - title?: string; - tabs?: Array<{ id: string; label: string; content: string }>; - copyButton?: boolean; -} - -export const CompactCodeView: React.FC = ({ - code, - language = 'text', - title, - tabs, - copyButton = true -}) => { - const [activeTab, setActiveTab] = useState(tabs?.[0]?.id || ''); - const [copied, setCopied] = useState(false); - const codeRef = useRef(null); - - useEffect(() => { - if (codeRef.current) { - Prism.highlightAllUnder(codeRef.current); - } - }, [activeTab, code, language]); - - const handleCopy = () => { - const textToCopy = tabs ? tabs.find(t => t.id === activeTab)?.content : code; - if (textToCopy) { - navigator.clipboard.writeText(textToCopy); - setCopied(true); - setTimeout(() => setCopied(false), 2000); - } - }; - - const displayCode = tabs ? tabs.find(t => t.id === activeTab)?.content : code; - - return ( -
- {(title || tabs) && ( -
- {title && !tabs &&

{title}

} - {tabs && ( -
- {tabs.map(tab => ( - - ))} -
- )} - {copyButton && ( - - )} -
- )} -
-
-          
-            {displayCode || ''}
-          
-        
-
-
- ); -}; - interface StatusBadgeProps { status: 'active' | 'inactive' | 'warning' | 'error'; text?: string;