github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/ui/src/views/shared/components/expandableString/index.tsx (about) 1 // Copyright 2018 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 import _ from "lodash"; 12 import React from "react"; 13 14 import { trustIcon } from "src/util/trust"; 15 16 import collapseIcon from "!!raw-loader!assets/collapse.svg"; 17 import expandIcon from "!!raw-loader!assets/expand.svg"; 18 19 import "./expandable.styl"; 20 21 const truncateLength = 50; 22 23 interface ExpandableStringProps { 24 short?: string; 25 long: string; 26 } 27 28 interface ExpandableStringState { 29 expanded: boolean; 30 } 31 32 // ExpandableString displays a short string with a clickable ellipsis. When 33 // clicked, the component displays long. If short is not specified, it uses 34 // the first 50 chars of long. 35 export class ExpandableString extends React.Component<ExpandableStringProps, ExpandableStringState> { 36 state: ExpandableStringState = { 37 expanded: false, 38 }; 39 40 onClick = (ev: any) => { 41 ev.preventDefault(); 42 this.setState({ expanded: !this.state.expanded }); 43 } 44 45 renderText(expanded: boolean) { 46 if (expanded) { 47 return ( 48 <span className="expandable__text expandable__text--expanded">{ this.props.long }</span> 49 ); 50 } 51 52 const short = this.props.short || this.props.long.substr(0, truncateLength).trim(); 53 return ( 54 <span className="expandable__text">{ short } …</span> 55 ); 56 } 57 58 render() { 59 const { short, long } = this.props; 60 61 const neverCollapse = _.isNil(short) && long.length <= truncateLength + 2; 62 if (neverCollapse) { 63 return <span className="expandable__long">{ this.props.long }</span>; 64 } 65 66 const { expanded } = this.state; 67 const icon = expanded ? collapseIcon : expandIcon; 68 return ( 69 <div className="expandable" onClick={ this.onClick }> 70 <span className="expandable__long">{ this.renderText(expanded) }</span> 71 <span className="expandable__icon" dangerouslySetInnerHTML={ trustIcon(icon) } /> 72 </div> 73 ); 74 } 75 }