Skip to content

Improve live code visuals #3654

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Mar 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docuilib/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "uilib-docs",
"version": "3.18.0",
"version": "3.19.0",
"main": "./src/index.ts",
"scripts": {
"docusaurus": "docusaurus",
Expand Down Expand Up @@ -31,7 +31,7 @@
"docusaurus-plugin-sass": "^0.2.1",
"file-loader": "^6.2.0",
"prettier": "2.8.8",
"prism-react-renderer": "^2.1.0",
"prism-react-renderer": "^2.4.1",
"react-html-parser": "^2.0.2",
"react-native-web": "^0.19.12",
"sass": "^1.39.0",
Expand Down
56 changes: 56 additions & 0 deletions docuilib/src/components/UILivePreview.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
$preview-width: 375px;
$preview-margin: 60px;

.container {
display: flex;
}

.liveEditor {
height: 100%;

pre {
height: 100%;
border-radius: 0;
background-color: #13191E;
}
}

.codeContainer {
position: relative;
flex: 1;
max-width: calc(100% - ($preview-width + $preview-margin));
border-radius: 4px;
overflow: hidden;

pre {
padding: 10px 20px;
}
}

.errorContainer {
position: absolute;
bottom: 0;
left: 0;
right: 0;
}

.preview {
position: relative;
width: $preview-width;
height: 700px;
margin-left: $preview-margin;
border-radius: 36px;
border: 1px solid #eee;
box-shadow: 0 0 10px rgba(110, 120, 129, 0.2);
overflow: hidden;
}

.iframe {
width: 100%;
height: 100%;
position: 'absolute';
top: 0;
left: 0;
border: 0;
padding: 10;
}
80 changes: 25 additions & 55 deletions docuilib/src/components/UILivePreview.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
import React, {useEffect, useRef, useState, useMemo} from 'react';
import {StyleSheet} from 'react-native';
import {LiveProvider, LiveEditor} from 'react-live';
import React, {useEffect, useRef, useState} from 'react';
import {LiveProvider, LiveEditor, LiveError} from 'react-live';
import {themes} from 'prism-react-renderer';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import BrowserOnly from '@docusaurus/BrowserOnly';
import CodeBlock from '@theme/CodeBlock';
import {View, Colors} from 'react-native-ui-lib/core';
import ReactLiveScope from '../theme/ReactLiveScope';
import {isComponentSupported} from '../utils/componentUtils';
import useFormattedCode from '../hooks/useFormattedCode';
import styles from './UILivePreview.module.scss';

export const IFRAME_MESSAGE_TYPE = 'LIVE_PREVIEW_CODE_UPDATE_MESSAGE';

export default function UILivePreview({code: codeProp, componentName = undefined, liveScopeSupport = false}) {
const [code, setCode] = useState(codeProp);
export default function UILivePreview({code: initialCode, componentName = undefined, liveScopeSupport = false}) {
const [iframeLoaded, setIframeLoaded] = useState(false);
const {siteConfig} = useDocusaurusContext();
const iframeRef = useRef(null);
const {code: formattedCode} = useFormattedCode(initialCode, {printWidth: 100});
const [code, setCode] = useState(formattedCode);

useEffect(() => {
setCode(formattedCode);
}, [formattedCode]);

useEffect(() => {
if (iframeLoaded) {
Expand All @@ -27,10 +33,6 @@ export default function UILivePreview({code: codeProp, componentName = undefined
iframeRef.current?.contentWindow.postMessage(message, '*');
};

const liveEditorStyle = useMemo(() => {
return {overflowY: 'scroll', scrollbarWidth: 'none'};
}, []);

if (!liveScopeSupport && !isComponentSupported(componentName)) {
return <CodeBlock language="jsx">{code}</CodeBlock>;
}
Expand All @@ -41,59 +43,27 @@ export default function UILivePreview({code: codeProp, componentName = undefined
const iframeSource = `${window.location.origin}${siteConfig?.baseUrl}livePreview`;

return (
<View row gap-s2 style={styles.liveCodeWrapper}>
<LiveProvider code={code} scope={ReactLiveScope}>
<View flex style={styles.editorWrapper}>
<LiveEditor
className="font-mono"
onChange={setCode}
//@ts-ignore
style={liveEditorStyle}
/>
</View>
<View bg-$backgroundDefault margin-s2 style={styles.iframeWrapper}>
<LiveProvider code={code} scope={ReactLiveScope} theme={themes.oceanicNext}>
<div className={styles.container}>
<div className={styles.codeContainer}>
<LiveEditor onChange={setCode} className={styles.liveEditor}/>
<div className={styles.errorContainer}>
<LiveError/>
</div>
</div>
<div className={styles.preview}>
<iframe
ref={iframeRef}
style={styles.iframe}
className={styles.iframe}
src={iframeSource}
title="Simulator"
onLoad={() => setIframeLoaded(true)}
/>
</View>
</LiveProvider>
</View>
</div>
</div>
</LiveProvider>
);
}}
</BrowserOnly>
);
}

const styles = StyleSheet.create({
liveCodeWrapper: {
borderRadius: 20,
borderWidth: 1,
backgroundColor: '#011627',
height: 725,
width: 900
},
editorWrapper: {maxHeight: 700, padding: 10, borderRadius: 20, overflow: 'hidden'},
iframeWrapper: {
alignSelf: 'center',
overflow: 'hidden',
borderRadius: 40,
borderWidth: 4,
borderColor: Colors.$outlineDisabledHeavy,
width: 320,
height: 700
},
iframe: {
width: 335, // Slightly wider to hide scrollbar
height: '100%',
position: 'absolute',
top: 0,
left: 0,
border: 0,
padding: 10,
background: 'transparent'
}
});
11 changes: 4 additions & 7 deletions docuilib/src/components/pageComponents/TableSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,10 @@ export const TableSection = ({section, component}) => {
return _.map(content, (item, index: number) => {
if (index < numberOfColumns - 1) {
return (
<td style={{backgroundColor: item.background || 'white', padding: 0, height: '100px'}}>
<ContentItem
item={item}
componentName={component.name}
showCodeButton
category={component.category}
/>
<td style={{backgroundColor: item?.background || 'white', padding: 0, height: '100px'}}>
{item && (
<ContentItem item={item} componentName={component.name} showCodeButton category={component.category}/>
)}
</td>
);
}
Expand Down
2 changes: 2 additions & 0 deletions docuilib/src/css/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
--ifm-color-primary-lightest: #232f3e;
--ifm-code-font-size: 95%;
--ifm-font-color-base: #20303C;

--ifm-container-width-xl: 1600px;
}

.docusaurus-highlight-code-line {
Expand Down
6 changes: 3 additions & 3 deletions docuilib/src/hooks/useFormattedCode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ type UseFormattedCodeOptions = {
printWidth?: number;
};
const useFormattedCode = (code: string, {printWidth = 35}: UseFormattedCodeOptions = {}) => {
const [formattedCode, setFormattedCode] = useState<string>('formatting...');
const [formattedCode, setFormattedCode] = useState<string>('');

useEffect(() => {
(async () => {
Expand All @@ -16,8 +16,8 @@ const useFormattedCode = (code: string, {printWidth = 35}: UseFormattedCodeOptio
singleQuote: true,
printWidth
});
const noLastSemiColonCode = formattedCode.trim().slice(0, -1);
setFormattedCode(noLastSemiColonCode);
// const noLastSemiColonCode = formattedCode.trim().slice(0, -1);
setFormattedCode(formattedCode);
})();
}, [code, printWidth]);

Expand Down
11 changes: 11 additions & 0 deletions docuilib/src/pages/livePreview.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.mobileFlexContainer {
display: flex;
flex-direction: column;
flex: 1;
}

.fakeTopBar {
height: 60px;
background-color: #ddd;
margin-bottom: 1px;
}
13 changes: 4 additions & 9 deletions docuilib/src/pages/livePreview.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React, {useEffect, useState} from 'react';
import {StyleSheet} from 'react-native';
import {LiveProvider, LivePreview} from 'react-live';
import ReactLiveScope from '../theme/ReactLiveScope';
import {IFRAME_MESSAGE_TYPE} from '@site/src/components/UILivePreview';
import ReactLiveScope from '../theme/ReactLiveScope';
import styles from './livePreview.module.css';

export default function UILivePreview() {
const [code, setCode] = useState(``);
Expand All @@ -17,13 +17,8 @@ export default function UILivePreview() {

return (
<LiveProvider code={code} scope={ReactLiveScope}>
<LivePreview style={styles.livePreview}/>
<div className={styles.fakeTopBar}/>
<LivePreview className={styles.mobileFlexContainer}/>
</LiveProvider>
);
}

const styles = StyleSheet.create({
livePreview: {
overflow: 'hidden'
}
});
8 changes: 4 additions & 4 deletions docuilib/src/theme/ReactLiveScope/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,17 @@ import * as Playground from './Playground';
Assets.loadAssetsGroup('icons.demo', {
// chevronDown: require('../../assets/icons/chevronDown.png').default,
chevronRight: {
uri: require('../../assets/icons/chevronRight.png').default,
uri: require('../../assets/icons/chevronRight.png'),
width: 24,
height: 24
},
chevronDown: {
uri: require('../../assets/icons/chevronDown.png').default,
uri: require('../../assets/icons/chevronDown.png'),
width: 14,
height: 8
},
star: {
uri: require('../../assets/icons/star.png').default,
uri: require('../../assets/icons/star.png'),
width: 24,
height: 24
},
Expand All @@ -52,7 +52,7 @@ Assets.loadAssetsGroup('icons.demo', {
// close: require('../../assets/icons/close.png').default,
// dashboard: require('../../assets/icons/dashboard.png').default,
drag: {
uri: require('../../assets/icons/drag.png').default,
uri: require('../../assets/icons/drag.png'),
width: 10,
height: 16
}
Expand Down
16 changes: 14 additions & 2 deletions docuilib/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -10598,7 +10598,7 @@ __metadata:
languageName: node
linkType: hard

"prism-react-renderer@npm:^2.0.6, prism-react-renderer@npm:^2.1.0, prism-react-renderer@npm:^2.3.0":
"prism-react-renderer@npm:^2.0.6, prism-react-renderer@npm:^2.3.0":
version: 2.4.0
resolution: "prism-react-renderer@npm:2.4.0"
dependencies:
Expand All @@ -10610,6 +10610,18 @@ __metadata:
languageName: node
linkType: hard

"prism-react-renderer@npm:^2.4.1":
version: 2.4.1
resolution: "prism-react-renderer@npm:2.4.1"
dependencies:
"@types/prismjs": ^1.26.0
clsx: ^2.0.0
peerDependencies:
react: ">=16.0.0"
checksum: ddd5490a1335629addde9535db7872f0aee8dbce048818dd6e4c3972c779780af13d669c12d3f2fbb54c5b22d1578e50945099ef1a24dd445f33774e87d85e6e
languageName: node
linkType: hard

"prismjs@npm:^1.29.0":
version: 1.30.0
resolution: "prismjs@npm:1.30.0"
Expand Down Expand Up @@ -12923,7 +12935,7 @@ __metadata:
docusaurus-plugin-sass: ^0.2.1
file-loader: ^6.2.0
prettier: 2.8.8
prism-react-renderer: ^2.1.0
prism-react-renderer: ^2.4.1
react: ^18.2.0
react-dom: ^18.2.0
react-html-parser: ^2.0.2
Expand Down
Loading