-
Notifications
You must be signed in to change notification settings - Fork 842
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
Add display, descriptionWidth, textWrap and isInvalid props to EuiExpression #3467
Changes from 32 commits
c4d93cd
faaa6ad
23dad35
f03e8fe
0f13450
1bf1d04
60fa604
efe0e00
eb52280
72b2918
dfc860a
89d3992
d256cc7
cb0d1aa
cb9ebd1
c4e396b
1caac1a
a392e3e
6e7585b
1c1b811
36bb3ec
b1e01dc
fc1ddf7
4128407
b606ecc
5cc964a
4e583f8
f6d39f2
d15a4b4
52dec78
3e21df3
e0209b0
85b20b6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,208 @@ | ||||||||
import React, { useState } from 'react'; | ||||||||
|
||||||||
import { | ||||||||
EuiPopoverTitle, | ||||||||
EuiPopover, | ||||||||
EuiSelect, | ||||||||
EuiComboBox, | ||||||||
EuiExpression, | ||||||||
EuiTitle, | ||||||||
EuiSpacer, | ||||||||
} from '../../../../src/components'; | ||||||||
|
||||||||
export default () => { | ||||||||
const [example1, setExample1] = useState({ | ||||||||
isOpen: false, | ||||||||
value: ( | ||||||||
<div> | ||||||||
<p>.kibana_task_manager,</p> | ||||||||
<p>kibana_sample_data_ecommerce</p> | ||||||||
</div> | ||||||||
), | ||||||||
}); | ||||||||
|
||||||||
const [example2, setExample2] = useState({ | ||||||||
isOpen: false, | ||||||||
value: 'count()', | ||||||||
}); | ||||||||
|
||||||||
const options = [ | ||||||||
{ | ||||||||
label: '.kibana_task_manager', | ||||||||
}, | ||||||||
{ | ||||||||
label: 'kibana_sample_data_ecommerce', | ||||||||
}, | ||||||||
{ | ||||||||
label: '.kibana-event-log-8.0.0-000001', | ||||||||
}, | ||||||||
{ | ||||||||
label: 'kibana_sample_data_flights', | ||||||||
}, | ||||||||
{ | ||||||||
label: '.kibana-event-log-8.0.0', | ||||||||
}, | ||||||||
]; | ||||||||
|
||||||||
const [selectedOptions, setSelected] = useState([options[0], options[1]]); | ||||||||
|
||||||||
const openExample1 = () => { | ||||||||
setExample1({ | ||||||||
...example1, | ||||||||
isOpen: !example1.isOpen, | ||||||||
}); | ||||||||
setExample2({ | ||||||||
...example2, | ||||||||
}); | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
}; | ||||||||
|
||||||||
const closeExample1 = () => { | ||||||||
setExample1({ | ||||||||
...example1, | ||||||||
isOpen: false, | ||||||||
}); | ||||||||
}; | ||||||||
|
||||||||
const openExample2 = () => { | ||||||||
setExample1({ | ||||||||
...example1, | ||||||||
}); | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
setExample2({ | ||||||||
...example2, | ||||||||
isOpen: !example2.isOpen, | ||||||||
}); | ||||||||
}; | ||||||||
|
||||||||
const closeExample2 = () => { | ||||||||
setExample2({ | ||||||||
...example2, | ||||||||
isOpen: false, | ||||||||
}); | ||||||||
}; | ||||||||
|
||||||||
const changeExample2 = e => { | ||||||||
setExample2({ | ||||||||
value: e.target.value, | ||||||||
isOpen: false, | ||||||||
}); | ||||||||
}; | ||||||||
|
||||||||
const onChange = selectedOptions => { | ||||||||
setSelected(selectedOptions); | ||||||||
const indices = selectedOptions.map((s, index) => { | ||||||||
return ( | ||||||||
<p key={index}> | ||||||||
{s.label} | ||||||||
{index < selectedOptions.length - 1 ? ',' : null} | ||||||||
</p> | ||||||||
); | ||||||||
}); | ||||||||
setExample1({ | ||||||||
...example1, | ||||||||
value: indices, | ||||||||
}); | ||||||||
}; | ||||||||
|
||||||||
const renderPopover1 = () => ( | ||||||||
<div style={{ width: 300 }}> | ||||||||
<EuiPopoverTitle>INDICES</EuiPopoverTitle> | ||||||||
<EuiComboBox | ||||||||
placeholder="Select one or more indices" | ||||||||
options={options} | ||||||||
selectedOptions={selectedOptions} | ||||||||
onChange={onChange} | ||||||||
isClearable={true} | ||||||||
data-test-subj="demoComboBox" | ||||||||
/> | ||||||||
</div> | ||||||||
); | ||||||||
|
||||||||
const renderPopover2 = () => ( | ||||||||
<div style={{ width: 150 }}> | ||||||||
<EuiPopoverTitle>WHEN</EuiPopoverTitle> | ||||||||
<EuiSelect | ||||||||
compressed | ||||||||
value={example2.value} | ||||||||
onChange={changeExample2} | ||||||||
options={[ | ||||||||
{ | ||||||||
value: 'count()', | ||||||||
text: 'count()', | ||||||||
}, | ||||||||
{ | ||||||||
value: 'sum()', | ||||||||
text: 'sum()', | ||||||||
}, | ||||||||
{ | ||||||||
value: 'min()', | ||||||||
text: 'min()', | ||||||||
}, | ||||||||
{ value: 'max()', text: 'max()' }, | ||||||||
]} | ||||||||
/> | ||||||||
</div> | ||||||||
); | ||||||||
|
||||||||
return ( | ||||||||
<div style={{ maxWidth: 500 }}> | ||||||||
<EuiPopover | ||||||||
id="columnsPopover1" | ||||||||
button={ | ||||||||
<EuiExpression | ||||||||
description="indices" | ||||||||
display="columns" | ||||||||
value={example1.value} | ||||||||
isInvalid={ | ||||||||
selectedOptions && selectedOptions.length > 0 ? false : true | ||||||||
} | ||||||||
isActive={example1.isOpen} | ||||||||
onClick={openExample1} | ||||||||
/> | ||||||||
} | ||||||||
isOpen={example1.isOpen} | ||||||||
closePopover={closeExample1} | ||||||||
ownFocus | ||||||||
display="block" | ||||||||
panelPaddingSize="s" | ||||||||
anchorPosition="downLeft"> | ||||||||
{renderPopover1()} | ||||||||
</EuiPopover> | ||||||||
|
||||||||
<EuiPopover | ||||||||
id="columnsPopover2" | ||||||||
panelPaddingSize="s" | ||||||||
button={ | ||||||||
<EuiExpression | ||||||||
description="when" | ||||||||
display="columns" | ||||||||
value={example2.value} | ||||||||
isActive={example2.isOpen} | ||||||||
onClick={openExample2} | ||||||||
/> | ||||||||
} | ||||||||
isOpen={example2.isOpen} | ||||||||
closePopover={closeExample2} | ||||||||
ownFocus | ||||||||
display="block" | ||||||||
anchorPosition="downLeft"> | ||||||||
{renderPopover2()} | ||||||||
</EuiPopover> | ||||||||
<EuiExpression | ||||||||
display="columns" | ||||||||
description="Except" | ||||||||
value="kibana_sample_data_ky_counties" | ||||||||
/> | ||||||||
<EuiSpacer /> | ||||||||
<EuiTitle size="xxs"> | ||||||||
<h3>Description width at 50px</h3> | ||||||||
</EuiTitle> | ||||||||
<EuiExpression | ||||||||
description="join" | ||||||||
display="columns" | ||||||||
descriptionWidth={50} | ||||||||
value="kibana_sample_data_ky_avl" | ||||||||
onClick={() => {}} | ||||||||
/> | ||||||||
</div> | ||||||||
); | ||||||||
}; |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -12,7 +12,7 @@ import Expression from './expression'; | |||||
const expressionSource = require('!!raw-loader!./expression'); | ||||||
const expressionHtml = renderToHtml(Expression); | ||||||
const expressionSnippet = `<EuiExpression | ||||||
description="description" | ||||||
description={description} | ||||||
value={value} | ||||||
isActive={isActive} | ||||||
onClick={handleClick} | ||||||
|
@@ -22,7 +22,7 @@ import Colors from './colors'; | |||||
const colorSource = require('!!raw-loader!./colors'); | ||||||
const colorHtml = renderToHtml(Colors); | ||||||
const colorSnippet = `<EuiExpression | ||||||
description="description" | ||||||
description={description} | ||||||
value={value} | ||||||
color="primary" | ||||||
/>`; | ||||||
|
@@ -32,17 +32,44 @@ const stringingSource = require('!!raw-loader!./stringing'); | |||||
const stringingHtml = renderToHtml(Stringing); | ||||||
const stringingSnippet = `<div> | ||||||
<EuiExpression | ||||||
description="description1" | ||||||
description={description1} | ||||||
value={value1} | ||||||
onClick={handleClick1} | ||||||
/> | ||||||
<EuiExpression | ||||||
description="description2" | ||||||
description={description2} | ||||||
value={value2} | ||||||
onClick={handleClick2} | ||||||
/> | ||||||
</div>`; | ||||||
|
||||||
import Columns from './columns'; | ||||||
const columnsSource = require('!!raw-loader!./columns'); | ||||||
const columnsHtml = renderToHtml(Columns); | ||||||
const columnsSnippet = `<EuiExpression | ||||||
description={description} | ||||||
display="columns" | ||||||
value={value} | ||||||
/>`; | ||||||
|
||||||
import Invalid from './invalid'; | ||||||
const invalidSource = require('!!raw-loader!./invalid'); | ||||||
const invalidHtml = renderToHtml(Invalid); | ||||||
const invalidSnippet = `<EuiExpression | ||||||
description={description} | ||||||
isInvalid | ||||||
value={value} | ||||||
/>`; | ||||||
|
||||||
import Truncate from './truncate'; | ||||||
const truncateSource = require('!!raw-loader!./truncate'); | ||||||
const truncateHtml = renderToHtml(Truncate); | ||||||
const truncateSnippet = `<EuiExpression | ||||||
description={description} | ||||||
value={value} | ||||||
textWrap="truncate" | ||||||
/>`; | ||||||
|
||||||
export const ExpressionExample = { | ||||||
title: 'Expression', | ||||||
sections: [ | ||||||
|
@@ -114,5 +141,89 @@ export const ExpressionExample = { | |||||
snippet: stringingSnippet, | ||||||
demo: <Stringing />, | ||||||
}, | ||||||
{ | ||||||
title: 'Column display', | ||||||
source: [ | ||||||
{ | ||||||
type: GuideSectionTypes.JS, | ||||||
code: columnsSource, | ||||||
}, | ||||||
{ | ||||||
type: GuideSectionTypes.HTML, | ||||||
code: columnsHtml, | ||||||
}, | ||||||
], | ||||||
text: ( | ||||||
<div> | ||||||
<p> | ||||||
There might be cases where displaying multiple{' '} | ||||||
<strong>EuiExpression</strong>s in a paragraph is not ideal. For | ||||||
example, when both the <EuiCode>description</EuiCode> and the{' '} | ||||||
<EuiCode>value</EuiCode> are variable or when their text is quite | ||||||
long. To use a column display instead, pass{' '} | ||||||
<EuiCode language="ts">{'display="columns"'}</EuiCode>. | ||||||
</p> | ||||||
<p> | ||||||
In column display, each expression is its own line and the{' '} | ||||||
<EuiCode>description</EuiCode> column is aligned to the right. The | ||||||
default width for the <EuiCode>description</EuiCode> is 20%, but you | ||||||
can customize this with the | ||||||
<EuiCode>descriptionWidth</EuiCode> prop. When displaying a group of{' '} | ||||||
<strong>EuiExpression</strong>s, make sure to set the same width for | ||||||
all descriptions. | ||||||
</p> | ||||||
</div> | ||||||
), | ||||||
snippet: columnsSnippet, | ||||||
demo: <Columns />, | ||||||
}, | ||||||
{ | ||||||
title: 'Invalid state', | ||||||
source: [ | ||||||
{ | ||||||
type: GuideSectionTypes.JS, | ||||||
code: invalidSource, | ||||||
}, | ||||||
{ | ||||||
type: GuideSectionTypes.HTML, | ||||||
code: invalidHtml, | ||||||
}, | ||||||
], | ||||||
text: ( | ||||||
<p> | ||||||
Set <EuiCode>isInvalid</EuiCode> to true to display{' '} | ||||||
<strong>EuiExpression</strong>'s error state. This state will | ||||||
override the <EuiCode>color</EuiCode> prop with danger. | ||||||
</p> | ||||||
), | ||||||
snippet: invalidSnippet, | ||||||
demo: <Invalid />, | ||||||
}, | ||||||
{ | ||||||
title: 'Truncate text', | ||||||
source: [ | ||||||
{ | ||||||
type: GuideSectionTypes.JS, | ||||||
code: truncateSource, | ||||||
}, | ||||||
{ | ||||||
type: GuideSectionTypes.HTML, | ||||||
code: truncateHtml, | ||||||
}, | ||||||
], | ||||||
text: ( | ||||||
<p> | ||||||
To truncate <strong>EuiExpression</strong>'s content, pass{' '} | ||||||
<EuiCode>truncate</EuiCode> to the <EuiCode>textWrap</EuiCode> prop. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
Text truncation only works properly if the prop types of{' '} | ||||||
<EuiCode>description</EuiCode> and <EuiCode>value</EuiCode> are | ||||||
strings. If you're using nodes, use the{' '} | ||||||
<EuiCode>.eui-textTruncate</EuiCode> | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
utility class on all their sub-children. | ||||||
</p> | ||||||
), | ||||||
snippet: truncateSnippet, | ||||||
demo: <Truncate />, | ||||||
}, | ||||||
], | ||||||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import React from 'react'; | ||
|
||
import { EuiExpression, EuiSpacer } from '../../../../src/components'; | ||
|
||
export default () => ( | ||
<div> | ||
<EuiExpression | ||
onClick={() => {}} | ||
description="sort by" | ||
value="count" | ||
isInvalid | ||
/> | ||
<EuiSpacer /> | ||
<div style={{ maxWidth: 220 }}> | ||
<EuiExpression | ||
description="email" | ||
display="columns" | ||
isInvalid | ||
value="example@mail." | ||
onClick={() => {}} | ||
/> | ||
</div> | ||
</div> | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you need this
div
, but if you do, it gets removed if you change the selected options, so you need to add it to theonChange
function as well. You can simply change it to a fragment<></>