Skip to content

Commit

Permalink
Add storybook for Code Editor (#58900)
Browse files Browse the repository at this point in the history
* Add storybook for code editor component

* Add dark mode story

* Update code editor README with storybook instructions

Co-authored-by: Elastic Machine <[email protected]>
  • Loading branch information
poffdeluxe and elasticmachine authored Mar 3, 2020
1 parent cc792e1 commit 2c7d13d
Show file tree
Hide file tree
Showing 4 changed files with 267 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/dev/storybook/aliases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
export const storybookAliases = {
apm: 'x-pack/legacy/plugins/apm/scripts/storybook.js',
canvas: 'x-pack/legacy/plugins/canvas/scripts/storybook_new.js',
codeeditor: 'src/plugins/kibana_react/public/code_editor/scripts/storybook.ts',
drilldowns: 'x-pack/plugins/drilldowns/scripts/storybook.js',
embeddable: 'src/plugins/embeddable/scripts/storybook.js',
infra: 'x-pack/legacy/plugins/infra/scripts/storybook.js',
Expand Down
7 changes: 5 additions & 2 deletions src/plugins/kibana_react/public/code_editor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ This editor component allows easy access to:
* Function signature widget
* [Hover widget](https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-hover-provider-example)

[_TODO: Examples of each_](https://github.com/elastic/kibana/issues/43812)
The Monaco editor doesn't automatically resize the editor area on window or container resize so this component includes a [resize detector](https://github.com/maslianok/react-resize-detector) to cause the Monaco editor to re-layout and adjust its size when the window or container size changes

The Monaco editor doesn't automatically resize the editor area on window or container resize so this component includes a [resize detector](https://github.com/maslianok/react-resize-detector) to cause the Monaco editor to re-layout and adjust its size when the window or container size changes
## Storybook Examples
To run the CodeEditor storybook, from the root kibana directory, run `yarn storybook codeeditor`

All stories for the component live in `code_editor.examples.tsx`
235 changes: 235 additions & 0 deletions src/plugins/kibana_react/public/code_editor/code_editor.examples.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { action } from '@storybook/addon-actions';
import { storiesOf } from '@storybook/react';
import React from 'react';
import { monaco as monacoEditor } from '@kbn/ui-shared-deps/monaco';
import { CodeEditor } from './code_editor';

// A sample language definition with a few example tokens
// Taken from https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-custom-languages
const simpleLogLang: monacoEditor.languages.IMonarchLanguage = {
tokenizer: {
root: [
[/\[error.*/, 'constant'],
[/\[notice.*/, 'variable'],
[/\[info.*/, 'string'],
[/\[[a-zA-Z 0-9:]+\]/, 'tag'],
],
},
};

monacoEditor.languages.register({ id: 'loglang' });
monacoEditor.languages.setMonarchTokensProvider('loglang', simpleLogLang);

const logs = `[Sun Mar 7 20:54:27 2004] [notice] [client xx.xx.xx.xx] This is a notice!
[Sun Mar 7 20:58:27 2004] [info] [client xx.xx.xx.xx] (104)Connection reset by peer: client stopped connection before send body completed
[Sun Mar 7 21:16:17 2004] [error] [client xx.xx.xx.xx] File does not exist: /home/httpd/twiki/view/Main/WebHome
`;

storiesOf('CodeEditor', module)
.addParameters({
info: {
// CodeEditor has no PropTypes set so this table will show up
// as blank. I'm just disabling it to reduce confusion
propTablesExclude: [CodeEditor],
},
})
.add(
'default',
() => (
<div>
<CodeEditor
languageId="plaintext"
height={250}
value="Hello!"
onChange={action('onChange')}
/>
</div>
),
{
info: {
text: 'Plaintext Monaco Editor',
},
}
)
.add(
'dark mode',
() => (
<div>
<CodeEditor
languageId="plaintext"
height={250}
value="Hello!"
onChange={action('onChange')}
useDarkTheme={true}
/>
</div>
),
{
info: {
text: 'The dark theme is automatically used when dark mode is enabled in Kibana',
},
}
)
.add(
'custom log language',
() => (
<div>
<CodeEditor languageId="loglang" height={250} value={logs} onChange={action('onChange')} />
</div>
),
{
info: {
text:
'Custom language example. Language definition taken from [here](https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-custom-languages)',
},
}
)
.add(
'hide minimap',
() => (
<div>
<CodeEditor
languageId="loglang"
height={250}
value={logs}
onChange={action('onChange')}
options={{
minimap: {
enabled: false,
},
}}
/>
</div>
),
{
info: {
text: 'The minimap (on left side of editor) can be disabled to save space',
},
}
)
.add(
'suggestion provider',
() => {
const provideSuggestions = (
model: monacoEditor.editor.ITextModel,
position: monacoEditor.Position,
context: monacoEditor.languages.CompletionContext
) => {
const wordRange = new monacoEditor.Range(
position.lineNumber,
position.column,
position.lineNumber,
position.column
);

return {
suggestions: [
{
label: 'Hello, World',
kind: monacoEditor.languages.CompletionItemKind.Variable,
documentation: {
value: '*Markdown* can be used in autocomplete help',
isTrusted: true,
},
insertText: 'Hello, World',
range: wordRange,
},
{
label: 'You know, for search',
kind: monacoEditor.languages.CompletionItemKind.Variable,
documentation: { value: 'Thanks `Monaco`', isTrusted: true },
insertText: 'You know, for search',
range: wordRange,
},
],
};
};

return (
<div>
<CodeEditor
languageId="loglang"
height={250}
value={logs}
onChange={action('onChange')}
suggestionProvider={{
triggerCharacters: ['.'],
provideCompletionItems: provideSuggestions,
}}
options={{
wordBasedSuggestions: false,
quickSuggestions: true,
}}
/>
</div>
);
},
{
info: {
text: 'Example suggestion provider is triggered by the `.` character',
},
}
)
.add(
'hover provider',
() => {
const provideHover = (
model: monacoEditor.editor.ITextModel,
position: monacoEditor.Position
) => {
const word = model.getWordAtPosition(position);

if (!word) {
return {
contents: [],
};
}

return {
contents: [
{
value: `You're hovering over **${word.word}**`,
},
],
};
};

return (
<div>
<CodeEditor
languageId="loglang"
height={250}
value={logs}
onChange={action('onChange')}
hoverProvider={{
provideHover,
}}
/>
</div>
);
},
{
info: {
text: 'Hover dialog example can be triggered by hovering over a word',
},
}
);
26 changes: 26 additions & 0 deletions src/plugins/kibana_react/public/code_editor/scripts/storybook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { join } from 'path';

// eslint-disable-next-line
require('@kbn/storybook').runStorybookCli({
name: 'code-editor',
storyGlobs: [join(__dirname, '..', '*.examples.tsx')],
});

0 comments on commit 2c7d13d

Please sign in to comment.