diff --git a/package-lock.json b/package-lock.json
index 263769291..dddea48c4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2322,6 +2322,11 @@
"fastq": "^1.6.0"
}
},
+ "@popperjs/core": {
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.4.4.tgz",
+ "integrity": "sha512-1oO6+dN5kdIA3sKPZhRGJTfGVP4SWV6KqlMOwry4J3HfyD68sl/3KmG7DeYUzvN+RbhXDnv/D8vNNB8168tAMg=="
+ },
"@samverschueren/stream-to-observable": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz",
@@ -2492,6 +2497,14 @@
}
}
},
+ "@tippyjs/react": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@tippyjs/react/-/react-4.1.0.tgz",
+ "integrity": "sha512-g6Dpm46edr9T9z+BYxd/eJZa6QMFc4T4z5xrztxVlkti7AhNYf7OaE6b3Nh+boUZZ9wn8xkNq9VrQM5K4huwnQ==",
+ "requires": {
+ "tippy.js": "^6.2.0"
+ }
+ },
"@types/anymatch": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz",
@@ -3582,7 +3595,7 @@
},
"array-equal": {
"version": "1.0.0",
- "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz",
+ "resolved": "http://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz",
"integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=",
"dev": true
},
@@ -3695,7 +3708,7 @@
},
"util": {
"version": "0.10.3",
- "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
+ "resolved": "http://registry.npmjs.org/util/-/util-0.10.3.tgz",
"integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
"dev": true,
"requires": {
@@ -3816,7 +3829,7 @@
},
"chalk": {
"version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
"requires": {
"ansi-styles": "^2.2.1",
@@ -3833,7 +3846,7 @@
},
"strip-ansi": {
"version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"requires": {
"ansi-regex": "^2.0.0"
@@ -4415,7 +4428,7 @@
},
"browserify-aes": {
"version": "1.2.0",
- "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
+ "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
"integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
"dev": true,
"requires": {
@@ -4452,7 +4465,7 @@
},
"browserify-rsa": {
"version": "4.0.1",
- "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
+ "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
"integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
"dev": true,
"requires": {
@@ -4610,7 +4623,7 @@
"dependencies": {
"callsites": {
"version": "2.0.0",
- "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
+ "resolved": "http://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
"integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=",
"dev": true
}
@@ -4859,7 +4872,7 @@
},
"slice-ansi": {
"version": "0.0.4",
- "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz",
+ "resolved": "http://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz",
"integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=",
"dev": true
},
@@ -4876,7 +4889,7 @@
},
"strip-ansi": {
"version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"requires": {
@@ -4990,7 +5003,7 @@
},
"colors": {
"version": "0.6.2",
- "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz",
+ "resolved": "http://registry.npmjs.org/colors/-/colors-0.6.2.tgz",
"integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w="
},
"combined-stream": {
@@ -5004,7 +5017,7 @@
},
"commander": {
"version": "2.1.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.1.0.tgz",
+ "resolved": "http://registry.npmjs.org/commander/-/commander-2.1.0.tgz",
"integrity": "sha1-0SG7roYNmZKj1Re6lvVliOR8Z4E="
},
"common-dir": {
@@ -5354,7 +5367,7 @@
},
"create-hash": {
"version": "1.2.0",
- "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
+ "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
"integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
"dev": true,
"requires": {
@@ -5367,7 +5380,7 @@
},
"create-hmac": {
"version": "1.1.7",
- "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
+ "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
"integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
"dev": true,
"requires": {
@@ -5474,7 +5487,7 @@
},
"css-select": {
"version": "1.2.0",
- "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
+ "resolved": "http://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
"integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
"dev": true,
"requires": {
@@ -5739,7 +5752,7 @@
"dependencies": {
"globby": {
"version": "6.1.0",
- "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
+ "resolved": "http://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
"integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
"requires": {
"array-union": "^1.0.1",
@@ -5751,7 +5764,7 @@
"dependencies": {
"pify": {
"version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
}
}
@@ -5838,7 +5851,7 @@
},
"diffie-hellman": {
"version": "5.0.3",
- "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
+ "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
"integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
"dev": true,
"requires": {
@@ -5959,7 +5972,7 @@
},
"duplexer": {
"version": "0.1.1",
- "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
+ "resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
"integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E="
},
"duplexify": {
@@ -6754,7 +6767,7 @@
"dependencies": {
"doctrine": {
"version": "1.5.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
+ "resolved": "http://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
"integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=",
"dev": true,
"requires": {
@@ -7760,8 +7773,7 @@
},
"ansi-regex": {
"version": "2.1.1",
- "bundled": true,
- "optional": true
+ "bundled": true
},
"aproba": {
"version": "1.2.0",
@@ -7779,13 +7791,11 @@
},
"balanced-match": {
"version": "1.0.0",
- "bundled": true,
- "optional": true
+ "bundled": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
- "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -7798,18 +7808,15 @@
},
"code-point-at": {
"version": "1.1.0",
- "bundled": true,
- "optional": true
+ "bundled": true
},
"concat-map": {
"version": "0.0.1",
- "bundled": true,
- "optional": true
+ "bundled": true
},
"console-control-strings": {
"version": "1.1.0",
- "bundled": true,
- "optional": true
+ "bundled": true
},
"core-util-is": {
"version": "1.0.2",
@@ -7912,8 +7919,7 @@
},
"inherits": {
"version": "2.0.3",
- "bundled": true,
- "optional": true
+ "bundled": true
},
"ini": {
"version": "1.3.5",
@@ -7923,7 +7929,6 @@
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
- "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -7936,20 +7941,17 @@
"minimatch": {
"version": "3.0.4",
"bundled": true,
- "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "0.0.8",
- "bundled": true,
- "optional": true
+ "bundled": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
- "optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@@ -7966,7 +7968,6 @@
"mkdirp": {
"version": "0.5.1",
"bundled": true,
- "optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -8039,8 +8040,7 @@
},
"number-is-nan": {
"version": "1.0.1",
- "bundled": true,
- "optional": true
+ "bundled": true
},
"object-assign": {
"version": "4.1.1",
@@ -8050,7 +8050,6 @@
"once": {
"version": "1.4.0",
"bundled": true,
- "optional": true,
"requires": {
"wrappy": "1"
}
@@ -8126,8 +8125,7 @@
},
"safe-buffer": {
"version": "5.1.2",
- "bundled": true,
- "optional": true
+ "bundled": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -8157,7 +8155,6 @@
"string-width": {
"version": "1.0.2",
"bundled": true,
- "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -8175,7 +8172,6 @@
"strip-ansi": {
"version": "3.0.1",
"bundled": true,
- "optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -8214,13 +8210,11 @@
},
"wrappy": {
"version": "1.0.2",
- "bundled": true,
- "optional": true
+ "bundled": true
},
"yallist": {
"version": "3.0.3",
- "bundled": true,
- "optional": true
+ "bundled": true
}
}
},
@@ -9360,7 +9354,7 @@
},
"is-obj": {
"version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
+ "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
"integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8="
},
"is-observable": {
@@ -11540,7 +11534,7 @@
},
"jsesc": {
"version": "0.5.0",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+ "resolved": "http://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
"integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0="
},
"json-parse-better-errors": {
@@ -12128,7 +12122,7 @@
},
"chalk": {
"version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
"dev": true,
"requires": {
@@ -12166,7 +12160,7 @@
},
"strip-ansi": {
"version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"requires": {
@@ -12828,7 +12822,7 @@
},
"mkdirp": {
"version": "0.5.1",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"requires": {
"minimist": "0.0.8"
@@ -12836,7 +12830,7 @@
"dependencies": {
"minimist": {
"version": "0.0.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
}
}
@@ -13384,7 +13378,7 @@
},
"os-tmpdir": {
"version": "1.0.2",
- "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
},
"p-defer": {
@@ -13549,7 +13543,7 @@
},
"path-is-absolute": {
"version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"path-is-inside": {
@@ -14513,7 +14507,7 @@
},
"readable-stream": {
"version": "2.3.6",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+ "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"requires": {
"core-util-is": "~1.0.0",
@@ -15066,7 +15060,7 @@
},
"safe-regex": {
"version": "1.1.0",
- "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+ "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
"integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
"requires": {
"ret": "~0.1.10"
@@ -15273,7 +15267,7 @@
},
"sha.js": {
"version": "2.4.11",
- "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
+ "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
"integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
"dev": true,
"requires": {
@@ -16189,7 +16183,7 @@
},
"strip-eof": {
"version": "1.0.0",
- "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+ "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
},
"strip-final-newline": {
@@ -16560,7 +16554,7 @@
},
"through": {
"version": "2.3.8",
- "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
},
"through2": {
@@ -16607,6 +16601,14 @@
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
},
+ "tippy.js": {
+ "version": "6.2.5",
+ "resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.2.5.tgz",
+ "integrity": "sha512-UIf8G99PMXGmdWPrr36s/DjQBdfxMPwzvPUXsxs3tDFDTZ1SgvKG+Jvt6RJ+aBqYL0oe/STxh3MNkCV3IWAKmw==",
+ "requires": {
+ "@popperjs/core": "^2.4.4"
+ }
+ },
"tmp": {
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
@@ -16638,7 +16640,7 @@
"dependencies": {
"ast-types": {
"version": "0.7.8",
- "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.7.8.tgz",
+ "resolved": "http://registry.npmjs.org/ast-types/-/ast-types-0.7.8.tgz",
"integrity": "sha1-kC0uDWDQcb3NRtwRXhgJ7RHBOKk="
},
"esprima": {
diff --git a/package.json b/package.json
index 165b08c54..71327f6dd 100644
--- a/package.json
+++ b/package.json
@@ -28,6 +28,7 @@
"node": ">=10"
},
"dependencies": {
+ "@tippyjs/react": "4.1.0",
"@vxna/mini-html-webpack-template": "^1.0.0",
"acorn": "^6.4.1",
"acorn-jsx": "^5.1.0",
diff --git a/src/client/rsg-components/ComplexType/ComplexType.spec.tsx b/src/client/rsg-components/ComplexType/ComplexType.spec.tsx
new file mode 100644
index 000000000..c51bf06a1
--- /dev/null
+++ b/src/client/rsg-components/ComplexType/ComplexType.spec.tsx
@@ -0,0 +1,20 @@
+import React from 'react';
+import { render, fireEvent } from '@testing-library/react';
+import ComplexType from './ComplexTypeRenderder';
+
+function renderComponent(name = 'color', raw = 'red | blue') {
+ return render();
+}
+
+describe('ComplexType', () => {
+ test('should render name', () => {
+ const { getByRole } = renderComponent();
+ expect(getByRole('button')).toHaveTextContent('color');
+ });
+
+ test('should render raw text in the tooltip', () => {
+ const { container, getByRole } = renderComponent();
+ fireEvent.focus(getByRole('button'));
+ expect(container.querySelector('[data-tippy-root]')).toHaveTextContent('red | blue');
+ });
+});
diff --git a/src/client/rsg-components/ComplexType/ComplexTypeRenderder.tsx b/src/client/rsg-components/ComplexType/ComplexTypeRenderder.tsx
new file mode 100644
index 000000000..8800fe6d7
--- /dev/null
+++ b/src/client/rsg-components/ComplexType/ComplexTypeRenderder.tsx
@@ -0,0 +1,36 @@
+import React from 'react';
+import Styled, { JssInjectedProps } from 'rsg-components/Styled';
+import { MdInfoOutline } from 'react-icons/md';
+import Text from 'rsg-components/Text';
+import Tooltip from 'rsg-components/Tooltip';
+import * as Rsg from '../../../typings';
+
+export const styles = ({ space }: Rsg.Theme) => ({
+ complexType: {
+ alignItems: 'center',
+ cursor: 'pointer',
+ display: 'inline-flex',
+ '& span': {
+ marginRight: space[0],
+ cursor: 'pointer',
+ },
+ },
+});
+
+export interface ComplexTypeProps extends JssInjectedProps {
+ name: string;
+ raw: string;
+}
+
+function ComplexTypeRenderer({ classes, name, raw }: ComplexTypeProps) {
+ return (
+
+
+ {name}
+
+
+
+ );
+}
+
+export default Styled(styles)(ComplexTypeRenderer);
diff --git a/src/client/rsg-components/ComplexType/index.ts b/src/client/rsg-components/ComplexType/index.ts
new file mode 100644
index 000000000..8710c1335
--- /dev/null
+++ b/src/client/rsg-components/ComplexType/index.ts
@@ -0,0 +1 @@
+export { default } from 'rsg-components/ComplexType/ComplexTypeRenderder';
diff --git a/src/client/rsg-components/Props/Props.spec.tsx b/src/client/rsg-components/Props/Props.spec.tsx
index 83b9d80a9..231f9665c 100644
--- a/src/client/rsg-components/Props/Props.spec.tsx
+++ b/src/client/rsg-components/Props/Props.spec.tsx
@@ -1,6 +1,6 @@
/* eslint-disable react/prop-types */
import React from 'react';
-import { render } from '@testing-library/react';
+import { render, fireEvent } from '@testing-library/react';
import { parse } from 'react-docgen';
import PropsRenderer, { columns, getRowKey } from './PropsRenderer';
import { unquote, getType, showSpaces, PropDescriptor } from './util';
@@ -513,7 +513,7 @@ describe('props columns', () => {
{
name: 'Foo',
description: 'Converts foo to bar',
- type: {type: 'NameExpression', name: 'Array' },
+ type: { type: 'NameExpression', name: 'Array' },
},
],
param: [
@@ -551,7 +551,7 @@ describe('props columns', () => {
{
title: 'Foo',
description: 'Returns foo from bar',
- type: {type: 'NameExpression', name: 'Array' },
+ type: { type: 'NameExpression', name: 'Array' },
},
],
},
@@ -658,21 +658,27 @@ describe('props columns', () => {
});
test('should render object type with body in tooltip', () => {
- const { getByText } = renderFn(['foo: { bar: string }']);
+ const { container, getByRole } = renderFn(['foo: { bar: string }']);
+ fireEvent.focus(getByRole('button'));
- expect(getByText('object').title).toMatchInlineSnapshot(`"{ bar: string }"`);
+ expect(getByRole('button')).toHaveTextContent('object');
+ expect(container.querySelector('[data-tippy-root]')).toHaveTextContent('{ bar: string }');
});
test('should render function type with body in tooltip', () => {
- const { getByText } = renderFn(['foo: () => void']);
+ const { container, getByRole } = renderFn(['foo: () => void']);
+ fireEvent.focus(getByRole('button'));
- expect(getByText('function').title).toMatchInlineSnapshot(`"() => void"`);
+ expect(getByRole('button')).toHaveTextContent('function');
+ expect(container.querySelector('[data-tippy-root]')).toHaveTextContent('() => void');
});
test('should render union type with body in tooltip', () => {
- const { getByText } = renderFn(['foo: "bar" | number']);
+ const { container, getByRole } = renderFn(['foo: "bar" | number']);
+ fireEvent.focus(getByRole('button'));
- expect(getByText('union').title).toMatchInlineSnapshot(`"\\"bar\\" | number"`);
+ expect(getByRole('button')).toHaveTextContent('union');
+ expect(container.querySelector('[data-tippy-root]')).toHaveTextContent('"bar" | number');
});
test('should render enum type', () => {
@@ -696,9 +702,12 @@ describe('props columns', () => {
});
test('should render tuple type with body in tooltip', () => {
- const { getByText } = renderFn(['foo: ["bar", number]']);
+ const { container, getByRole } = renderFn(['foo: ["bar", number]']);
- expect(getByText('tuple').title).toMatchInlineSnapshot(`"[\\"bar\\", number]"`);
+ fireEvent.focus(getByRole('button'));
+
+ expect(getByRole('button')).toHaveTextContent('tuple');
+ expect(container.querySelector('[data-tippy-root]')).toHaveTextContent('["bar", number]');
});
test('should render custom class type', () => {
diff --git a/src/client/rsg-components/Props/renderType.tsx b/src/client/rsg-components/Props/renderType.tsx
index ba36c33e6..e73683444 100644
--- a/src/client/rsg-components/Props/renderType.tsx
+++ b/src/client/rsg-components/Props/renderType.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { PropTypeDescriptor } from 'react-docgen';
import Type from 'rsg-components/Type';
-import Text from 'rsg-components/Text';
+import ComplexType from 'rsg-components/ComplexType';
import { getType, PropDescriptor, TypeDescriptor } from './util';
@@ -28,31 +28,23 @@ export function renderType(type: ExtendedPropTypeDescriptor): string {
}
}
-function renderComplexType(name: string, title: string): React.ReactNode {
- return (
-
- {name}
-
- );
-}
-
function renderAdvancedType(type: TypeDescriptor): React.ReactNode {
if (!type) {
- return 'unknown';
+ return unknown;
}
switch (type.name) {
case 'enum':
- return type.name;
+ return {type.name};
case 'literal':
- return type.value;
+ return {type.value};
case 'signature':
- return renderComplexType(type.type, type.raw);
+ return ;
case 'union':
case 'tuple':
- return renderComplexType(type.name, type.raw);
+ return ;
default:
- return (type as any).raw || (type as any).name;
+ return {(type as any).raw || (type as any).name};
}
}
@@ -62,7 +54,7 @@ export default function renderTypeColumn(prop: PropDescriptor): React.ReactNode
return null;
}
if (prop.flowType || prop.tsType) {
- return {renderAdvancedType(type as any)};
+ return renderAdvancedType(type as any);
}
return {renderType(type)};
}
diff --git a/src/client/rsg-components/Tooltip/Tooltip.spec.tsx b/src/client/rsg-components/Tooltip/Tooltip.spec.tsx
new file mode 100644
index 000000000..fad7d0ef5
--- /dev/null
+++ b/src/client/rsg-components/Tooltip/Tooltip.spec.tsx
@@ -0,0 +1,74 @@
+import React from 'react';
+import { render, fireEvent, waitFor } from '@testing-library/react';
+import Tooltip, { TooltipPlacement } from './TooltipRenderer';
+
+function renderComponent(content = 'tooltip', placement?: TooltipPlacement) {
+ return render(
+
+
+
+ );
+}
+
+describe('Tooltip', () => {
+ test('should render child component as is', () => {
+ const { container, getByTestId } = renderComponent();
+ expect(container).toContainElement(getByTestId('child'));
+ });
+
+ test('should the child component be wrapped by "role=button" element', () => {
+ const { getByTestId } = renderComponent();
+ expect(getByTestId('child').closest('span')).toHaveAttribute('role', 'button');
+ });
+
+ test('should render content in the tooltop body', () => {
+ const { container, getByRole } = renderComponent();
+ fireEvent.focus(getByRole('button'));
+ expect(container.querySelector('[data-tippy-root]')).toHaveTextContent('tooltip');
+ });
+
+ test('should show the tooltip by focus in', async () => {
+ const { container, getByRole } = renderComponent();
+ fireEvent.focus(getByRole('button'));
+ await waitFor(() =>
+ expect(container.querySelector('[data-state="visible"]')).toBeInTheDocument()
+ );
+ expect(container.querySelector('[data-state]')).toHaveAttribute('data-state', 'visible');
+ });
+
+ test('should show the tooltip by click', async () => {
+ const { container, getByRole } = renderComponent();
+ fireEvent.click(getByRole('button'));
+ await waitFor(() =>
+ expect(container.querySelector('[data-state="visible"]')).toBeInTheDocument()
+ );
+ expect(container.querySelector('[data-state]')).toHaveAttribute('data-state', 'visible');
+ });
+
+ test('should show the tooltip by mouse enter', async () => {
+ const { container, getByRole } = renderComponent();
+ fireEvent.mouseEnter(getByRole('button'));
+ await waitFor(() =>
+ expect(container.querySelector('[data-state="visible"]')).toBeInTheDocument()
+ );
+ expect(container.querySelector('[data-state]')).toHaveAttribute('data-state', 'visible');
+ });
+
+ describe.each([['top'], ['right'], ['left'], ['bottom']])(
+ 'Test placement attribute',
+ placement => {
+ test(`should have ${placement} in data-placement attribute`, async () => {
+ // @ts-ignore
+ const { container, getByRole } = renderComponent(undefined, placement);
+ fireEvent.focus(getByRole('button'));
+ await waitFor(() =>
+ expect(container.querySelector('[data-state="visible"]')).toBeInTheDocument()
+ );
+ expect(container.querySelector('[data-placement]')).toHaveAttribute(
+ 'data-placement',
+ placement
+ );
+ });
+ }
+ );
+});
diff --git a/src/client/rsg-components/Tooltip/TooltipRenderer.tsx b/src/client/rsg-components/Tooltip/TooltipRenderer.tsx
new file mode 100644
index 000000000..f7492c01e
--- /dev/null
+++ b/src/client/rsg-components/Tooltip/TooltipRenderer.tsx
@@ -0,0 +1,51 @@
+import React from 'react';
+import Tippy from '@tippyjs/react';
+import Styled, { JssInjectedProps } from 'rsg-components/Styled';
+import * as Rsg from '../../../typings';
+
+export const styles = ({ space, color, borderRadius, fontSize }: Rsg.Theme) => ({
+ tooltip: {
+ '&.tippy-box': {
+ transitionProperty: [['opacity']],
+ '&[data-state="hidden"]': {
+ opacity: 0,
+ },
+ },
+ '& .tippy-content': {
+ padding: space[0],
+ border: `1px ${color.border} solid`,
+ borderRadius,
+ background: color.baseBackground,
+ boxShadow: [[0, 2, 4, 'rgba(0,0,0,.15)']],
+ fontSize: fontSize.small,
+ color: color.type,
+ },
+ },
+});
+
+export type TooltipPlacement = 'top' | 'right' | 'bottom' | 'left';
+
+export interface TooltipProps extends JssInjectedProps {
+ children: React.ReactNode;
+ content: React.ReactNode;
+ placement?: TooltipPlacement;
+}
+
+function TooltipRenderer({ classes, children, content, placement = 'top' }: TooltipProps) {
+ return (
+
+
+ {children}
+
+
+ );
+}
+
+export default Styled(styles)(TooltipRenderer);
diff --git a/src/client/rsg-components/Tooltip/index.ts b/src/client/rsg-components/Tooltip/index.ts
new file mode 100644
index 000000000..7d61a1a47
--- /dev/null
+++ b/src/client/rsg-components/Tooltip/index.ts
@@ -0,0 +1 @@
+export { default } from 'rsg-components/Tooltip/TooltipRenderer';