@@ -2,20 +2,27 @@ import {Absolute, BorderBox, Relative, Text} from '@primer/components'
2
2
import Highlight , { defaultProps } from 'prism-react-renderer'
3
3
import githubTheme from 'prism-react-renderer/themes/github'
4
4
import React from 'react'
5
+ import { useState , useEffect } from 'react'
5
6
import ClipboardCopy from './clipboard-copy'
6
7
import LiveCode from './live-code'
7
8
8
9
function Code ( { className, children, live, noinline} ) {
10
+ const [ scrollHandleStyle , setScrollHandleStyle ] = useState ( { position : 'absolute' } )
9
11
const language = className ? className . replace ( / l a n g u a g e - / , '' ) : ''
10
12
const code = children . trim ( )
13
+ const scrollHandleRef = React . createRef ( )
14
+
15
+ useEffect ( ( ) => {
16
+ resizeScrollHandle ( )
17
+ } )
11
18
12
19
if ( live ) {
13
20
return < LiveCode code = { code } language = { language } noinline = { noinline } />
14
21
}
15
22
16
23
return (
17
24
< Relative >
18
- < Absolute top = { 0 } right = { 0 } p = { 2 } >
25
+ < Absolute top = { 0 } right = { 0 } p = { 2 } zIndex = { 1 } >
19
26
< ClipboardCopy value = { code } />
20
27
</ Absolute >
21
28
< Highlight
@@ -34,6 +41,8 @@ function Code({className, children, live, noinline}) {
34
41
border = { 0 }
35
42
style = { { ...style , overflow : 'auto' } }
36
43
>
44
+ { /* This is the scroll handle, it is supposed to be focused with keyboard and scroll a wide codebox horizontally */ }
45
+ < div aria-hidden = "true" tabIndex = { 0 } style = { scrollHandleStyle } ref = { scrollHandleRef } aria-label = { code } > </ div >
37
46
{ tokens . map ( ( line , i ) => (
38
47
< div key = { i } { ...getLineProps ( { line, key : i } ) } >
39
48
{ line . map ( ( token , key ) => (
@@ -51,6 +60,22 @@ function Code({className, children, live, noinline}) {
51
60
</ Highlight >
52
61
</ Relative >
53
62
)
63
+
64
+ /**
65
+ * Resize the scroll handle to the size of the code contents, since the former has to be positioned absolutely.
66
+ */
67
+ function resizeScrollHandle ( ) {
68
+ // Skip if already resized.
69
+ if ( typeof scrollHandleStyle . width !== 'undefined' )
70
+ return
71
+
72
+ const node = scrollHandleRef . current
73
+ node . parentElement . style . position = 'relative'
74
+ const computedStyle = getComputedStyle ( node . parentElement )
75
+ const height = node . parentElement . clientHeight - parseInt ( computedStyle . paddingTop , 10 ) - parseInt ( computedStyle . paddingBottom , 10 )
76
+ const width = node . parentElement . scrollWidth - parseInt ( computedStyle . paddingLeft , 10 ) - parseInt ( computedStyle . paddingRight , 10 )
77
+ setScrollHandleStyle ( { ...scrollHandleStyle , height, width} )
78
+ }
54
79
}
55
80
56
81
export default Code
0 commit comments