storybookjs / storybook

Storybook is the industry standard workshop for building, documenting, and testing UI components in isolation
https://storybook.js.org
MIT License
84.21k stars 9.26k forks source link

Text inside of DocPage stories can be selected but can not be copied. #18611

Closed andyford closed 1 year ago

andyford commented 2 years ago

Describe the bug Text inside of DocPage stories can be selected but can not be copied.

To Reproduce Can be seen here:

I asked on Discord if this was a known issue and @kylegach discovered the issue exists on the above 3 instances.

I first noticed this in a private storybook instance running on @storybook/react v6.5.4 but it appears the the above 3 instances as well.

Additional context Tested on Mac in Chrome, Firefox, and Safari. Text cannot be copied through conventional means (cmd+c or right click and select "Copy" from context menu) but I noticed it's still possible to use navigator.clipboard.writeText()

EDIT (2022-08-09) Just to clarify. Rendered text/code inside of code preview blocks appears to be manually selectable and copy-able (in addition to the Copy button still functioning fine. This bug report is about the text content within the rendered stories themselves. This also appears to only affect the Docs tab and not the Canvas tab.

Here's a video: https://user-images.githubusercontent.com/49811/183597174-c04353ba-54a0-4ea2-b617-1c45e7533484.mp4

petdud commented 2 years ago

+1, facing the same issue here: https://react.fluentui.dev/?path=/docs/theme-color--page The storybook contains an indication that the item is copied, so I assume the problem might be somewhere there?

Screenshot 2022-07-25 at 2 23 12 PM
pocka commented 2 years ago

It seems this behavior is intentional... see #15559.

I feel that "feature" is both unintuitive and surprising. In my opinion, it's should be an opt-in feature or be assigned to a safe and unused shortcut key.

jphawk commented 2 years ago

Agree with @pocka. I'm taking care of a design system done in storybook and I'm getting plenty of complaints from developers who can't copy e.g. color codes or spacing values from DocPages 😬 It would be great to make this optional, as it just doesn't suit some use cases

andyford commented 2 years ago

I'm taking care of a design system done in storybook and I'm getting plenty of complaints from developers who can't copy e.g. color codes or spacing values from DocPages

That's exactly how I discovered this issue! In this case we implemented our own copy-to-clipboard functionality, but we shouldn't have to do this.

andyford commented 2 years ago

It seems this behavior is intentional... see #15559.

I'm not 100% sure... You can still manually select and copy rendered text inside of the code blocks. But you can't copy text in the rendered stories. Maybe it is somehow related... but maybe not? 🤷

EDIT: After making a video (which I've added to the original post) and watching it back, I noticed that when I copy text from the rendered story (around 0:13 to 0:17), the UI temporarily says Copied in the bottom right corner. So this is could indicate that this bug is somehow tied to the source code copying functionality as @pocka suggested.

shilman commented 1 year ago

Yo-ho-ho!! I just released https://github.com/storybookjs/storybook/releases/tag/v7.0.0-beta.27 containing PR #19788 that references this issue. Upgrade today to the @next NPM tag to try it out!

npx sb@next upgrade --prerelease

Closing this issue. Please re-open if you think there's still more to do.

James-Wilkinson-git commented 1 year ago

Can we get a fix for this in non storybook 7? for those who can't upgrade?

riotrah commented 1 month ago

Just want to echo the prior poster's request.

Upgrading for us is not tenable in the near future, largely due to lack of developer resources available to migrate our bespoke clojurescript -> js -> storybook build setup.

It would be lovely to have this fixed in v6. Any guidance as to how to maybe monkeypatch this ourselves would also be appreciated if anyone has any!

pocka commented 1 month ago

I'm willing to send a patch to v6 release but that release channel seems to be unmaintained? I see release-6-5 branch got some updates, however there are no v6 releases since v6.5.16 (2 years ago).

So here is a workaround: a patch for v6.5.16 generated using patch-package. Copyright and license are same to the ones of Storybook repo code (for ease and simplicity).

# Unofficial patch for https://github.com/storybookjs/storybook/issues/18611
# SPDX-FileCopyrightText: Copyright (c) 2024 Storybook
# SPDX-License-Identifier: MIT
diff --git a/node_modules/@storybook/components/dist/esm/index-681e4b07.js b/node_modules/@storybook/components/dist/esm/index-681e4b07.js
index 1fe1e2d..68f43f2 100644
--- a/node_modules/@storybook/components/dist/esm/index-681e4b07.js
+++ b/node_modules/@storybook/components/dist/esm/index-681e4b07.js
@@ -351,7 +351,12 @@ if(CONFIG_TYPE!=='DEVELOPMENT'||!EventSource)return undefined;var eventSource=ne
  * items. The preview also shows the source for the component
  * as a drop-down.
  */var Preview=function Preview(_a){var isLoading=_a.isLoading,isColumn=_a.isColumn,columns=_a.columns,children=_a.children,withSource=_a.withSource,_a$withToolbar=_a.withToolbar,withToolbar=_a$withToolbar===void 0?false:_a$withToolbar,_a$isExpanded=_a.isExpanded,isExpanded=_a$isExpanded===void 0?false:_a$isExpanded,additionalActions=_a.additionalActions,className=_a.className,props=__rest(_a,["isLoading","isColumn","columns","children","withSource","withToolbar","isExpanded","additionalActions","className"]);var _useState7=useState(isExpanded),_useState8=_slicedToArray(_useState7,2),expanded=_useState8[0],setExpanded=_useState8[1];var _getSource=getSource(withSource,expanded,setExpanded),source=_getSource.source,actionItem=_getSource.actionItem;var _useState9=useState(1),_useState10=_slicedToArray(_useState9,2),scale=_useState10[0],setScale=_useState10[1];var previewClasses=[className].concat(['sbdocs','sbdocs-preview']);var defaultActionItems=withSource?[actionItem]:[];var _useState11=useState(additionalActions?_toConsumableArray(additionalActions):[]),_useState12=_slicedToArray(_useState11,2),additionalActionItems=_useState12[0],setAdditionalActionItems=_useState12[1];var actionItems=[].concat(defaultActionItems,_toConsumableArray(additionalActionItems));// @ts-ignore
-var layout=getLayout(Children.count(children)===1?[children]:children);var globalWindow=window_1.window;var copyToClipboard=useCallback(function(text){return __awaiter(void 0,void 0,void 0,/*#__PURE__*/regeneratorRuntime.mark(function _callee2(){var _yield$import,createCopyToClipboardFunction;return regeneratorRuntime.wrap(function _callee2$(_context2){while(1){switch(_context2.prev=_context2.next){case 0:_context2.next=2;return import('./syntaxhighlighter-b07b042a.js');case 2:_yield$import=_context2.sent;createCopyToClipboardFunction=_yield$import.createCopyToClipboardFunction;createCopyToClipboardFunction();case 5:case"end":return _context2.stop();}}},_callee2);}));},[]);var onCopyCapture=function onCopyCapture(e){e.preventDefault();if(additionalActionItems.filter(function(item){return item.title==='Copied';}).length===0){copyToClipboard(source.props.code).then(function(){setAdditionalActionItems([].concat(_toConsumableArray(additionalActionItems),[{title:'Copied',onClick:function onClick(){}}]));globalWindow.setTimeout(function(){return setAdditionalActionItems(additionalActionItems.filter(function(item){return item.title!=='Copied';}));},1500);});}};return React__default.createElement(PreviewContainer,Object.assign({},{withSource:withSource,withToolbar:withToolbar},props,{className:previewClasses.join(' ')}),withToolbar&&React__default.createElement(PositionedToolbar,{isLoading:isLoading,border:true,zoom:function zoom(z){return setScale(scale*z);},resetZoom:function resetZoom(){return setScale(1);},storyId:getStoryId(children),baseUrl:"./iframe.html"}),React__default.createElement(ZoomContext.Provider,{value:{scale:scale}},React__default.createElement(Relative,{className:"docs-story",onCopyCapture:withSource&&onCopyCapture},React__default.createElement(ChildrenContainer,{isColumn:isColumn||!Array.isArray(children),columns:columns,layout:layout},React__default.createElement(Zoom$1.Element,{scale:scale},Array.isArray(children)?// eslint-disable-next-line react/no-array-index-key
+var layout=getLayout(Children.count(children)===1?[children]:children);var globalWindow=window_1.window;var copyToClipboard=useCallback(function(text){return __awaiter(void 0,void 0,void 0,/*#__PURE__*/regeneratorRuntime.mark(function _callee2(){var _yield$import,createCopyToClipboardFunction;return regeneratorRuntime.wrap(function _callee2$(_context2){while(1){switch(_context2.prev=_context2.next){case 0:_context2.next=2;return import('./syntaxhighlighter-b07b042a.js');case 2:_yield$import=_context2.sent;createCopyToClipboardFunction=_yield$import.createCopyToClipboardFunction;createCopyToClipboardFunction();case 5:case"end":return _context2.stop();}}},_callee2);}));},[]);var onCopyCapture=function onCopyCapture(e){
+  const selection = globalWindow.getSelection();
+  if (selection && selection.type === 'Range') {
+    return;
+  }
+  e.preventDefault();if(additionalActionItems.filter(function(item){return item.title==='Copied';}).length===0){copyToClipboard(source.props.code).then(function(){setAdditionalActionItems([].concat(_toConsumableArray(additionalActionItems),[{title:'Copied',onClick:function onClick(){}}]));globalWindow.setTimeout(function(){return setAdditionalActionItems(additionalActionItems.filter(function(item){return item.title!=='Copied';}));},1500);});}};return React__default.createElement(PreviewContainer,Object.assign({},{withSource:withSource,withToolbar:withToolbar},props,{className:previewClasses.join(' ')}),withToolbar&&React__default.createElement(PositionedToolbar,{isLoading:isLoading,border:true,zoom:function zoom(z){return setScale(scale*z);},resetZoom:function resetZoom(){return setScale(1);},storyId:getStoryId(children),baseUrl:"./iframe.html"}),React__default.createElement(ZoomContext.Provider,{value:{scale:scale}},React__default.createElement(Relative,{className:"docs-story",onCopyCapture:withSource&&onCopyCapture},React__default.createElement(ChildrenContainer,{isColumn:isColumn||!Array.isArray(children),columns:columns,layout:layout},React__default.createElement(Zoom$1.Element,{scale:scale},Array.isArray(children)?// eslint-disable-next-line react/no-array-index-key
 children.map(function(child,i){return React__default.createElement("div",{key:i},child);}):React__default.createElement("div",null,children))),React__default.createElement(ActionBar,{actionItems:actionItems}))),withSource&&expanded&&source);};var StyledPreview=styled(Preview)(function(){return{'.docs-story':{paddingTop:32,paddingBottom:40}};});var PreviewSkeleton=function PreviewSkeleton(){return React__default.createElement(StyledPreview,{isLoading:true,withToolbar:true},React__default.createElement(StorySkeleton,null));};/**
  * A specialized version of `_.map` for arrays without support for iteratee
  * shorthands.