Skip to content

Commit e59076a

Browse files
authored
Improve OpenAPI schemas block ungrouped style (#3092)
1 parent 653920d commit e59076a

21 files changed

+478
-327
lines changed

.changeset/strange-chicken-provide.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@gitbook/react-openapi": patch
3+
"gitbook": patch
4+
---
5+
6+
Improve OpenAPI schemas block ungrouped style. Classnames have changed, please refer to this PR to update GBX.

packages/gitbook/src/app/middleware/(site)/(content)/[[...pathname]]/PageClientLayout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { useScrollPage } from '@/components/hooks';
1111
export function PageClientLayout(props: { withSections?: boolean }) {
1212
// We use this hook in the page layout to ensure the elements for the blocks
1313
// are rendered before we scroll to a hash or to the top of the page
14-
useScrollPage({ scrollMarginTop: props.withSections ? 50 : undefined });
14+
useScrollPage({ scrollMarginTop: props.withSections ? 48 : undefined });
1515

1616
useStripFallbackQueryParam();
1717
return null;

packages/gitbook/src/components/DocumentView/Heading.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,15 @@ export function Heading(props: BlockProps<DocumentBlockHeading>) {
2020
return (
2121
<Tag
2222
id={id}
23-
className={tcls(textStyle.textSize, 'heading', 'group', 'relative', 'grid', style)}
23+
className={tcls(
24+
textStyle.textSize,
25+
'heading',
26+
'group',
27+
'relative',
28+
'grid',
29+
'scroll-m-12',
30+
style
31+
)}
2432
>
2533
<div
2634
className={tcls(

packages/gitbook/src/components/DocumentView/OpenAPI/OpenAPIOperation.tsx

Lines changed: 2 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
1-
import type { JSONDocument } from '@gitbook/api';
2-
import { Icon } from '@gitbook/icons';
31
import { OpenAPIOperation as BaseOpenAPIOperation } from '@gitbook/react-openapi';
42

53
import { resolveOpenAPIOperationBlock } from '@/lib/openapi/resolveOpenAPIOperationBlock';
64
import { tcls } from '@/lib/tailwind';
75

86
import type { BlockProps } from '../Block';
9-
import { PlainCodeBlock } from '../CodeBlock';
10-
import { DocumentView } from '../DocumentView';
11-
import { Heading } from '../Heading';
127

138
import './scalar.css';
149
import './style.css';
1510
import type { AnyOpenAPIOperationsBlock } from '@/lib/openapi/types';
11+
import { getOpenAPIContext } from './context';
1612

1713
/**
1814
* Render an openapi block or an openapi-operation block.
@@ -55,56 +51,7 @@ async function OpenAPIOperationBody(props: BlockProps<AnyOpenAPIOperationsBlock>
5551
return (
5652
<BaseOpenAPIOperation
5753
data={data}
58-
context={{
59-
specUrl,
60-
icons: {
61-
chevronDown: <Icon icon="chevron-down" />,
62-
chevronRight: <Icon icon="chevron-right" />,
63-
plus: <Icon icon="plus" />,
64-
},
65-
renderCodeBlock: (codeProps) => <PlainCodeBlock {...codeProps} />,
66-
renderDocument: (documentProps) => (
67-
<DocumentView
68-
document={documentProps.document as JSONDocument}
69-
context={props.context}
70-
style="space-y-6"
71-
blockStyle="max-w-full"
72-
/>
73-
),
74-
renderHeading: (headingProps) => (
75-
<Heading
76-
document={props.document}
77-
ancestorBlocks={props.ancestorBlocks}
78-
isEstimatedOffscreen={props.isEstimatedOffscreen}
79-
context={props.context}
80-
style={tcls([
81-
headingProps.deprecated ? 'line-through' : undefined,
82-
headingProps.deprecated || !!headingProps.stability
83-
? '[&>div]:mt-0'
84-
: undefined,
85-
])}
86-
block={{
87-
object: 'block',
88-
key: `${block.key}-heading`,
89-
meta: block.meta,
90-
data: {},
91-
type: 'heading-2',
92-
nodes: [
93-
{
94-
key: `${block.key}-heading-text`,
95-
object: 'text',
96-
leaves: [
97-
{ text: headingProps.title, object: 'leaf', marks: [] },
98-
],
99-
},
100-
],
101-
}}
102-
/>
103-
),
104-
defaultInteractiveOpened: context.mode === 'print',
105-
id: block.meta?.id,
106-
blockKey: block.key,
107-
}}
54+
context={getOpenAPIContext({ props, specUrl })}
10855
className="openapi-block"
10956
/>
11057
);

packages/gitbook/src/components/DocumentView/OpenAPI/OpenAPISchemas.tsx

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { resolveOpenAPISchemasBlock } from '@/lib/openapi/resolveOpenAPISchemasBlock';
22
import { tcls } from '@/lib/tailwind';
3-
import { Icon } from '@gitbook/icons';
43
import { OpenAPISchemas as BaseOpenAPISchemas } from '@gitbook/react-openapi';
54

65
import type { BlockProps } from '../Block';
76

87
import './scalar.css';
98
import './style.css';
109
import type { OpenAPISchemasBlock } from '@/lib/openapi/types';
10+
import { getOpenAPIContext } from './context';
1111

1212
/**
1313
* Render an openapi-schemas block.
@@ -49,19 +49,9 @@ async function OpenAPISchemasBody(props: BlockProps<OpenAPISchemasBlock>) {
4949

5050
return (
5151
<BaseOpenAPISchemas
52-
data={data}
52+
schemas={data.schemas}
5353
grouped={block.data.grouped}
54-
context={{
55-
specUrl,
56-
icons: {
57-
chevronDown: <Icon icon="chevron-down" />,
58-
chevronRight: <Icon icon="chevron-right" />,
59-
plus: <Icon icon="plus" />,
60-
},
61-
defaultInteractiveOpened: context.mode === 'print',
62-
id: block.meta?.id,
63-
blockKey: block.key,
64-
}}
54+
context={getOpenAPIContext({ props, specUrl })}
6555
className="openapi-block"
6656
/>
6757
);
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import type { JSONDocument } from '@gitbook/api';
2+
import { Icon } from '@gitbook/icons';
3+
import type { OpenAPIContext } from '@gitbook/react-openapi';
4+
5+
import { tcls } from '@/lib/tailwind';
6+
7+
import type { BlockProps } from '../Block';
8+
import { PlainCodeBlock } from '../CodeBlock';
9+
import { DocumentView } from '../DocumentView';
10+
import { Heading } from '../Heading';
11+
12+
import './scalar.css';
13+
import './style.css';
14+
import type { AnyOpenAPIOperationsBlock, OpenAPISchemasBlock } from '@/lib/openapi/types';
15+
16+
/**
17+
* Get the OpenAPI context to render a block.
18+
*/
19+
export function getOpenAPIContext(args: {
20+
props: BlockProps<AnyOpenAPIOperationsBlock | OpenAPISchemasBlock>;
21+
specUrl: string;
22+
}): OpenAPIContext {
23+
const { props, specUrl } = args;
24+
const { block } = props;
25+
return {
26+
specUrl,
27+
icons: {
28+
chevronDown: <Icon icon="chevron-down" />,
29+
chevronRight: <Icon icon="chevron-right" />,
30+
plus: <Icon icon="plus" />,
31+
},
32+
renderCodeBlock: (codeProps) => <PlainCodeBlock {...codeProps} />,
33+
renderDocument: (documentProps) => (
34+
<DocumentView
35+
document={documentProps.document as JSONDocument}
36+
context={props.context}
37+
style="space-y-6"
38+
blockStyle="max-w-full"
39+
/>
40+
),
41+
renderHeading: (headingProps) => (
42+
<Heading
43+
document={props.document}
44+
ancestorBlocks={props.ancestorBlocks}
45+
isEstimatedOffscreen={props.isEstimatedOffscreen}
46+
context={props.context}
47+
style={tcls([
48+
headingProps.deprecated ? 'line-through' : undefined,
49+
headingProps.deprecated || !!headingProps.stability
50+
? '[&>div]:mt-0'
51+
: undefined,
52+
])}
53+
block={{
54+
object: 'block',
55+
key: `${block.key}-heading`,
56+
meta: block.meta,
57+
data: {},
58+
type: 'heading-2',
59+
nodes: [
60+
{
61+
key: `${block.key}-heading-text`,
62+
object: 'text',
63+
leaves: [{ text: headingProps.title, object: 'leaf', marks: [] }],
64+
},
65+
],
66+
}}
67+
/>
68+
),
69+
defaultInteractiveOpened: props.context.mode === 'print',
70+
id: block.meta?.id,
71+
blockKey: block.key,
72+
};
73+
}

packages/gitbook/src/components/DocumentView/OpenAPI/style.css

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/* Layout Components */
2-
.openapi-operation {
2+
.openapi-operation,
3+
.openapi-schemas {
34
@apply flex-1 flex flex-col gap-8 mb-14 min-w-0;
45
}
56

@@ -17,7 +18,7 @@
1718
}
1819

1920
.openapi-summary {
20-
@apply flex flex-col items-start justify-start gap-3;
21+
@apply flex flex-col items-start justify-start gap-3 scroll-m-12;
2122
}
2223

2324
.openapi-summary-tags {
@@ -483,12 +484,30 @@
483484
@apply flex flex-row items-center py-2 px-3 justify-end border-t border-tint-subtle;
484485
}
485486

486-
/* Response Example */
487-
.openapi-response-example {
487+
/* Panel */
488+
.openapi-panel {
488489
@apply border rounded bg-tint border-tint-subtle;
489490
}
490491

491-
.openapi-response-example-empty {
492+
.openapi-panel-heading {
493+
@apply font-medium px-4 py-2 text-xs uppercase;
494+
}
495+
496+
.openapi-panel-body {
497+
@apply theme-gradient:bg-tint-12/1 relative;
498+
@apply before:w-full before:h-px before:absolute before:bg-tint-6 before:-top-px before:z-10;
499+
}
500+
501+
.openapi-panel-footer {
502+
@apply px-3 py-2 pt-2.5 border-t border-tint-subtle text-[0.813rem] text-tint;
503+
}
504+
505+
.openapi-panel-footer .openapi-markdown {
506+
@apply text-[0.813rem] text-tint;
507+
}
508+
509+
/* Example */
510+
.openapi-example-empty {
492511
@apply relative text-tint bg-tint min-h-20 flex flex-col justify-center items-center;
493512
}
494513

@@ -559,15 +578,6 @@
559578

560579
.openapi-tabs-panel {
561580
@apply flex-1 text-sm relative focus-visible:outline-none;
562-
@apply before:w-full before:h-px before:absolute before:bg-tint-6 before:-top-px before:z-10;
563-
}
564-
565-
.openapi-tabs-footer {
566-
@apply px-3 py-2 pt-2.5 border-t border-tint-subtle text-[0.813rem] text-tint;
567-
}
568-
569-
.openapi-tabs-footer .openapi-markdown {
570-
@apply text-[0.813rem] text-tint;
571581
}
572582

573583
/* Disclosure group */

packages/gitbook/src/components/SitePage/PageClientLayout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { useScrollPage } from '@/components/hooks';
1111
export function PageClientLayout(props: { withSections?: boolean }) {
1212
// We use this hook in the page layout to ensure the elements for the blocks
1313
// are rendered before we scroll to a hash or to the top of the page
14-
useScrollPage({ scrollMarginTop: props.withSections ? 50 : undefined });
14+
useScrollPage({ scrollMarginTop: props.withSections ? 48 : undefined });
1515

1616
useStripFallbackQueryParam();
1717
return null;

packages/gitbook/src/lib/document-sections.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { GitBookAnyContext } from '@v2/lib/context';
33

44
import { getNodeText } from './document';
55
import { resolveOpenAPIOperationBlock } from './openapi/resolveOpenAPIOperationBlock';
6+
import { resolveOpenAPISchemasBlock } from './openapi/resolveOpenAPISchemasBlock';
67

78
export interface DocumentSection {
89
id: string;
@@ -52,6 +53,26 @@ export async function getDocumentSections(
5253
});
5354
}
5455
}
56+
57+
if (
58+
block.type === 'openapi-schemas' &&
59+
!block.data.grouped &&
60+
block.meta?.id &&
61+
block.data.schemas.length === 1
62+
) {
63+
const { data } = await resolveOpenAPISchemasBlock({
64+
block,
65+
context,
66+
});
67+
const schema = data?.schemas[0];
68+
if (schema) {
69+
sections.push({
70+
id: block.meta.id,
71+
title: `The ${schema.name} object`,
72+
depth: 1,
73+
});
74+
}
75+
}
5576
}
5677

5778
return sections;

packages/gitbook/src/lib/openapi/resolveOpenAPISchemasBlock.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
import { OpenAPIParseError } from '@gitbook/openapi-parser';
2-
import { type OpenAPISchemasData, resolveOpenAPISchemas } from '@gitbook/react-openapi';
1+
import { OpenAPIParseError, type OpenAPISchema } from '@gitbook/openapi-parser';
2+
import { resolveOpenAPISchemas } from '@gitbook/react-openapi';
33
import { fetchOpenAPIFilesystem } from './fetch';
44
import type {
55
OpenAPISchemasBlock,
66
ResolveOpenAPIBlockArgs,
77
ResolveOpenAPIBlockResult,
88
} from './types';
99

10-
type ResolveOpenAPISchemasBlockResult = ResolveOpenAPIBlockResult<OpenAPISchemasData>;
10+
type ResolveOpenAPISchemasBlockResult = ResolveOpenAPIBlockResult<{
11+
schemas: OpenAPISchema[];
12+
}>;
1113

1214
const weakmap = new WeakMap<OpenAPISchemasBlock, Promise<ResolveOpenAPISchemasBlockResult>>();
1315

packages/react-openapi/src/OpenAPICodeSample.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { StaticSection } from './StaticSection';
99
import { type CodeSampleGenerator, codeSampleGenerators } from './code-samples';
1010
import { generateMediaTypeExamples, generateSchemaExample } from './generateSchemaExample';
1111
import { stringifyOpenAPI } from './stringifyOpenAPI';
12-
import type { OpenAPIContextProps, OpenAPIOperationData } from './types';
12+
import type { OpenAPIContext, OpenAPIOperationData } from './types';
1313
import { getDefaultServerURL } from './util/server';
1414
import { checkIsReference, createStateKey } from './utils';
1515

@@ -21,7 +21,7 @@ const CUSTOM_CODE_SAMPLES_KEYS = ['x-custom-examples', 'x-code-samples', 'x-code
2121
*/
2222
export function OpenAPICodeSample(props: {
2323
data: OpenAPIOperationData;
24-
context: OpenAPIContextProps;
24+
context: OpenAPIContext;
2525
}) {
2626
const { data } = props;
2727

@@ -58,7 +58,7 @@ export function OpenAPICodeSample(props: {
5858
*/
5959
function generateCodeSamples(props: {
6060
data: OpenAPIOperationData;
61-
context: OpenAPIContextProps;
61+
context: OpenAPIContext;
6262
}) {
6363
const { data, context } = props;
6464

@@ -189,7 +189,7 @@ export interface MediaTypeRenderer {
189189
function OpenAPICodeSampleFooter(props: {
190190
data: OpenAPIOperationData;
191191
renderers: MediaTypeRenderer[];
192-
context: OpenAPIContextProps;
192+
context: OpenAPIContext;
193193
}) {
194194
const { data, context, renderers } = props;
195195
const { method, path } = data;
@@ -227,7 +227,7 @@ function OpenAPICodeSampleFooter(props: {
227227
*/
228228
function getCustomCodeSamples(props: {
229229
data: OpenAPIOperationData;
230-
context: OpenAPIContextProps;
230+
context: OpenAPIContext;
231231
}) {
232232
const { data, context } = props;
233233

0 commit comments

Comments
 (0)