1import { css } from '@emotion/react'; 2import { theme, typography } from '@expo/styleguide'; 3import * as React from 'react'; 4 5const MDX_CLASS_NAME_TO_TAB_NAME: Record<string, string> = { 6 'language-swift': 'Swift', 7 'language-kotlin': 'Kotlin', 8 'language-javascript': 'JavaScript', 9 'language-typescript': 'TypeScript', 10 'language-json': 'JSON', 11 'language-ruby': 'Ruby', 12 'language-groovy': 'Gradle', 13}; 14 15const CodeSamplesCSS = css` 16 display: flex; 17 flex-direction: row; 18 max-width: 100%; 19 margin: 20px 0; 20 21 .code-block-column { 22 display: flex; 23 flex-direction: column; 24 flex: 1; 25 margin-right: -1px; 26 min-width: 0; 27 28 pre { 29 border-top-left-radius: 0; 30 border-top-right-radius: 0; 31 } 32 &:not(:first-of-type) pre { 33 border-bottom-left-radius: 0; 34 } 35 &:not(:last-child) pre { 36 border-bottom-right-radius: 0; 37 } 38 &:first-of-type .code-block-header { 39 border-top-left-radius: 4px; 40 } 41 &:last-child .code-block-header { 42 border-top-right-radius: 4px; 43 } 44 } 45 .code-block-header { 46 padding: 6px 16px; 47 background-color: ${theme.background.secondary}; 48 border: 1px solid ${theme.border.default}; 49 border-bottom-width: 0px; 50 51 span { 52 ${typography.fontSizes[15]} 53 color: ${theme.text.default}; 54 font-family: ${typography.fontFaces.mono}; 55 } 56 } 57 .code-block-content { 58 flex: 1; 59 overflow-x: auto; 60 61 pre { 62 height: 100%; 63 margin: 0; 64 65 ::-webkit-scrollbar { 66 height: 6px; 67 } 68 ::-webkit-scrollbar-track { 69 background: ${theme.background.secondary}; 70 } 71 ::-webkit-scrollbar-thumb { 72 background: ${theme.background.tertiary}; 73 border-radius: 10px; 74 } 75 ::-webkit-scrollbar-thumb:hover { 76 background: ${theme.background.quaternary}; 77 } 78 } 79 } 80`; 81 82type Props = { 83 children: JSX.Element[]; 84 tabs?: string[]; 85}; 86 87export function CodeBlocksTable({ children, tabs }: Props) { 88 const childrenArray = Array.isArray(children) ? children : [children]; 89 const codeBlocks = childrenArray.filter( 90 ({ props }) => props.mdxType === 'pre' && props.children.props.className 91 ); 92 const tabNames = 93 tabs || 94 codeBlocks.map(child => { 95 const className = child.props.children.props.className; 96 return MDX_CLASS_NAME_TO_TAB_NAME[className] || className.replace('language-', ''); 97 }); 98 99 return ( 100 <div css={CodeSamplesCSS}> 101 {codeBlocks.map((codeBlock, index) => ( 102 <div key={index} className="code-block-column"> 103 <div className="code-block-header"> 104 <span>{tabNames[index]}</span> 105 </div> 106 <div className="code-block-content">{codeBlock}</div> 107 </div> 108 ))} 109 </div> 110 ); 111} 112