1
- import { useState , useEffect } from 'react'
1
+ import React , { useState , useEffect } from 'react'
2
+ import cx from 'classnames'
2
3
import { useRouter } from 'next/router'
3
4
import dynamic from 'next/dynamic'
4
5
5
6
import { DefaultLayout } from 'components/DefaultLayout'
6
- import { ArticleTitle } from 'components/article/ArticleTitle'
7
7
import { useMainContext } from 'components/context/MainContext'
8
8
import { MarkdownContent } from 'components/ui/MarkdownContent'
9
9
import { Lead } from 'components/ui/Lead'
10
- import { ArticleGridLayout } from 'components/article/ArticleGridLayout'
11
10
import { MiniTocItem } from 'components/context/ArticleContext'
12
11
import { RestCategoryOperationsT } from './types'
13
12
import { RestOperation } from './RestOperation'
14
- import { MiniTocs } from 'components/ui/MiniTocs'
13
+ import { ChevronDownIcon , ChevronUpIcon , SearchIcon } from '@primer/octicons-react'
14
+ import { useTranslation } from 'components/hooks/useTranslation'
15
+ import { ActionList } from '@primer/react'
15
16
16
17
const ClientSideHighlightJS = dynamic ( ( ) => import ( 'components/article/ClientSideHighlightJS' ) , {
17
18
ssr : false ,
@@ -37,9 +38,11 @@ export const RestReferencePage = ({
37
38
restOperations,
38
39
miniTocItems,
39
40
} : StructuredContentT ) => {
41
+ const { t } = useTranslation ( 'pages' )
40
42
const { asPath } = useRouter ( )
41
43
const { page } = useMainContext ( )
42
44
const subcategories = Object . keys ( restOperations )
45
+ const [ collapsed , setCollapsed ] = useState ( { } as Record < number , boolean > )
43
46
44
47
// We have some one-off redirects for rest api docs
45
48
// currently those are limited to the repos page, but
@@ -106,54 +109,104 @@ export const RestReferencePage = ({
106
109
// consecutive one does.
107
110
} , [ asPath ] )
108
111
112
+ // Resetting the collapsed array when we move to another REST page
113
+ useEffect ( ( ) => {
114
+ setCollapsed ( { } )
115
+ } , [ asPath ] )
116
+
117
+ const handleClick = ( param : number ) => {
118
+ setCollapsed ( ( prevState ) => {
119
+ return { ...prevState , [ param ] : ! prevState [ param ] }
120
+ } )
121
+ }
122
+
123
+ const renderTocItem = ( item : MiniTocItem , index : number ) => {
124
+ return (
125
+ < ActionList . Item
126
+ as = "li"
127
+ key = { item . contents }
128
+ className = { item . platform }
129
+ sx = { { listStyle : 'none' , padding : '2px' } }
130
+ >
131
+ < div className = { cx ( 'lh-condensed d-block width-full' ) } >
132
+ < div className = "d-inline-flex" dangerouslySetInnerHTML = { { __html : item . contents } } />
133
+ { item . items && item . items . length > 0 && (
134
+ < button
135
+ className = "background-transparent border-0 ml-1"
136
+ onClick = { ( ) => handleClick ( index ) }
137
+ >
138
+ { ! collapsed [ index ] ? < ChevronDownIcon /> : < ChevronUpIcon /> }
139
+ </ button >
140
+ ) }
141
+ { collapsed [ index ] && item . items && item . items . length > 0 ? (
142
+ < ul className = "ml-3" > { item . items . map ( renderTocItem ) } </ ul >
143
+ ) : null }
144
+ </ div >
145
+ </ ActionList . Item >
146
+ )
147
+ }
148
+
109
149
return (
110
150
< DefaultLayout >
111
151
{ /* Doesn't matter *where* this is included because it will
112
152
never render anything. It always just return null. */ }
113
153
{ loadClientsideRedirectExceptions && < ClientSideRedirectExceptions /> }
114
154
{ lazyLoadHighlightJS && < ClientSideHighlightJS /> }
115
155
116
- < div className = "container-xl px-3 px-md-6 my-4" >
117
- < ArticleGridLayout
118
- topper = { < ArticleTitle > { page . title } </ ArticleTitle > }
119
- intro = {
120
- < >
121
- { page . introPlainText && (
122
- < Lead data-testid = "lead" data-search = "lead" >
123
- { page . introPlainText }
124
- </ Lead >
125
- ) }
126
- </ >
127
- }
128
- toc = {
129
- < >
130
- { miniTocItems && miniTocItems . length > 1 && (
131
- < MiniTocs pageTitle = { page . title } miniTocItems = { miniTocItems } />
132
- ) }
133
- </ >
134
- }
135
- >
136
- < div key = { `restCategory-introContent` } >
137
- < div dangerouslySetInnerHTML = { { __html : introContent } } />
156
+ < div className = "container-xl px-3 px-md-6 my-4 mx-xl-12 mx-lg-12" >
157
+ < h1 > { page . title } </ h1 >
158
+ { page . introPlainText && (
159
+ < Lead data-testid = "lead" data-search = "lead" className = "markdown-body" >
160
+ { page . introPlainText }
161
+ </ Lead >
162
+ ) }
163
+ < div key = { `restCategory-introContent` } >
164
+ < div dangerouslySetInnerHTML = { { __html : introContent } } />
165
+ </ div >
166
+ < div className = "my-3 d-flex" >
167
+ < div className = "pr-3 mt-1" >
168
+ < Circle className = "color-fg-on-emphasis color-bg-emphasis" >
169
+ < SearchIcon className = "" size = { 15 } />
170
+ </ Circle >
138
171
</ div >
139
172
< div id = "article-contents" >
140
- < MarkdownContent >
141
- { subcategories . map ( ( subcategory , index ) => (
142
- < div key = { `restCategory-${ index } ` } >
143
- < div dangerouslySetInnerHTML = { { __html : descriptions [ subcategory ] } } />
144
- { restOperations [ subcategory ] . map ( ( operation , index ) => (
145
- < RestOperation
146
- key = { `restOperation-${ index } ` }
147
- operation = { operation }
148
- index = { index }
149
- />
150
- ) ) }
151
- </ div >
152
- ) ) }
153
- </ MarkdownContent >
173
+ < h3 > { t ( 'miniToc' ) } </ h3 >
174
+ { miniTocItems && (
175
+ < ActionList
176
+ key = { page . title }
177
+ items = { miniTocItems . map ( ( items , i ) => {
178
+ return {
179
+ key : page . title + i ,
180
+ text : page . title ,
181
+ renderItem : ( ) => < ul > { renderTocItem ( items , i ) } </ ul > ,
182
+ }
183
+ } ) }
184
+ />
185
+ ) }
154
186
</ div >
155
- </ ArticleGridLayout >
187
+ </ div >
188
+ < MarkdownContent >
189
+ { subcategories . map ( ( subcategory , index ) => (
190
+ < div key = { `restCategory-${ index } ` } >
191
+ < div dangerouslySetInnerHTML = { { __html : descriptions [ subcategory ] } } />
192
+ { restOperations [ subcategory ] . map ( ( operation , index ) => (
193
+ < RestOperation key = { `restOperation-${ index } ` } operation = { operation } index = { index } />
194
+ ) ) }
195
+ </ div >
196
+ ) ) }
197
+ </ MarkdownContent >
156
198
</ div >
157
199
</ DefaultLayout >
158
200
)
159
201
}
202
+
203
+ const Circle = ( { className, children } : { className ?: string ; children ?: React . ReactNode } ) => {
204
+ return (
205
+ < div
206
+ className = { cx ( 'circle d-flex flex-justify-center flex-items-center' , className ) }
207
+ style = { { width : 24 , height : 24 } }
208
+ >
209
+ { children }
210
+ </ div >
211
+ )
212
+ }
0 commit comments