From 83c3365106a297152440029c5db3a47fa71343e6 Mon Sep 17 00:00:00 2001 From: Nathan Stilwell Date: Fri, 29 Jan 2021 14:08:27 -0500 Subject: [PATCH] # cluster-ui // Truncating long queries with CSS (#179) * CRDB-2271: Truncating long queries with CSS Applying a tried and true hack using `-webkit-line-clamp` to truncate queries in the statements table to a couple of lines followed by an ellipsis. To allow a longer preview, I am applying the same fix to the tooltip, but clamping the lines to 15 (there were around 30 characters per line and design asked for ~425 characters. It's close enough). * Adding truncation to Transactions table Since statements and transactions have enough variation to not be able to make this change at the common table level, I'm adding truncation to the transactions table styles to mirror the change in the statements page table. * Adding trucation to Statement col in Sessions Adding trucation to the Statements column on the Sessions page to be consistent with how statements appear on Statements and Tranactions pages. * Truncating long app names in Statements app filter If a very long name is displayed in the Statements application filter, the name may cause the dropdown to extend outside of the view or at least beyond the table and cause excessive horizontal scrolling. To correct this I have added the `nowrap` option to the `` component inside of the Dropdown trigger. The "nowrap" prop will constrain the the text to a single line but does not offer a constraint for the width. To constrain the width I have added a local style set to a max-width of `75ch` (75 characters wide). Just a note, that I have used this opportunity to bring in the `` from `ui-components` to replace the local one here, which was the inspiration for the common component. The width and display of the menu are controlled by the Dropdown component and I didn't want to alter the display of all dropdowns that use that component. So instead I extended the dropdown component to take an additional `itemsClassname` prop to apply a class name to the element rendered for the menu items. This way I can supply another local style to constrain the width of the menu (to `80ch`) and apply text truncation. * Replacing repetitive styles with Sass mixins DRYing up the code a little with two Sass mixins: text-overflow and line-clamp. --- pkg/ui/cluster-ui/src/core/index.module.scss | 6 ++-- .../src/core/typography.module.scss | 23 ++++++++++++ pkg/ui/cluster-ui/src/dropdown/dropdown.tsx | 35 ++++++++++++------- .../src/sessions/sessionsTable.module.scss | 1 + .../src/sortedtable/table.module.scss | 4 +-- .../statementsPage/statementsPage.module.scss | 20 ++++++++++- .../src/statementsPage/statementsPage.tsx | 16 ++++++--- .../statementsTable.module.scss | 10 ++++-- .../statementsTableContent.module.scss | 7 ++-- .../transactionsCells.module.scss | 5 +-- 10 files changed, 97 insertions(+), 30 deletions(-) diff --git a/pkg/ui/cluster-ui/src/core/index.module.scss b/pkg/ui/cluster-ui/src/core/index.module.scss index 47a1ac9f854d..ed87ada626ad 100644 --- a/pkg/ui/cluster-ui/src/core/index.module.scss +++ b/pkg/ui/cluster-ui/src/core/index.module.scss @@ -1,5 +1,5 @@ -@import './typography.module'; -@import './colors.module'; +@import "./typography.module"; +@import "./colors.module"; @import "./base.module"; @import "./palette.module"; @@ -7,4 +7,4 @@ margin: 0; padding: 0; box-sizing: border-box; -} \ No newline at end of file +} diff --git a/pkg/ui/cluster-ui/src/core/typography.module.scss b/pkg/ui/cluster-ui/src/core/typography.module.scss index 3b1ccd03677f..ffd483deaaf5 100644 --- a/pkg/ui/cluster-ui/src/core/typography.module.scss +++ b/pkg/ui/cluster-ui/src/core/typography.module.scss @@ -128,3 +128,26 @@ $spacing-xx-large: 48px; line-height: $line-height--medium; font-weight: $font-weight--bold; } + +// +// Text Truncation +// + +// text-overflow - limits a line of text to a single line. If text overflows +// the container will be truncated with an ellipsis +@mixin text-overflow { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} + +// line-clamp - limits text in a container to a number of lines. If text +// overflows container past number of lines, text will be truncated with an +// ellipsis. This mixin takes a single parameter that is the number of line +// to limit text to (default is 2) +@mixin line-clamp($lines: 2) { + display: -webkit-box; + -webkit-line-clamp: $lines; + -webkit-box-orient: vertical; + overflow: hidden; +} diff --git a/pkg/ui/cluster-ui/src/dropdown/dropdown.tsx b/pkg/ui/cluster-ui/src/dropdown/dropdown.tsx index ec6dc16f1e73..a521abba4e3d 100644 --- a/pkg/ui/cluster-ui/src/dropdown/dropdown.tsx +++ b/pkg/ui/cluster-ui/src/dropdown/dropdown.tsx @@ -14,6 +14,13 @@ export interface DropdownOption { disabled?: boolean; } +export interface DropdownItemProps { + children: React.ReactNode; + value: T; + onClick: (value: T) => void; + disabled?: boolean; + className?: string; +} export interface DropdownProps { items: Array>; onChange: (item: DropdownOption["value"]) => void; @@ -22,6 +29,7 @@ export interface DropdownProps { customToggleButtonOptions?: Partial; menuPosition?: "left" | "right"; className?: string; + itemsClassname?: string; } interface DropdownState { @@ -53,13 +61,17 @@ const DropdownButton: React.FC = ({ }; function DropdownItem(props: DropdownItemProps) { - const { children, value, onClick, disabled } = props; + const { children, value, onClick, disabled, className } = props; return (
onClick(value)} - className={cx("crl-dropdown__item", { - "crl-dropdown__item--disabled": disabled, - })} + className={cx( + "crl-dropdown__item", + { + "crl-dropdown__item--disabled": disabled, + }, + className, + )} > {children}
@@ -111,7 +123,12 @@ export class Dropdown extends React.Component< }; render() { - const { items, menuPosition = "left", className } = this.props; + const { + items, + menuPosition = "left", + className, + itemsClassname, + } = this.props; const { isOpen } = this.state; const menuStyles = cx( @@ -128,6 +145,7 @@ export class Dropdown extends React.Component< onClick={this.handleItemSelection} key={idx} disabled={menuItem.disabled} + className={itemsClassname} > {menuItem.name} @@ -152,10 +170,3 @@ export class Dropdown extends React.Component< ); } } - -export interface DropdownItemProps { - children: React.ReactNode; - value: T; - onClick: (value: T) => void; - disabled?: boolean; -} diff --git a/pkg/ui/cluster-ui/src/sessions/sessionsTable.module.scss b/pkg/ui/cluster-ui/src/sessions/sessionsTable.module.scss index c3d8df2d371b..f4e07f9f0cb6 100644 --- a/pkg/ui/cluster-ui/src/sessions/sessionsTable.module.scss +++ b/pkg/ui/cluster-ui/src/sessions/sessionsTable.module.scss @@ -22,6 +22,7 @@ width: 400px; text-decoration: none; cursor: pointer; + @include line-clamp(2); &:hover { color: $colors--link; text-decoration: underline; diff --git a/pkg/ui/cluster-ui/src/sortedtable/table.module.scss b/pkg/ui/cluster-ui/src/sortedtable/table.module.scss index a7ba7a0762be..3820883dc0c4 100644 --- a/pkg/ui/cluster-ui/src/sortedtable/table.module.scss +++ b/pkg/ui/cluster-ui/src/sortedtable/table.module.scss @@ -1,4 +1,4 @@ -@import '../core/index.module.scss'; +@import "../core/index.module.scss"; $table-cell-border: 1px solid $colors--neutral-2; $stats-table-td--fg: $colors--neutral-6; @@ -19,7 +19,7 @@ $stats-table-tr--bg: $colors--neutral-0; border-right: 1px solid $colors--neutral-2; width: 250px; } - + &__row { &--body { letter-spacing: 0.33px; diff --git a/pkg/ui/cluster-ui/src/statementsPage/statementsPage.module.scss b/pkg/ui/cluster-ui/src/statementsPage/statementsPage.module.scss index b0a645072195..845e3ce3b71f 100644 --- a/pkg/ui/cluster-ui/src/statementsPage/statementsPage.module.scss +++ b/pkg/ui/cluster-ui/src/statementsPage/statementsPage.module.scss @@ -7,7 +7,8 @@ margin-bottom: 7px; } -.cl-count-title, .last-cleared-title { +.cl-count-title, +.last-cleared-title { font-family: $font-family--base; font-size: 14px; padding: 0px; @@ -51,3 +52,20 @@ h2.base-heading { flex-grow: 0; width: 100%; } + +.app-filter-dropdown { + /* + we are truncating the text in the filter, + but need to constrain to a width + */ + max-width: 75ch; +} + +.app-filter-dropdown-item { + /* + Truncating and constrainging the width of the + items in the app filter dropdown + */ + max-width: 80ch; + @include text-overflow; +} diff --git a/pkg/ui/cluster-ui/src/statementsPage/statementsPage.tsx b/pkg/ui/cluster-ui/src/statementsPage/statementsPage.tsx index 06b4b2c84606..d9e0006aa3a8 100644 --- a/pkg/ui/cluster-ui/src/statementsPage/statementsPage.tsx +++ b/pkg/ui/cluster-ui/src/statementsPage/statementsPage.tsx @@ -5,6 +5,8 @@ import moment from "moment"; import Helmet from "react-helmet"; import classNames from "classnames/bind"; +import { Text } from "@cockroachlabs/ui-components"; + import { Dropdown, Loading, @@ -14,8 +16,6 @@ import { Search, Pagination, ResultsPerPageLabel, - Text, - TextTypes, } from "src/index"; import { DATE_FORMAT, appAttr, getMatchParamByName } from "src/util"; import { @@ -253,8 +253,16 @@ export class StatementsPage extends React.Component< /> - - + + {`App: ${decodeURIComponent(currentOption.name)}`} diff --git a/pkg/ui/cluster-ui/src/statementsTable/statementsTable.module.scss b/pkg/ui/cluster-ui/src/statementsTable/statementsTable.module.scss index 5ee116a57eac..ea15d2829f62 100644 --- a/pkg/ui/cluster-ui/src/statementsTable/statementsTable.module.scss +++ b/pkg/ui/cluster-ui/src/statementsTable/statementsTable.module.scss @@ -1,4 +1,4 @@ -@import 'src/core/index.module'; +@import "src/core/index.module"; .statements-table__col-time { white-space: nowrap; @@ -18,13 +18,16 @@ } } -.statements-table__col-rows, .statements-table__col-latency { +.statements-table__col-rows, +.statements-table__col-latency { &--bar-chart { min-width: 150px; } } -.statements-table__col-count, .statements-table__col-retries, .statements-table__col-rows { +.statements-table__col-count, +.statements-table__col-retries, +.statements-table__col-rows { &--bar-chart { margin-left: 0; @@ -42,5 +45,6 @@ width: 400px; div { font-size: $font-size--small; + @include line-clamp(2); } } diff --git a/pkg/ui/cluster-ui/src/statementsTable/statementsTableContent.module.scss b/pkg/ui/cluster-ui/src/statementsTable/statementsTableContent.module.scss index 2cf3b639aa86..44d09bc8d6df 100644 --- a/pkg/ui/cluster-ui/src/statementsTable/statementsTableContent.module.scss +++ b/pkg/ui/cluster-ui/src/statementsTable/statementsTableContent.module.scss @@ -1,4 +1,4 @@ -@import 'src/core/index.module'; +@import "src/core/index.module"; .cl-table-link__description { font-size: $font-size--small; @@ -6,6 +6,7 @@ color: $colors--neutral-1; white-space: pre-wrap; margin-bottom: 0; + @include line-clamp(15); } .cl-table-link__statement-tooltip--fixed-width { @@ -54,7 +55,7 @@ align-items: center; .activate-diagnostic-link { - width: auto!important; + width: auto !important; } .activate-diagnostic-dropdown { @@ -69,4 +70,4 @@ text-decoration: none; } } -} \ No newline at end of file +} diff --git a/pkg/ui/cluster-ui/src/transactionsTable/transactionsCells/transactionsCells.module.scss b/pkg/ui/cluster-ui/src/transactionsTable/transactionsCells/transactionsCells.module.scss index 712b6b1d9aa0..32d75af66402 100644 --- a/pkg/ui/cluster-ui/src/transactionsTable/transactionsCells/transactionsCells.module.scss +++ b/pkg/ui/cluster-ui/src/transactionsTable/transactionsCells/transactionsCells.module.scss @@ -1,4 +1,4 @@ -@import '../../core/index.module.scss'; +@import "../../core/index.module.scss"; .hover-area { white-space: pre-line; @@ -6,9 +6,10 @@ font-family: $font-family--monospace; font-size: $font-size--small; color: $colors--neutral-6; + @include line-clamp(2); } .hover-area:hover { text-decoration: underline; color: #0788ff; -} \ No newline at end of file +}