diff --git a/CHANGELOG.md b/CHANGELOG.md index 19bb57aec99..43b57b265b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## [`master`](https://github.com/elastic/eui/tree/master) +- Added `whiteSpace ` prop to `EuiCodeBlock` ([#3103](https://github.com/elastic/eui/pull/3103)) - Added `sortMatchesBy` prop for `EuiComboBox` ([#3089](https://github.com/elastic/eui/pull/3089)) - Added `prepend` and `append` ability to `EuiFieldPassword` ([#3122](https://github.com/elastic/eui/pull/3122)) - Added `Enter` key press functionality to `EuiSuperDatePicker` ([#3048](https://github.com/elastic/eui/pull/3048)) diff --git a/src-docs/src/views/code/code_block_pre.js b/src-docs/src/views/code/code_block_pre.js new file mode 100644 index 00000000000..ec73c3b3b9e --- /dev/null +++ b/src-docs/src/views/code/code_block_pre.js @@ -0,0 +1,37 @@ +import React from 'react'; + +import { EuiCodeBlock, EuiSpacer } from '../../../../src/components'; + +export default () => ( +
+ + {`export default () => ( +
+ +
+ In this example, the whiteSpace property is set to pre. All the whitespaces will be kept as is and the text only wraps when line breaks are in the content. +
+
+ + +
+ );`} +
+ + +
+); diff --git a/src-docs/src/views/code/code_example.js b/src-docs/src/views/code/code_example.js index 8784af51d16..ac6520b9d4e 100644 --- a/src-docs/src/views/code/code_example.js +++ b/src-docs/src/views/code/code_example.js @@ -15,10 +15,14 @@ import CodeBlock from './code_block'; const codeBlockSource = require('!!raw-loader!./code_block'); const codeBlockHtml = renderToHtml(CodeBlock); const codeBlockSnippet = ` - { \`

Title

\` } +{ \`

Title

\` }
`; +import CodeBlockPre from './code_block_pre'; +const codeBlockPreSource = require('!!raw-loader!./code_block_pre'); +const codeBlockPreHtml = renderToHtml(CodeBlockPre); + export const CodeExample = { title: 'Code', sections: [ @@ -67,5 +71,29 @@ export const CodeExample = { props: { EuiCodeBlockImpl }, demo: , }, + { + title: 'CodeBlock and white-space', + source: [ + { + type: GuideSectionTypes.JS, + code: codeBlockPreSource, + }, + { + type: GuideSectionTypes.HTML, + code: codeBlockPreHtml, + }, + ], + text: ( +

+ By default, the whiteSpace property is set to{' '} + pre-wrap. This makes the text wrap when needed. You + can, however, pass pre to the{' '} + whiteSpace prop and the text won't wrap unless + line breaks are in the content. +

+ ), + props: { EuiCodeBlockImpl }, + demo: , + }, ], }; diff --git a/src/components/code/__snapshots__/_code_block.test.tsx.snap b/src/components/code/__snapshots__/_code_block.test.tsx.snap index 71853e13d0a..e639fafbf7f 100644 --- a/src/components/code/__snapshots__/_code_block.test.tsx.snap +++ b/src/components/code/__snapshots__/_code_block.test.tsx.snap @@ -5,7 +5,7 @@ exports[`EuiCodeBlockImpl block highlights javascript code, adding "js" class 1` class="euiCodeBlock euiCodeBlock--fontSmall euiCodeBlock--paddingLarge" >
     
   
+    
+      var some = 'code';
+console.log(some);
+    
+  
+ +`; + +exports[`EuiCodeBlockImpl block renders a pre block tag with a css class modifier 1`] = ` +
+
     
   
     
   
-
+    
       
         constvalue =
         'State 1'
@@ -16,7 +16,7 @@ exports[`EuiCodeBlock dynamic content updates DOM when input changes 1`] = `
 exports[`EuiCodeBlock dynamic content updates DOM when input changes 2`] = `
 "
-
+    
       
         constvalue =
         'State 2'
@@ -31,7 +31,7 @@ exports[`EuiCodeBlock props fontSize l is rendered 1`] = `
   class="euiCodeBlock euiCodeBlock--fontLarge euiCodeBlock--paddingLarge"
 >
   
     
   
     
   
     
   
     
   
     
   
     
   
     
   
     
   
     
   
     
   
     
   
      {
 
       expect(snapshotCodeBlock(component)).toMatchSnapshot();
     });
+
+    test('renders a pre block tag with a css class modifier', () => {
+      const component = mount(
+        
+          {code}
+        
+      );
+      expect(snapshotCodeBlock(component)).toMatchSnapshot();
+    });
   });
 });
diff --git a/src/components/code/_code_block.tsx b/src/components/code/_code_block.tsx
index 14ecd0993dc..14fc0016ccf 100644
--- a/src/components/code/_code_block.tsx
+++ b/src/components/code/_code_block.tsx
@@ -55,6 +55,12 @@ interface Props {
   overflowHeight?: number;
   paddingSize: PaddingSize;
   transparentBackground: boolean;
+  /**
+   * Specify how `white-space` inside the element is handled.
+   * `pre` respects line breaks/white space but doesn't force them to wrap the line
+   * `pre-wrap` respects line breaks/white space but does force them to wrap the line when necessary.
+   */
+  whiteSpace?: 'pre' | 'pre-wrap';
 }
 
 interface State {
@@ -71,6 +77,7 @@ export class EuiCodeBlockImpl extends Component {
     paddingSize: 'l',
     fontSize: 's',
     isCopyable: false,
+    whiteSpace: 'pre-wrap',
   };
 
   constructor(props: Props) {
@@ -152,6 +159,7 @@ export class EuiCodeBlockImpl extends Component {
       paddingSize,
       transparentBackground,
       isCopyable,
+      whiteSpace,
       ...otherProps
     } = this.props;
 
@@ -169,6 +177,11 @@ export class EuiCodeBlockImpl extends Component {
 
     const codeClasses = classNames('euiCodeBlock__code', language);
 
+    const preClasses = classNames('euiCodeBlock__pre', {
+      'euiCodeBlock__pre--whiteSpacePre': whiteSpace === 'pre',
+      'euiCodeBlock__pre--whiteSpacePreWrap': whiteSpace === 'pre-wrap',
+    });
+
     const optionalStyles: CSSProperties = {};
 
     if (overflowHeight) {
@@ -286,7 +299,7 @@ export class EuiCodeBlockImpl extends Component {
           
             
               
-
+                
                    {
                       this.codeFullScreen = ref;
@@ -318,7 +331,7 @@ export class EuiCodeBlockImpl extends Component {
                 
+                  className={preClasses}>
                   {codeSnippet}