fix: Table reskinning (#17228)

* update rich text editor styles

* fix disalbed text  color

* add border

* fix gaps and borders in json form

* fix disabled state

* fix checkbox disabled state color on checkbox + font size of title in json

* fix pagination arrows

* update list + modal

* update tabs widget

* fix border color

* fix pagination styles

* fix font weight

* update colors

* update colors

* fix table hidden header

* add config for variant

* add check header border

* fix hover colors

* fix hover colors

* add fixes for feedbacks from dilip

* move cell borders

* move cell borders

* update label

* add dilip feedback fixes

* remove unused import

* fix font in filter popup

* fix margin and datepicker getting cut off

* table disabled state for header input

* fix icon color

* fix cypress tests
This commit is contained in:
Pawan Kumar 2022-10-14 10:23:31 +05:30 committed by GitHub
parent 01f2fac326
commit 5ab8e57e0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 546 additions and 177 deletions

View File

@ -321,7 +321,7 @@ describe("Table Widget V2 property pane feature validation", function() {
"0", "0",
"0", "0",
"background", "background",
"rgb(126, 34, 206) none repeat scroll 0% 0% / auto padding-box border-box", "rgb(113, 30, 184) none repeat scroll 0% 0% / auto padding-box border-box",
true, true,
); );
// Changing Cell backgroud color to PURPLE and validate using JS // Changing Cell backgroud color to PURPLE and validate using JS
@ -332,7 +332,7 @@ describe("Table Widget V2 property pane feature validation", function() {
"0", "0",
"0", "0",
"background", "background",
"rgb(128, 0, 128) none repeat scroll 0% 0% / auto padding-box border-box", "rgb(102, 0, 102) none repeat scroll 0% 0% / auto padding-box border-box",
true, true,
); );
// close property pane // close property pane

View File

@ -93,7 +93,7 @@ describe("Checkbox column type funtionality test", () => {
cy.get(selector + " div").should( cy.get(selector + " div").should(
"have.css", "have.css",
"background-color", "background-color",
"rgb(128, 0, 128)", "rgb(102, 0, 102)",
); );
}); });
}); });

View File

@ -93,7 +93,7 @@ describe("Switch column type funtionality test", () => {
cy.get(selector + " div").should( cy.get(selector + " div").should(
"have.css", "have.css",
"background-color", "background-color",
"rgb(128, 0, 128)", "rgb(102, 0, 102)",
); );
}); });
}); });

View File

@ -16,6 +16,7 @@ export type PopperProps = {
parentElement?: Element | null; parentElement?: Element | null;
zIndex: number; zIndex: number;
isOpen: boolean; isOpen: boolean;
borderRadius?: string;
themeMode?: ThemeMode; themeMode?: ThemeMode;
targetNode?: Element; targetNode?: Element;
children: JSX.Element | null; children: JSX.Element | null;
@ -31,6 +32,7 @@ export type PopperProps = {
isDraggable?: boolean; isDraggable?: boolean;
disablePopperEvents?: boolean; disablePopperEvents?: boolean;
cypressSelectorDragHandle?: string; cypressSelectorDragHandle?: string;
portalContainer?: Element;
position?: { position?: {
top: number; top: number;
left: number; left: number;
@ -39,9 +41,12 @@ export type PopperProps = {
// DraggableNode?: any; // DraggableNode?: any;
}; };
const PopperWrapper = styled.div<{ zIndex: number }>` const PopperWrapper = styled.div<{ zIndex: number; borderRadius?: string }>`
z-index: ${(props) => props.zIndex}; z-index: ${(props) => props.zIndex};
position: absolute; position: absolute;
border-radius: ${(props) => props.borderRadius || "0"};
box-shadow: 0 6px 20px 0px rgba(0, 0, 0, 0.15);
overflow: hidden;
`; `;
const DragHandleBlock = styled.div` const DragHandleBlock = styled.div`
@ -178,10 +183,14 @@ export default (props: PopperProps) => {
]); ]);
return createPortal( return createPortal(
props.isOpen && ( props.isOpen && (
<PopperWrapper ref={contentRef} zIndex={props.zIndex}> <PopperWrapper
borderRadius={props.borderRadius}
ref={contentRef}
zIndex={props.zIndex}
>
{props.children} {props.children}
</PopperWrapper> </PopperWrapper>
), ),
document.body, props.portalContainer ? props.portalContainer : document.body,
); );
}; };

View File

@ -31,7 +31,10 @@ export const DropdownTrigger = styled.div<{ skin: Skin }>`
} }
} }
`; `;
export const DropdownContent = styled.div<{ skin: Skin }>` export const DropdownContent = styled.div<{
skin: Skin;
borderRadius?: string;
}>`
&&& * { &&& * {
font-size: ${(props) => props.theme.fontSizes[3]}px; font-size: ${(props) => props.theme.fontSizes[3]}px;
} }
@ -40,6 +43,7 @@ export const DropdownContent = styled.div<{ skin: Skin }>`
background: ${(props) => props.theme.dropdown[props.skin].background}; background: ${(props) => props.theme.dropdown[props.skin].background};
max-height: 300px; max-height: 300px;
overflow-y: auto; overflow-y: auto;
border-radius: ${(props) => `min(0.375rem, ${props.borderRadius || "0"})`};
`; `;
export const DropdownContentSection = styled.div<{ export const DropdownContentSection = styled.div<{

View File

@ -1,5 +1,5 @@
import React, { ReactNode } from "react"; import React, { ReactNode } from "react";
import { withTheme } from "styled-components"; import { createGlobalStyle, withTheme } from "styled-components";
import { import {
Popover, Popover,
IconName, IconName,
@ -49,9 +49,24 @@ export type CustomizedDropdownProps = {
openOnHover?: boolean; openOnHover?: boolean;
usePortal?: boolean; usePortal?: boolean;
skin?: Skin; skin?: Skin;
borderRadius?: string;
customizedDropdownId?: string;
modifiers?: IPopoverSharedProps["modifiers"]; modifiers?: IPopoverSharedProps["modifiers"];
}; };
const PopoverStyles = createGlobalStyle<{
id?: string;
borderRadius?: string;
}>`
${({ borderRadius, id }) => `
.${id}.${Classes.POPOVER} {
border-radius: min(${borderRadius}, 0.375rem);
box-shadow: 0 6px 20px 0px rgba(0, 0, 0, 0.15);
overflow: hidden;
}
`}
`;
export const getIcon = (icon?: string | MaybeElement, intent?: Intent) => { export const getIcon = (icon?: string | MaybeElement, intent?: Intent) => {
if (icon && typeof icon === "string") { if (icon && typeof icon === "string") {
if (MenuIcons[icon]) { if (MenuIcons[icon]) {
@ -133,6 +148,7 @@ export function CustomizedDropdown(
</DropdownContentSection> </DropdownContentSection>
)); ));
return ( return (
<>
<Popover <Popover
enforceFocus={false} enforceFocus={false}
interactionKind={ interactionKind={
@ -147,6 +163,7 @@ export function CustomizedDropdown(
props.onCloseDropDown(); props.onCloseDropDown();
} }
}} }}
popoverClassName={props.customizedDropdownId}
position={ position={
getDirectionBased.POPPER_POSITION( getDirectionBased.POPPER_POSITION(
props.openDirection, props.openDirection,
@ -154,8 +171,15 @@ export function CustomizedDropdown(
} }
> >
<DropdownTrigger skin={skin}>{trigger}</DropdownTrigger> <DropdownTrigger skin={skin}>{trigger}</DropdownTrigger>
<DropdownContent skin={skin}>{content}</DropdownContent> <DropdownContent borderRadius={props.borderRadius} skin={skin}>
{content}
</DropdownContent>
</Popover> </Popover>
<PopoverStyles
borderRadius={props.borderRadius}
id={props.customizedDropdownId}
/>
</>
); );
} }

View File

@ -24,7 +24,7 @@
--wds-color-icon: #858282; --wds-color-icon: #858282;
--wds-color-icon-disabled: #A9A7A7; --wds-color-icon-disabled: #A9A7A7;
--wds-color-hover: #4B4848; --wds-color-icon-hover: #4B4848;
--wds-color-text: #090707; --wds-color-text: #090707;
--wds-color-text-danger: #D91921; --wds-color-text-danger: #D91921;

View File

@ -108,6 +108,7 @@ export interface ButtonStyleProps {
buttonVariant?: ButtonVariant; buttonVariant?: ButtonVariant;
dimension?: number; dimension?: number;
hasOnClickAction?: boolean; hasOnClickAction?: boolean;
compactMode?: string;
} }
export const StyledButton = styled((props) => ( export const StyledButton = styled((props) => (
@ -119,16 +120,25 @@ export const StyledButton = styled((props) => (
"boxShadow", "boxShadow",
"dimension", "dimension",
"hasOnClickAction", "hasOnClickAction",
"compactMode",
])} ])}
/> />
))<ThemeProp & ButtonStyleProps>` ))<ThemeProp & ButtonStyleProps>`
background-image: none !important; background-image: none !important;
height: ${({ dimension }) => (dimension ? `${dimension}px` : "auto")}; height: ${({ dimension }) => (dimension ? `${dimension}px` : "auto")};
width: ${({ dimension }) => (dimension ? `${dimension}px` : "auto")}; width: ${({ dimension }) => (dimension ? `${dimension}px` : "auto")};
min-height: 32px !important; min-height: ${({ compactMode }) =>
min-width: 32px !important; compactMode === "SHORT" ? "24px" : "30px"};
min-width: ${({ compactMode }) =>
compactMode === "SHORT" ? "24px" : "30px"};
font-size: ${({ compactMode }) =>
compactMode === "SHORT" ? "12px" : "14px"};
line-height: ${({ compactMode }) =>
compactMode === "SHORT" ? "24px" : "28px"};
${({ buttonColor, buttonVariant, hasOnClickAction, theme }) => `
${({ buttonColor, buttonVariant, compactMode, hasOnClickAction, theme }) => `
&:enabled { &:enabled {
background: ${ background: ${
getCustomBackgroundColor(buttonVariant, buttonColor) !== "none" getCustomBackgroundColor(buttonVariant, buttonColor) !== "none"
@ -213,8 +223,10 @@ export const StyledButton = styled((props) => (
& > span > svg { & > span > svg {
height: 100%; height: 100%;
width: 100%; width: 100%;
min-height: 16px; min-height:
min-width: 16px; ${compactMode === "SHORT" ? "14px" : "16px"};
min-width:
${compactMode === "SHORT" ? "14px" : "16px"};
} }
`} `}

View File

@ -104,7 +104,7 @@ const ControlBtn = styled.a<{
background: var(--wds-color-bg-hover); background: var(--wds-color-bg-hover);
svg path { svg path {
fill: var(--wds-color-hover); fill: var(--wds-color-icon-hover);
} }
} }
`; `;

View File

@ -195,6 +195,10 @@ const paginatorCss = css<{
.rc-pagination-disabled:hover, .rc-pagination-disabled:hover,
.rc-pagination-disabled:focus { .rc-pagination-disabled:focus {
cursor: not-allowed; cursor: not-allowed;
& > * {
pointer-events: none;
}
} }
.rc-pagination-disabled .rc-pagination-item-link, .rc-pagination-disabled .rc-pagination-item-link,
.rc-pagination-disabled:hover .rc-pagination-item-link, .rc-pagination-disabled:hover .rc-pagination-item-link,
@ -322,7 +326,6 @@ const paginatorCss = css<{
box-shadow: ${({ boxShadow }) => `${boxShadow}`} !important; box-shadow: ${({ boxShadow }) => `${boxShadow}`} !important;
color: var(--wds-color-text) !important; color: var(--wds-color-text) !important;
border-color: transparent !important; border-color: transparent !important;
} }
.rc-pagination-prev .rc-pagination-item-link, .rc-pagination-next .rc-pagination-item-link { .rc-pagination-prev .rc-pagination-item-link, .rc-pagination-next .rc-pagination-item-link {
@ -340,6 +343,10 @@ const paginatorCss = css<{
} }
} }
.rc-pagination-disabled .rc-pagination-item-link {
color: var(--wds-color-text-disabled) !important;
}
.rc-pagination-item:hover { .rc-pagination-item:hover {
background-color: var(--wds-color-bg-hover) !important; background-color: var(--wds-color-bg-hover) !important;

View File

@ -22,6 +22,7 @@ export const TableIconWrapper = styled.div<{
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
background: var(--wds-color-bg);
opacity: ${(props) => (props.disabled ? 0.6 : 1)}; opacity: ${(props) => (props.disabled ? 0.6 : 1)};
cursor: ${(props) => !props.disabled && "pointer"}; cursor: ${(props) => !props.disabled && "pointer"};
color: ${(props) => (props.selected ? Colors.CODE_GRAY : Colors.GRAY)}; color: ${(props) => (props.selected ? Colors.CODE_GRAY : Colors.GRAY)};
@ -34,7 +35,7 @@ export const TableIconWrapper = styled.div<{
margin-left: 5px; margin-left: 5px;
padding: 0 5px; padding: 0 5px;
&:hover { &:hover {
background: ${Colors.ATHENS_GRAY}; background: var(--wds-color-bg-hover);
} }
`; `;

View File

@ -1,13 +1,11 @@
import React, { useState, useEffect, useCallback } from "react"; import React, { useState, useEffect, useCallback } from "react";
import styled from "styled-components"; import styled from "styled-components";
import { Icon, InputGroup } from "@blueprintjs/core"; import { InputGroup } from "@blueprintjs/core";
import { debounce } from "lodash"; import { debounce } from "lodash";
import { AnyStyledComponent } from "styled-components";
import CustomizedDropdown from "pages/common/CustomizedDropdown"; import CustomizedDropdown from "pages/common/CustomizedDropdown";
import { Directions } from "utils/helpers"; import { Directions } from "utils/helpers";
import { Colors } from "constants/Colors"; import { Colors } from "constants/Colors";
import { ControlIcons } from "icons/ControlIcons";
import { Skin } from "constants/DefaultTheme"; import { Skin } from "constants/DefaultTheme";
import AutoToolTipComponent from "./cellComponents/AutoToolTipComponent"; import AutoToolTipComponent from "./cellComponents/AutoToolTipComponent";
import { import {
@ -24,21 +22,13 @@ import DatePickerComponent from "widgets/DatePickerWidget2/component";
import { TimePrecision } from "widgets/DatePickerWidget2/constants"; import { TimePrecision } from "widgets/DatePickerWidget2/constants";
import { ColumnTypes, ReadOnlyColumnTypes } from "../constants"; import { ColumnTypes, ReadOnlyColumnTypes } from "../constants";
const StyledRemoveIcon = styled( import CloseIcon from "remixicon-react/CloseCircleFillIcon";
ControlIcons.CLOSE_CIRCLE_CONTROL as AnyStyledComponent, import ArrowDownIcon from "remixicon-react/ArrowDownSLineIcon";
)`
padding: 0;
position: relative;
cursor: pointer;
&.hide-icon {
display: none;
}
`;
const LabelWrapper = styled.div` const LabelWrapper = styled.div`
width: 95px; width: 95px;
margin-left: 10px; margin-left: 10px;
color: ${Colors.BLUE_BAYOUX}; color: var(--wds-color-text-light);
font-size: 14px; font-size: 14px;
font-weight: 500; font-weight: 500;
`; `;
@ -55,18 +45,29 @@ const DropdownWrapper = styled.div<{ width: number }>`
margin-left: 10px; margin-left: 10px;
`; `;
const StyledInputGroup = styled(InputGroup)` const StyledInputGroup = styled(InputGroup)<{
background: ${Colors.WHITE}; borderRadius?: string;
border: 1px solid #d3dee3; }>`
background: var(--wds-color-bg);
border: 1px solid var(--wds-color-border);
box-sizing: border-box; box-sizing: border-box;
border-radius: 2px; border-radius: ${(props) => props.borderRadius || "0"};
color: ${Colors.OXFORD_BLUE}; color: var(--wds-color-text);
height: 32px; height: 32px;
width: 150px; width: 120px;
margin-left: 10px; margin-left: 10px;
overflow: hidden;
input { input {
box-shadow: none; box-shadow: none;
} }
input:focus {
box-shadow: none;
}
&:hover {
border-color: var(--wds-color-border-hover);
}
`; `;
const DatePickerWrapper = styled.div` const DatePickerWrapper = styled.div`
@ -74,20 +75,26 @@ const DatePickerWrapper = styled.div`
width: 150px; width: 150px;
`; `;
const DropdownTrigger = styled.div` const DropdownTrigger = styled.div<{
borderRadius?: string;
}>`
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
width: 100%; width: 100%;
height: 32px; height: 32px;
background: ${Colors.WHITE}; background: var(--wds-color-bg);
border: 1px solid #d3dee3; border: 1px solid var(--wds-color-border);
box-sizing: border-box; box-sizing: border-box;
border-radius: 2px; border-radius: ${(props) => props.borderRadius || "0"};
font-size: 14px; font-size: 14px;
padding: 5px 12px 7px; padding: 5px 12px 7px;
color: ${Colors.OXFORD_BLUE}; color: var(--wds-color-text);
cursor: pointer; cursor: pointer;
&:hover {
border-color: var(--wds-color-border-hover);
}
&&& span { &&& span {
margin-right: 0; margin-right: 0;
} }
@ -209,6 +216,7 @@ function RenderOptions(props: {
value?: string | Condition; value?: string | Condition;
showType?: boolean; showType?: boolean;
className?: string; className?: string;
borderRadius?: string;
}) { }) {
const [selectedValue, selectValue] = useState(props.placeholder); const [selectedValue, selectValue] = useState(props.placeholder);
const configs = { const configs = {
@ -239,15 +247,20 @@ function RenderOptions(props: {
openDirection: Directions.DOWN, openDirection: Directions.DOWN,
trigger: { trigger: {
content: ( content: (
<DropdownTrigger className={props.className}> <DropdownTrigger
<AutoToolTipComponentWrapper title={selectedValue}> borderRadius={props.borderRadius}
className={props.className}
>
<AutoToolTipComponentWrapper disablePadding title={selectedValue}>
{selectedValue} {selectedValue}
</AutoToolTipComponentWrapper> </AutoToolTipComponentWrapper>
<Icon color={Colors.SLATE_GRAY} icon="caret-down" iconSize={16} /> <ArrowDownIcon className="w-5 h-5" color="var(--wds-color-icon)" />
</DropdownTrigger> </DropdownTrigger>
), ),
}, },
skin: Skin.LIGHT, skin: Skin.LIGHT,
borderRadius: props.borderRadius,
customizedDropdownId: "cascade-dropdown",
}; };
useEffect(() => { useEffect(() => {
if (props.value && props.columns) { if (props.value && props.columns) {
@ -270,6 +283,7 @@ function RenderInput(props: {
value: string; value: string;
onChange: (value: string) => void; onChange: (value: string) => void;
className?: string; className?: string;
borderRadius?: string;
}) { }) {
const debouncedOnChange = useCallback(debounce(props.onChange, 400), []); const debouncedOnChange = useCallback(debounce(props.onChange, 400), []);
const [value, setValue] = useState(props.value); const [value, setValue] = useState(props.value);
@ -283,6 +297,7 @@ function RenderInput(props: {
}, [props.value]); }, [props.value]);
return ( return (
<StyledInputGroup <StyledInputGroup
borderRadius={props.borderRadius}
className={props.className} className={props.className}
defaultValue={value} defaultValue={value}
onChange={onChange} onChange={onChange}
@ -547,18 +562,17 @@ function Fields(props: CascadeFieldProps & { state: CascadeFieldState }) {
}, [props]); }, [props]);
return ( return (
<FieldWrapper className="t--table-filter"> <FieldWrapper className="t--table-filter">
<StyledRemoveIcon <CloseIcon
className={`t--table-filter-remove-btn ${ className={`t--table-filter-remove-btn w-6 h-6 cursor-pointer ${
hasAnyFilters ? "" : "hide-icon" hasAnyFilters ? "" : "hidden"
}`} }`}
color={Colors.GRAY} color="var(--wds-color-icon)"
height={16}
onClick={handleRemoveFilter} onClick={handleRemoveFilter}
width={16}
/> />
{index === 1 ? ( {index === 1 ? (
<DropdownWrapper width={95}> <DropdownWrapper width={95}>
<RenderOptions <RenderOptions
borderRadius={props.borderRadius}
className="t--table-filter-operators-dropdown" className="t--table-filter-operators-dropdown"
columns={operatorOptions} columns={operatorOptions}
placeholder="or" placeholder="or"
@ -571,8 +585,9 @@ function Fields(props: CascadeFieldProps & { state: CascadeFieldState }) {
{index === 0 ? "Where" : OperatorTypes[props.operator]} {index === 0 ? "Where" : OperatorTypes[props.operator]}
</LabelWrapper> </LabelWrapper>
)} )}
<DropdownWrapper width={150}> <DropdownWrapper width={120}>
<RenderOptions <RenderOptions
borderRadius={props.borderRadius}
className="t--table-filter-columns-dropdown" className="t--table-filter-columns-dropdown"
columns={props.columns} columns={props.columns}
placeholder="Attribute" placeholder="Attribute"
@ -584,6 +599,7 @@ function Fields(props: CascadeFieldProps & { state: CascadeFieldState }) {
{showConditions ? ( {showConditions ? (
<DropdownWrapper width={200}> <DropdownWrapper width={200}>
<RenderOptions <RenderOptions
borderRadius={props.borderRadius}
className="t--table-filter-conditions-dropdown" className="t--table-filter-conditions-dropdown"
columns={conditions} columns={conditions}
placeholder="" placeholder=""
@ -594,6 +610,7 @@ function Fields(props: CascadeFieldProps & { state: CascadeFieldState }) {
) : null} ) : null}
{showInput ? ( {showInput ? (
<RenderInput <RenderInput
borderRadius={props.borderRadius}
className="t--table-filter-value-input" className="t--table-filter-value-input"
onChange={onValueChange} onChange={onValueChange}
value={value} value={value}
@ -617,7 +634,6 @@ function Fields(props: CascadeFieldProps & { state: CascadeFieldState }) {
shortcuts={false} shortcuts={false}
timePrecision={TimePrecision.MINUTE} timePrecision={TimePrecision.MINUTE}
widgetId="" widgetId=""
withoutPortal
/> />
</DatePickerWrapper> </DatePickerWrapper>
) : null} ) : null}

View File

@ -30,7 +30,7 @@ import { Scrollbars } from "react-custom-scrollbars";
import { renderEmptyRows } from "./cellComponents/EmptyCell"; import { renderEmptyRows } from "./cellComponents/EmptyCell";
import { renderHeaderCheckBoxCell } from "./cellComponents/SelectionCheckboxCell"; import { renderHeaderCheckBoxCell } from "./cellComponents/SelectionCheckboxCell";
import { HeaderCell } from "./cellComponents/HeaderCell"; import { HeaderCell } from "./cellComponents/HeaderCell";
import { EditableCell } from "../constants"; import { EditableCell, TableVariant } from "../constants";
import { TableBody } from "./TableBody"; import { TableBody } from "./TableBody";
interface TableProps { interface TableProps {
@ -81,8 +81,11 @@ interface TableProps {
accentColor: string; accentColor: string;
borderRadius: string; borderRadius: string;
boxShadow?: string; boxShadow?: string;
borderWidth?: number;
borderColor?: string;
onBulkEditDiscard: () => void; onBulkEditDiscard: () => void;
onBulkEditSave: () => void; onBulkEditSave: () => void;
variant?: TableVariant;
primaryColumnId?: string; primaryColumnId?: string;
} }
@ -236,13 +239,17 @@ export function Table(props: TableProps) {
<TableWrapper <TableWrapper
accentColor={props.accentColor} accentColor={props.accentColor}
backgroundColor={Colors.ATHENS_GRAY_DARKER} backgroundColor={Colors.ATHENS_GRAY_DARKER}
borderColor={props.borderColor}
borderRadius={props.borderRadius} borderRadius={props.borderRadius}
borderWidth={props.borderWidth}
boxShadow={props.boxShadow} boxShadow={props.boxShadow}
height={props.height} height={props.height}
id={`table${props.widgetId}`} id={`table${props.widgetId}`}
isHeaderVisible={isHeaderVisible} isHeaderVisible={isHeaderVisible}
isResizingColumn={isResizingColumn.current}
tableSizes={tableSizes} tableSizes={tableSizes}
triggerRowSelection={props.triggerRowSelection} triggerRowSelection={props.triggerRowSelection}
variant={props.variant}
width={props.width} width={props.width}
> >
{isHeaderVisible && ( {isHeaderVisible && (
@ -263,6 +270,7 @@ export function Table(props: TableProps) {
backgroundColor={Colors.WHITE} backgroundColor={Colors.WHITE}
serverSidePaginationEnabled={props.serverSidePaginationEnabled} serverSidePaginationEnabled={props.serverSidePaginationEnabled}
tableSizes={tableSizes} tableSizes={tableSizes}
variant={props.variant}
width={props.width} width={props.width}
> >
<TableHeader <TableHeader

View File

@ -12,17 +12,21 @@ interface TableActionProps {
icon: string; icon: string;
title: string; title: string;
titleColor?: string; titleColor?: string;
borderRadius?: string;
} }
export const TableIconWrapper = styled.div<{ export const TableIconWrapper = styled.div<{
selected?: boolean; selected?: boolean;
disabled?: boolean; disabled?: boolean;
titleColor?: string; titleColor?: string;
borderRadius?: string;
}>` }>`
height: 38px; height: calc(100% - 12px);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
background: var(--wds-color-bg);
border-radius: ${(props) => props.borderRadius || "0"};
opacity: ${(props) => (props.disabled ? 0.6 : 1)}; opacity: ${(props) => (props.disabled ? 0.6 : 1)};
cursor: ${(props) => !props.disabled && "pointer"}; cursor: ${(props) => !props.disabled && "pointer"};
color: ${(props) => (props.selected ? Colors.CODE_GRAY : Colors.GRAY)}; color: ${(props) => (props.selected ? Colors.CODE_GRAY : Colors.GRAY)};
@ -32,10 +36,18 @@ export const TableIconWrapper = styled.div<{
color: ${(props) => props.titleColor || Colors.GRAY}; color: ${(props) => props.titleColor || Colors.GRAY};
} }
position: relative; position: relative;
margin-left: 5px; margin-left: 8px;
padding: 0 5px; padding: 0 6px;
&:hover { &:hover {
background: ${Colors.ATHENS_GRAY}; background: var(--wds-color-bg-hover);
}
& > div {
width: 16px;
}
span {
font-size: 13px;
} }
`; `;
@ -59,6 +71,7 @@ function TableAction(props: TableActionProps) {
return ( return (
<TableIconWrapper <TableIconWrapper
borderRadius={props.borderRadius}
className={props.className} className={props.className}
onClick={handleIconClick} onClick={handleIconClick}
selected={props.selected} selected={props.selected}

View File

@ -10,7 +10,7 @@ import { Colors } from "constants/Colors";
import { ReactTableColumnProps } from "./Constants"; import { ReactTableColumnProps } from "./Constants";
import { TableIconWrapper } from "./TableStyledWrappers"; import { TableIconWrapper } from "./TableStyledWrappers";
import TableAction from "./TableAction"; import TableAction from "./TableAction";
import styled from "styled-components"; import styled, { createGlobalStyle } from "styled-components";
import { transformTableDataIntoCsv } from "./CommonUtilities"; import { transformTableDataIntoCsv } from "./CommonUtilities";
import zipcelx from "zipcelx"; import zipcelx from "zipcelx";
import { ReactComponent as DownloadIcon } from "assets/icons/control/download-data-icon.svg"; import { ReactComponent as DownloadIcon } from "assets/icons/control/download-data-icon.svg";
@ -33,10 +33,10 @@ const OptionWrapper = styled.div`
height: 32px; height: 32px;
box-sizing: border-box; box-sizing: border-box;
padding: 6px 12px; padding: 6px 12px;
color: ${Colors.CHARCOAL}; color: var(--wds-color-text);
min-width: 200px; min-width: 200px;
cursor: pointer; cursor: pointer;
background: ${Colors.WHITE}; background: var(--wds-color-bg);
border-left: none; border-left: none;
border-radius: none; border-radius: none;
.option-title { .option-title {
@ -45,15 +45,28 @@ const OptionWrapper = styled.div`
line-height: 20px; line-height: 20px;
} }
&:hover { &:hover {
background: ${Colors.SEA_SHELL}; background: var(--wds-color-bg-hover);
color: ${Colors.CODE_GRAY};
} }
`; `;
const PopoverStyles = createGlobalStyle<{
id?: string;
borderRadius?: string;
}>`
${({ borderRadius, id }) => `
.${id}.${Classes.POPOVER} {
border-radius: min(${borderRadius}, 0.375rem);
box-shadow: 0 6px 20px 0px rgba(0, 0, 0, 0.15);
overflow: hidden;
}
`}
`;
interface TableDataDownloadProps { interface TableDataDownloadProps {
data: Array<Record<string, unknown>>; data: Array<Record<string, unknown>>;
columns: ReactTableColumnProps[]; columns: ReactTableColumnProps[];
widgetName: string; widgetName: string;
delimiter: string; delimiter: string;
borderRadius?: string;
} }
type FileDownloadType = "CSV" | "EXCEL"; type FileDownloadType = "CSV" | "EXCEL";
@ -192,15 +205,18 @@ function TableDataDownload(props: TableDataDownloadProps) {
); );
} }
return ( return (
<>
<Popover <Popover
enforceFocus={false} enforceFocus={false}
interactionKind={PopoverInteractionKind.CLICK} interactionKind={PopoverInteractionKind.CLICK}
isOpen={selected} isOpen={selected}
minimal minimal
onClose={handleCloseMenu} onClose={handleCloseMenu}
popoverClassName="table-download-popover"
position={Position.BOTTOM} position={Position.BOTTOM}
> >
<TableAction <TableAction
borderRadius={props.borderRadius}
className="t--table-download-btn" className="t--table-download-btn"
icon="download" icon="download"
selectMenu={selectMenu} selectMenu={selectMenu}
@ -223,6 +239,11 @@ function TableDataDownload(props: TableDataDownloadProps) {
})} })}
</DropDownWrapper> </DropDownWrapper>
</Popover> </Popover>
<PopoverStyles
borderRadius={props.borderRadius}
id="table-download-popover"
/>
</>
); );
} }

View File

@ -21,7 +21,7 @@ import { ReactComponent as DragHandleIcon } from "assets/icons/ads/app-icons/dra
const DragBlock = styled.div` const DragBlock = styled.div`
height: 40px; height: 40px;
width: 83px; width: 83px;
background: ${Colors.WHITE_SNOW}; background: var(--wds-color-bg-light);
box-sizing: border-box; box-sizing: border-box;
font-size: 12px; font-size: 12px;
color: ${Colors.GREY_11}; color: ${Colors.GREY_11};
@ -33,7 +33,7 @@ const DragBlock = styled.div`
cursor: pointer; cursor: pointer;
span { span {
padding-left: 8px; padding-left: 8px;
color: ${Colors.GREY_11}; color: var(--wds-color-text-light);
} }
`; `;
@ -86,6 +86,7 @@ class TableFilterPane extends Component<Props> {
return ( return (
<Popper <Popper
borderRadius={this.props.borderRadius}
boundaryParent={boundaryParent || "viewport"} boundaryParent={boundaryParent || "viewport"}
disablePopperEvents={get(this.props, "metaProps.isMoved", false)} disablePopperEvents={get(this.props, "metaProps.isMoved", false)}
isDraggable isDraggable
@ -93,6 +94,7 @@ class TableFilterPane extends Component<Props> {
onPositionChange={this.handlePositionUpdate} onPositionChange={this.handlePositionUpdate}
parentElement={boundaryParent} parentElement={boundaryParent}
placement="top" placement="top"
portalContainer={document.getElementById("art-board") || undefined}
position={get(this.props, "metaProps.position") as PositionPropsInt} position={get(this.props, "metaProps.position") as PositionPropsInt}
renderDragBlock={ renderDragBlock={
<DragBlock> <DragBlock>

View File

@ -1,5 +1,5 @@
import React, { useEffect, useCallback } from "react"; import React, { useEffect, useCallback } from "react";
import styled, { AnyStyledComponent } from "styled-components"; import styled from "styled-components";
import { Classes } from "@blueprintjs/core"; import { Classes } from "@blueprintjs/core";
import { Colors } from "constants/Colors"; import { Colors } from "constants/Colors";
import { import {
@ -9,36 +9,27 @@ import {
OperatorTypes, OperatorTypes,
} from "./Constants"; } from "./Constants";
import { DropdownOption } from "./TableFilters"; import { DropdownOption } from "./TableFilters";
import Button from "components/editorComponents/Button";
import CascadeFields from "./CascadeFields"; import CascadeFields from "./CascadeFields";
import { import {
createMessage, createMessage,
TABLE_FILTER_COLUMN_TYPE_CALLOUT, TABLE_FILTER_COLUMN_TYPE_CALLOUT,
} from "@appsmith/constants/messages"; } from "@appsmith/constants/messages";
import { ControlIcons } from "icons/ControlIcons";
import { Icon, IconSize } from "design-system"; import { Icon, IconSize } from "design-system";
import Button from "pages/AppViewer/AppViewerButton";
import { ButtonVariantTypes } from "components/constants";
import AddIcon from "remixicon-react/AddLineIcon";
import { cloneDeep } from "lodash"; import { cloneDeep } from "lodash";
const StyledPlusCircleIcon = styled( const TableFilterOuterWrapper = styled.div<{
ControlIcons.ADD_CIRCLE_CONTROL as AnyStyledComponent, borderRadius?: string;
)` }>`
padding: 0;
position: relative;
cursor: pointer;
svg {
circle {
fill: none !important;
stroke: ${Colors.GREEN};
}
}
`;
const TableFilterOuterWrapper = styled.div`
display: flex; display: flex;
flex-direction: column; flex-direction: column;
width: 100%; width: 100%;
background: ${Colors.WHITE}; background: ${Colors.WHITE};
box-shadow: 0px 12px 28px -8px rgba(0, 0, 0, 0.1); box-shadow: 0 6px 20px 0px rgba(0, 0, 0, 0.15);
border-radius: ${(props) => props.borderRadius || "0"};
`; `;
const TableFilerWrapper = styled.div` const TableFilerWrapper = styled.div`
@ -75,10 +66,10 @@ const ButtonActionsWrapper = styled.div`
const ColumnTypeBindingMessage = styled.div` const ColumnTypeBindingMessage = styled.div`
height: 40px; height: 40px;
line-height: 40px; line-height: 40px;
background: ${Colors.WHITE_SNOW}; background: var(--wds-color-bg-light);
box-sizing: border-box; box-sizing: border-box;
font-size: 12px; font-size: 12px;
color: ${Colors.GREY_11}; color: var(--wds-color-text-light);
letter-spacing: 0.04em; letter-spacing: 0.04em;
font-weight: 500; font-weight: 500;
margin-left: 83px; margin-left: 83px;
@ -180,6 +171,7 @@ function TableFilterPaneContent(props: TableFilterProps) {
); );
return ( return (
<TableFilterOuterWrapper <TableFilterOuterWrapper
borderRadius={props.borderRadius}
onClick={(e) => { onClick={(e) => {
e.stopPropagation(); e.stopPropagation();
}} }}
@ -254,25 +246,29 @@ function TableFilterPaneContent(props: TableFilterProps) {
{hasAnyFilters ? ( {hasAnyFilters ? (
<ButtonWrapper> <ButtonWrapper>
<Button <Button
borderRadius={props.borderRadius}
buttonColor={props.accentColor}
buttonVariant={ButtonVariantTypes.TERTIARY}
className="t--add-filter-btn" className="t--add-filter-btn"
icon={<StyledPlusCircleIcon height={16} width={16} />} icon={<AddIcon className="w-5 h-5" color={props.accentColor} />}
intent="primary"
onClick={addFilter} onClick={addFilter}
size="small" size="small"
text="Add Filter" text="Add Filter"
/> />
<ButtonActionsWrapper> <ButtonActionsWrapper>
<Button <Button
borderRadius={props.borderRadius}
buttonColor={props.accentColor}
buttonVariant={ButtonVariantTypes.SECONDARY}
className="t--clear-all-filter-btn" className="t--clear-all-filter-btn"
intent="primary"
onClick={clearFilters} onClick={clearFilters}
outline
text="CLEAR ALL" text="CLEAR ALL"
/> />
<Button <Button
borderRadius={props.borderRadius}
buttonColor={props.accentColor}
buttonVariant={ButtonVariantTypes.PRIMARY}
className="t--apply-filter-btn" className="t--apply-filter-btn"
filled
intent="primary"
onClick={applyFilter} onClick={applyFilter}
text="APPLY" text="APPLY"
/> />

View File

@ -97,6 +97,7 @@ function TableFilters(props: TableFilterProps) {
return ( return (
<> <>
<TableAction <TableAction
borderRadius={props.borderRadius}
className={className} className={className}
icon="filter" icon="filter"
selectMenu={toggleFilterPane} selectMenu={toggleFilterPane}

View File

@ -17,15 +17,16 @@ import {
import TableDataDownload from "./TableDataDownload"; import TableDataDownload from "./TableDataDownload";
import { Colors } from "constants/Colors"; import { Colors } from "constants/Colors";
import { EventType } from "constants/AppsmithActionConstants/ActionConstants"; import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
import { lightenColor } from "widgets/WidgetUtils";
const PageNumberInputWrapper = styled(NumericInput)<{ const PageNumberInputWrapper = styled(NumericInput)<{
borderRadius: string; borderRadius: string;
accentColor?: string;
}>` }>`
&&& input { &&& input {
box-shadow: none; box-shadow: none;
border: 1px solid ${Colors.ALTO2}; border: 1px solid var(--wds-color-border);
background: linear-gradient(0deg, ${Colors.WHITE}, ${Colors.WHITE}), background: var(--wds-color-bg);
${Colors.POLAR};
box-sizing: border-box; box-sizing: border-box;
width: 24px; width: 24px;
height: 24px; height: 24px;
@ -34,10 +35,26 @@ const PageNumberInputWrapper = styled(NumericInput)<{
text-align: center; text-align: center;
font-size: 12px; font-size: 12px;
border-radius: ${({ borderRadius }) => borderRadius}; border-radius: ${({ borderRadius }) => borderRadius};
&:disabled {
border-color: var(--wds-color-border-disabled);
background: var(--wds-color-bg-disabled);
color: var(--wds-color-text-disabled);
} }
}
&&&.bp3-control-group > :only-child { &&&.bp3-control-group > :only-child {
border-radius: 0; border-radius: 0;
} }
& input:hover:not(:disabled) {
border-color: var(--wds-color-border-hover) !important;
}
& input:focus {
box-shadow: 0 0 0 2px ${({ accentColor }) => lightenColor(accentColor)} !important;
border-color: ${({ accentColor }) => accentColor} !important;
}
margin: 0 8px; margin: 0 8px;
`; `;
@ -46,12 +63,65 @@ const SearchComponentWrapper = styled.div<{
boxShadow?: string; boxShadow?: string;
accentColor: string; accentColor: string;
}>` }>`
margin: 3px 10px; margin: 6px 8px;
padding: 0 8px;
flex: 0 0 200px; flex: 0 0 200px;
border: 1px solid var(--wds-color-border);
border-radius: ${({ borderRadius }) => borderRadius} !important;
overflow: hidden;
&:hover {
border-color: var(--wds-color-border-hover);
}
&:focus-within {
border-color: ${({ accentColor }) => accentColor} !important;
box-shadow: 0 0 0 2px ${({ accentColor }) => lightenColor(accentColor)} !important;
}
& .${Classes.INPUT} { & .${Classes.INPUT} {
border-radius: ${({ borderRadius }) => borderRadius} !important; height: 100%;
padding-left: 20px !important;
} }
& > div {
height: 100%;
}
// search component
& > div > div {
height: 100%;
svg {
height: 12px;
width: 12px;
path {
fill: var(--wds-color-icon) !important;
}
}
}
// cross icon component
& > div > div + div {
top: 0;
right: -4px;
height: 100%;
align-items: center;
display: flex;
svg {
top: initial !important;
}
}
& .${Classes.ICON} {
margin: 0;
height: 100%;
display: flex;
align-items: center;
}
& .${Classes.INPUT}:active, & .${Classes.INPUT}:focus { & .${Classes.INPUT}:active, & .${Classes.INPUT}:focus {
border-radius: ${({ borderRadius }) => borderRadius}; border-radius: ${({ borderRadius }) => borderRadius};
border: 0px solid !important; border: 0px solid !important;
@ -66,6 +136,7 @@ function PageNumberInput(props: {
updatePageNo: (pageNo: number, event?: EventType) => void; updatePageNo: (pageNo: number, event?: EventType) => void;
disabled: boolean; disabled: boolean;
borderRadius: string; borderRadius: string;
accentColor?: string;
}) { }) {
const [pageNumber, setPageNumber] = React.useState(props.pageNo || 0); const [pageNumber, setPageNumber] = React.useState(props.pageNo || 0);
useEffect(() => { useEffect(() => {
@ -95,6 +166,7 @@ function PageNumberInput(props: {
); );
return ( return (
<PageNumberInputWrapper <PageNumberInputWrapper
accentColor={props.accentColor}
borderRadius={props.borderRadius} borderRadius={props.borderRadius}
buttonPosition="none" buttonPosition="none"
clampValueOnBlur clampValueOnBlur
@ -178,6 +250,7 @@ function TableHeader(props: TableHeaderProps) {
{props.isVisibleDownload && ( {props.isVisibleDownload && (
<TableDataDownload <TableDataDownload
borderRadius={props.borderRadius}
columns={props.tableColumns} columns={props.tableColumns}
data={props.tableData} data={props.tableData}
delimiter={props.delimiter} delimiter={props.delimiter}
@ -257,6 +330,7 @@ function TableHeader(props: TableHeaderProps) {
onClick={() => { onClick={() => {
const pageNo = const pageNo =
props.currentPageIndex > 0 ? props.currentPageIndex - 1 : 0; props.currentPageIndex > 0 ? props.currentPageIndex - 1 : 0;
!(props.currentPageIndex === 0) &&
props.updatePageNo(pageNo + 1, EventType.ON_PREV_PAGE); props.updatePageNo(pageNo + 1, EventType.ON_PREV_PAGE);
}} }}
> >
@ -265,6 +339,7 @@ function TableHeader(props: TableHeaderProps) {
<TableHeaderContentWrapper> <TableHeaderContentWrapper>
Page{" "} Page{" "}
<PageNumberInput <PageNumberInput
accentColor={props.accentColor}
borderRadius={props.borderRadius} borderRadius={props.borderRadius}
disabled={props.pageCount === 1} disabled={props.pageCount === 1}
pageCount={props.pageCount} pageCount={props.pageCount}
@ -283,6 +358,7 @@ function TableHeader(props: TableHeaderProps) {
props.currentPageIndex < props.pageCount - 1 props.currentPageIndex < props.pageCount - 1
? props.currentPageIndex + 1 ? props.currentPageIndex + 1
: 0; : 0;
!(props.currentPageIndex === props.pageCount - 1) &&
props.updatePageNo(pageNo + 1, EventType.ON_NEXT_PAGE); props.updatePageNo(pageNo + 1, EventType.ON_NEXT_PAGE);
}} }}
> >

View File

@ -18,6 +18,7 @@ import { hideScrollbar, invisible } from "constants/DefaultTheme";
import { lightenColor, darkenColor } from "widgets/WidgetUtils"; import { lightenColor, darkenColor } from "widgets/WidgetUtils";
import { FontStyleTypes } from "constants/WidgetConstants"; import { FontStyleTypes } from "constants/WidgetConstants";
import { Classes } from "@blueprintjs/core"; import { Classes } from "@blueprintjs/core";
import { TableVariant, TableVariantTypes } from "../constants";
const OFFSET_WITHOUT_HEADER = 40; const OFFSET_WITHOUT_HEADER = 40;
const OFFSET_WITH_HEADER = 80; const OFFSET_WITH_HEADER = 80;
@ -34,12 +35,17 @@ export const TableWrapper = styled.div<{
isHeaderVisible?: boolean; isHeaderVisible?: boolean;
borderRadius: string; borderRadius: string;
boxShadow?: string; boxShadow?: string;
borderColor?: string;
borderWidth?: number;
isResizingColumn?: boolean;
variant?: TableVariant;
}>` }>`
width: 100%; width: 100%;
height: 100%; height: 100%;
background: white; background: white;
border: ${({ boxShadow }) => border-style: solid;
boxShadow === "none" ? `1px solid ${Colors.GEYSER_LIGHT}` : `none`}; border-width: ${({ borderWidth }) => `${borderWidth}px`};
border-color: ${({ borderColor }) => borderColor};
border-radius: ${({ borderRadius }) => borderRadius}; border-radius: ${({ borderRadius }) => borderRadius};
box-shadow: ${({ boxShadow }) => `${boxShadow}`} !important; box-shadow: ${({ boxShadow }) => `${boxShadow}`} !important;
box-sizing: border-box; box-sizing: border-box;
@ -65,7 +71,6 @@ export const TableWrapper = styled.div<{
border-spacing: 0; border-spacing: 0;
color: ${Colors.THUNDER}; color: ${Colors.THUNDER};
position: relative; position: relative;
background: ${Colors.ATHENS_GRAY_DARKER};
display: table; display: table;
width: 100%; width: 100%;
${hideScrollbar}; ${hideScrollbar};
@ -92,17 +97,31 @@ export const TableWrapper = styled.div<{
&.selected-row { &.selected-row {
background: ${({ accentColor }) => background: ${({ accentColor }) =>
`${lightenColor(accentColor)}`} !important; `${lightenColor(accentColor)}`} !important;
}
&:hover { &:hover {
background: ${({ accentColor }) => background: ${({ accentColor }) =>
`${lightenColor(accentColor)}`} !important; `${lightenColor(accentColor, "0.9")}`} !important;
}
}
&:hover {
background: var(--wds-color-bg-hover) !important;
} }
} }
.th, .th,
.td { .td {
margin: 0; margin: 0;
border-bottom: 1px solid ${Colors.GEYSER_LIGHT}; border-bottom: ${(props) =>
border-right: 1px solid ${Colors.GEYSER_LIGHT}; props.variant === TableVariantTypes.DEFAULT ||
props.variant === undefined ||
props.variant === TableVariantTypes.VARIANT3
? `1px solid var(--wds-color-border-onaccent)`
: `1px solid transparent`};
border-right: ${(props) =>
props.variant === TableVariantTypes.DEFAULT ||
props.variant === undefined ||
props.isResizingColumn
? `1px solid var(--wds-color-border-onaccent)`
: `1px solid transparent`};
position: relative; position: relative;
font-size: ${(props) => props.tableSizes.ROW_FONT_SIZE}px; font-size: ${(props) => props.tableSizes.ROW_FONT_SIZE}px;
line-height: ${(props) => props.tableSizes.ROW_FONT_SIZE}px; line-height: ${(props) => props.tableSizes.ROW_FONT_SIZE}px;
@ -125,13 +144,23 @@ export const TableWrapper = styled.div<{
} }
} }
} }
.th {
font-size: 14px;
}
.thead:hover .th {
border-right: 1px solid var(--wds-color-border-onaccent);
}
.th { .th {
padding: 0 10px 0 0; padding: 0 10px 0 0;
height: ${(props) => height: ${(props) =>
props.isHeaderVisible ? props.tableSizes.COLUMN_HEADER_HEIGHT : 40}px; props.isHeaderVisible ? props.tableSizes.COLUMN_HEADER_HEIGHT : 40}px;
line-height: ${(props) => line-height: ${(props) =>
props.isHeaderVisible ? props.tableSizes.COLUMN_HEADER_HEIGHT : 40}px; props.isHeaderVisible ? props.tableSizes.COLUMN_HEADER_HEIGHT : 40}px;
background: ${Colors.ATHENS_GRAY_DARKER}; background: var(--wds-color-bg);
font-weight: bold;
} }
.td { .td {
min-height: ${(props) => props.tableSizes.ROW_HEIGHT}px; min-height: ${(props) => props.tableSizes.ROW_HEIGHT}px;
@ -154,7 +183,6 @@ export const TableWrapper = styled.div<{
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
color: ${Colors.OXFORD_BLUE}; color: ${Colors.OXFORD_BLUE};
font-weight: 500;
padding-left: 10px; padding-left: 10px;
&.sorted { &.sorted {
padding-left: 5px; padding-left: 5px;
@ -171,6 +199,8 @@ export const TableWrapper = styled.div<{
} }
} }
.hidden-header { .hidden-header {
opacity: 0.6;
${invisible}; ${invisible};
} }
.column-menu { .column-menu {
@ -248,8 +278,8 @@ export const PaginationWrapper = styled.div`
width: 100%; width: 100%;
justify-content: flex-end; justify-content: flex-end;
align-items: center; align-items: center;
padding: 8px 20px; padding: 8px;
color: ${Colors.GRAY}; color: var(--wds-color-text-light);
`; `;
export const PaginationItemWrapper = styled.div<{ export const PaginationItemWrapper = styled.div<{
@ -258,8 +288,13 @@ export const PaginationItemWrapper = styled.div<{
borderRadius: string; borderRadius: string;
accentColor: string; accentColor: string;
}>` }>`
background: ${(props) => (props.disabled ? Colors.MERCURY : Colors.WHITE)}; background: ${(props) =>
border: 1px solid ${Colors.ALTO2}; props.disabled ? `var(--wds-color-bg-disabled)` : `var(--wds-color-bg)`};
border: 1px solid
${(props) =>
props.disabled
? `var(--wds-color-border-disabled)`
: `var(--wds-color-border)`};
box-sizing: border-box; box-sizing: border-box;
width: 24px; width: 24px;
height: 24px; height: 24px;
@ -267,12 +302,29 @@ export const PaginationItemWrapper = styled.div<{
justify-content: center; justify-content: center;
align-items: center; align-items: center;
margin: 0 4px; margin: 0 4px;
pointer-events: ${(props) => props.disabled && "none"}; cursor: ${(props) => (props.disabled ? "not-allowed" : "pointer")};
cursor: pointer;
border-radius: ${({ borderRadius }) => borderRadius}; border-radius: ${({ borderRadius }) => borderRadius};
&:hover {
border-color: ${({ accentColor }) => accentColor}; & > * {
pointer-events: ${(props) => props.disabled && "none"};
display: flex;
align-items: center;
justify-content: center;
position: relative;
} }
& svg {
fill: ${(props) =>
props.disabled
? `var(--wds-color-icon-disabled)`
: `var(--wds-color-icon)`};
}
${({ disabled }) =>
!disabled &&
`&:hover {
border-color: var(--wds-color-border-hover);
background-color: var(--wds-color-bg-hover);
}`}
`; `;
export const MenuColumnWrapper = styled.div<{ selected: boolean }>` export const MenuColumnWrapper = styled.div<{ selected: boolean }>`
@ -312,6 +364,9 @@ export const ActionWrapper = styled.div<{ disabled: boolean }>`
export const IconButtonWrapper = styled.div<{ disabled: boolean }>` export const IconButtonWrapper = styled.div<{ disabled: boolean }>`
${(props) => (props.disabled ? "cursor: not-allowed;" : null)} ${(props) => (props.disabled ? "cursor: not-allowed;" : null)}
align-items: center;
display: flex;
}
`; `;
export const TableStyles = css<{ export const TableStyles = css<{
@ -334,6 +389,7 @@ export const CellWrapper = styled.div<{
textColor?: string; textColor?: string;
cellBackground?: string; cellBackground?: string;
textSize?: string; textSize?: string;
disablePadding?: boolean;
}>` }>`
display: ${(props) => (props.isCellVisible !== false ? "flex" : "none")}; display: ${(props) => (props.isCellVisible !== false ? "flex" : "none")};
align-items: center; align-items: center;
@ -357,11 +413,21 @@ export const CellWrapper = styled.div<{
align-items: ${(props) => align-items: ${(props) =>
props.verticalAlignment && ALIGN_ITEMS[props.verticalAlignment]}; props.verticalAlignment && ALIGN_ITEMS[props.verticalAlignment]};
background: ${(props) => props.cellBackground}; background: ${(props) => props.cellBackground};
&:hover, .selected-row & {
background: ${(props) =>
props.cellBackground ? darkenColor(props.cellBackground, 5) : ""};
}
font-size: ${(props) => props.textSize}; font-size: ${(props) => props.textSize};
padding: ${(props) => padding: ${(props) =>
props.compactMode ? TABLE_SIZES[props.compactMode].VERTICAL_PADDING : 0}px props.disablePadding
10px; ? 0
: `${
props.compactMode
? `${TABLE_SIZES[props.compactMode].VERTICAL_PADDING}px 10px`
: `${0}px 10px`
}`};
line-height: ${CELL_WRAPPER_LINE_HEIGHT}px; line-height: ${CELL_WRAPPER_LINE_HEIGHT}px;
.${Classes.POPOVER_WRAPPER} { .${Classes.POPOVER_WRAPPER} {
width: 100%; width: 100%;
@ -505,12 +571,15 @@ export const TableHeaderInnerWrapper = styled.div<{
width: number; width: number;
tableSizes: TableSizes; tableSizes: TableSizes;
backgroundColor?: Color; backgroundColor?: Color;
variant?: TableVariant;
}>` }>`
position: relative; position: relative;
display: flex; display: flex;
width: 100%; width: 100%;
height: 100%; height: 100%;
border-bottom: 1px solid ${Colors.GEYSER_LIGHT}; border-bottom: ${(props) =>
props.variant !== "VARIANT2" &&
`1px solid var(--wds-color-border-onaccent)`};
`; `;
export const CommonFunctionsMenuWrapper = styled.div<{ export const CommonFunctionsMenuWrapper = styled.div<{
@ -518,7 +587,17 @@ export const CommonFunctionsMenuWrapper = styled.div<{
}>` }>`
display: flex; display: flex;
align-items: center; align-items: center;
height: ${(props) => props.tableSizes.TABLE_HEADER_HEIGHT}px; height: 100%;
& .bp3-popover-target,
& .bp3-popover-wrapper {
height: 100%;
}
& .bp3-popover-target {
display: flex;
align-items: center;
}
`; `;
export const TableHeaderContentWrapper = styled.div` export const TableHeaderContentWrapper = styled.div`

View File

@ -82,6 +82,7 @@ interface Props {
fontStyle?: string; fontStyle?: string;
cellBackground?: string; cellBackground?: string;
textSize?: string; textSize?: string;
disablePadding?: boolean;
url?: string; url?: string;
} }
@ -130,6 +131,7 @@ function AutoToolTipComponent(props: Props) {
cellBackground={props.cellBackground} cellBackground={props.cellBackground}
className="cell-wrapper" className="cell-wrapper"
compactMode={props.compactMode} compactMode={props.compactMode}
disablePadding={props.disablePadding}
fontStyle={props.fontStyle} fontStyle={props.fontStyle}
horizontalAlignment={props.horizontalAlignment} horizontalAlignment={props.horizontalAlignment}
isCellVisible={props.isCellVisible} isCellVisible={props.isCellVisible}

View File

@ -5,8 +5,17 @@ import { BaseButton } from "widgets/ButtonWidget/component";
import { ButtonColumnActions } from "widgets/TableWidgetV2/constants"; import { ButtonColumnActions } from "widgets/TableWidgetV2/constants";
import styled from "styled-components"; import styled from "styled-components";
const StyledButton = styled(BaseButton)` const StyledButton = styled(BaseButton)<{
compactMode?: string;
}>`
min-width: 40px; min-width: 40px;
min-height: ${({ compactMode }) =>
compactMode === "SHORT" ? "24px" : "30px"};
font-size: ${({ compactMode }) =>
compactMode === "SHORT" ? "12px" : "14px"};
line-height: ${({ compactMode }) =>
compactMode === "SHORT" ? "24px" : "28px"};
`; `;
type ButtonProps = { type ButtonProps = {
@ -14,6 +23,7 @@ type ButtonProps = {
isSelected: boolean; isSelected: boolean;
isDisabled?: boolean; isDisabled?: boolean;
action: ButtonColumnActions; action: ButtonColumnActions;
compactMode?: string;
onCommandClick: (dynamicTrigger: string, onComplete: () => void) => void; onCommandClick: (dynamicTrigger: string, onComplete: () => void) => void;
}; };
@ -40,6 +50,7 @@ export function Button(props: ButtonProps) {
boxShadow={props.action.boxShadow} boxShadow={props.action.boxShadow}
buttonColor={props.action.backgroundColor} buttonColor={props.action.backgroundColor}
buttonVariant={props.action.variant} buttonVariant={props.action.variant}
compactMode={props.compactMode}
disabled={props.isDisabled} disabled={props.isDisabled}
iconAlign={props.action.iconAlign} iconAlign={props.action.iconAlign}
iconName={props.action.iconName} iconName={props.action.iconName}

View File

@ -29,6 +29,7 @@ function IconButton(props: {
borderRadius: string; borderRadius: string;
boxShadow: string; boxShadow: string;
disabled: boolean; disabled: boolean;
compactMode?: string;
}): JSX.Element { }): JSX.Element {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const onComplete = () => { const onComplete = () => {
@ -55,6 +56,7 @@ function IconButton(props: {
boxShadow={props.boxShadow} boxShadow={props.boxShadow}
buttonColor={props.buttonColor} buttonColor={props.buttonColor}
buttonVariant={props.buttonVariant} buttonVariant={props.buttonVariant}
compactMode={props.compactMode}
disabled={props.disabled} disabled={props.disabled}
icon={props.iconName} icon={props.iconName}
loading={loading} loading={loading}
@ -122,6 +124,7 @@ export function IconButtonCell(props: RenderIconButtonProps) {
boxShadow={boxShadow} boxShadow={boxShadow}
buttonColor={buttonColor} buttonColor={buttonColor}
buttonVariant={buttonVariant} buttonVariant={buttonVariant}
compactMode={compactMode}
disabled={disabled} disabled={disabled}
iconName={iconName} iconName={iconName}
isSelected={isSelected} isSelected={isSelected}

View File

@ -15,6 +15,7 @@ interface MenuButtonProps extends Omit<RenderMenuButtonProps, "columnActions"> {
function MenuButton({ function MenuButton({
borderRadius, borderRadius,
boxShadow, boxShadow,
compactMode,
iconAlign, iconAlign,
iconName, iconName,
isCompact, isCompact,
@ -45,6 +46,7 @@ function MenuButton({
<MenuButtonTableComponent <MenuButtonTableComponent
borderRadius={borderRadius} borderRadius={borderRadius}
boxShadow={boxShadow} boxShadow={boxShadow}
compactMode={compactMode}
iconAlign={iconAlign} iconAlign={iconAlign}
iconName={iconName} iconName={iconName}
isCompact={isCompact} isCompact={isCompact}

View File

@ -76,6 +76,7 @@ interface BaseStyleProps {
buttonVariant?: ButtonVariant; buttonVariant?: ButtonVariant;
isCompact?: boolean; isCompact?: boolean;
textColor?: string; textColor?: string;
compactMode?: string;
} }
const BaseButton = styled(Button)<ThemeProp & BaseStyleProps>` const BaseButton = styled(Button)<ThemeProp & BaseStyleProps>`
@ -88,6 +89,12 @@ const BaseButton = styled(Button)<ThemeProp & BaseStyleProps>`
border: 1.2px solid #ebebeb; border: 1.2px solid #ebebeb;
border-radius: 0; border-radius: 0;
box-shadow: none !important; box-shadow: none !important;
min-height: ${({ compactMode }) =>
compactMode === "SHORT" ? "24px" : "30px"};
font-size: ${({ compactMode }) =>
compactMode === "SHORT" ? "12px" : "14px"};
line-height: ${({ compactMode }) =>
compactMode === "SHORT" ? "24px" : "28px"};
${({ buttonColor, buttonVariant, theme }) => ` ${({ buttonColor, buttonVariant, theme }) => `
&:enabled { &:enabled {
@ -269,6 +276,7 @@ interface PopoverTargetButtonProps {
iconAlign?: Alignment; iconAlign?: Alignment;
isDisabled?: boolean; isDisabled?: boolean;
label?: string; label?: string;
compactMode?: string;
} }
function PopoverTargetButton(props: PopoverTargetButtonProps) { function PopoverTargetButton(props: PopoverTargetButtonProps) {
@ -277,6 +285,7 @@ function PopoverTargetButton(props: PopoverTargetButtonProps) {
boxShadow, boxShadow,
buttonColor, buttonColor,
buttonVariant, buttonVariant,
compactMode,
iconAlign, iconAlign,
iconName, iconName,
isDisabled, isDisabled,
@ -290,6 +299,7 @@ function PopoverTargetButton(props: PopoverTargetButtonProps) {
boxShadow={boxShadow} boxShadow={boxShadow}
buttonColor={buttonColor} buttonColor={buttonColor}
buttonVariant={buttonVariant} buttonVariant={buttonVariant}
compactMode={compactMode}
disabled={isDisabled} disabled={isDisabled}
fill fill
icon={iconAlign !== Alignment.RIGHT ? iconName : undefined} icon={iconAlign !== Alignment.RIGHT ? iconName : undefined}
@ -314,6 +324,7 @@ export interface MenuButtonComponentProps {
iconAlign?: Alignment; iconAlign?: Alignment;
onItemClicked: (onClick: string | undefined) => void; onItemClicked: (onClick: string | undefined) => void;
rowIndex: number; rowIndex: number;
compactMode?: string;
} }
function MenuButtonTableComponent(props: MenuButtonComponentProps) { function MenuButtonTableComponent(props: MenuButtonComponentProps) {
@ -321,6 +332,7 @@ function MenuButtonTableComponent(props: MenuButtonComponentProps) {
borderRadius = "0px", borderRadius = "0px",
boxShadow, boxShadow,
boxShadowColor, boxShadowColor,
compactMode,
iconAlign, iconAlign,
iconName, iconName,
isCompact, isCompact,
@ -365,6 +377,7 @@ function MenuButtonTableComponent(props: MenuButtonComponentProps) {
boxShadowColor={boxShadowColor} boxShadowColor={boxShadowColor}
buttonColor={menuColor} buttonColor={menuColor}
buttonVariant={menuVariant} buttonVariant={menuVariant}
compactMode={compactMode}
iconAlign={iconAlign} iconAlign={iconAlign}
iconName={iconName} iconName={iconName}
isDisabled={isDisabled} isDisabled={isDisabled}

View File

@ -9,7 +9,7 @@ import { Row } from "react-table";
import { EventType } from "constants/AppsmithActionConstants/ActionConstants"; import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
import equal from "fast-deep-equal/es6"; import equal from "fast-deep-equal/es6";
import { ColumnTypes, EditableCell } from "../constants"; import { ColumnTypes, EditableCell, TableVariant } from "../constants";
import { useCallback } from "react"; import { useCallback } from "react";
export interface ColumnMenuOptionProps { export interface ColumnMenuOptionProps {
@ -83,12 +83,17 @@ interface ReactTableComponentProps {
borderRadius: string; borderRadius: string;
boxShadow?: string; boxShadow?: string;
isEditableCellValid?: boolean; isEditableCellValid?: boolean;
borderColor?: string;
borderWidth?: number;
variant?: TableVariant;
primaryColumnId?: string; primaryColumnId?: string;
} }
function ReactTableComponent(props: ReactTableComponentProps) { function ReactTableComponent(props: ReactTableComponentProps) {
const { const {
applyFilter, applyFilter,
borderColor,
borderWidth,
columns, columns,
columnWidthMap, columnWidthMap,
compactMode, compactMode,
@ -127,6 +132,7 @@ function ReactTableComponent(props: ReactTableComponentProps) {
triggerRowSelection, triggerRowSelection,
unSelectAllRow, unSelectAllRow,
updatePageNo, updatePageNo,
variant,
widgetId, widgetId,
widgetName, widgetName,
width, width,
@ -268,7 +274,9 @@ function ReactTableComponent(props: ReactTableComponentProps) {
<Table <Table
accentColor={props.accentColor} accentColor={props.accentColor}
applyFilter={applyFilter} applyFilter={applyFilter}
borderColor={borderColor}
borderRadius={props.borderRadius} borderRadius={props.borderRadius}
borderWidth={borderWidth}
boxShadow={props.boxShadow} boxShadow={props.boxShadow}
columnWidthMap={columnWidthMap} columnWidthMap={columnWidthMap}
columns={columns} columns={columns}
@ -307,6 +315,7 @@ function ReactTableComponent(props: ReactTableComponentProps) {
totalRecordsCount={totalRecordsCount} totalRecordsCount={totalRecordsCount}
triggerRowSelection={triggerRowSelection} triggerRowSelection={triggerRowSelection}
updatePageNo={updatePageNo} updatePageNo={updatePageNo}
variant={variant}
widgetId={widgetId} widgetId={widgetId}
widgetName={widgetName} widgetName={widgetName}
width={width} width={width}
@ -350,6 +359,8 @@ export default React.memo(ReactTableComponent, (prev, next) => {
prev.width === next.width && prev.width === next.width &&
prev.borderRadius === next.borderRadius && prev.borderRadius === next.borderRadius &&
prev.boxShadow === next.boxShadow && prev.boxShadow === next.boxShadow &&
prev.borderWidth === next.borderWidth &&
prev.borderColor === next.borderColor &&
prev.accentColor === next.accentColor && prev.accentColor === next.accentColor &&
equal(prev.columnWidthMap, next.columnWidthMap) && equal(prev.columnWidthMap, next.columnWidthMap) &&
equal(prev.tableData, next.tableData) && equal(prev.tableData, next.tableData) &&
@ -358,6 +369,7 @@ export default React.memo(ReactTableComponent, (prev, next) => {
JSON.stringify(prev.columns) === JSON.stringify(next.columns) && JSON.stringify(prev.columns) === JSON.stringify(next.columns) &&
equal(prev.editableCell, next.editableCell) && equal(prev.editableCell, next.editableCell) &&
prev.isEditableCellValid === next.isEditableCellValid && prev.isEditableCellValid === next.isEditableCellValid &&
prev.variant === next.variant &&
prev.primaryColumnId === next.primaryColumnId prev.primaryColumnId === next.primaryColumnId
); );
}); });

View File

@ -80,9 +80,18 @@ export interface TableWidgetProps extends WidgetProps, WithMeta, TableStyles {
inlineEditingSaveOption?: InlineEditingSaveOptions; inlineEditingSaveOption?: InlineEditingSaveOptions;
showInlineEditingOptionDropdown?: boolean; showInlineEditingOptionDropdown?: boolean;
isEditableCellValid: boolean; isEditableCellValid: boolean;
variant?: TableVariant;
selectColumnFilterText?: Record<string, string>; selectColumnFilterText?: Record<string, string>;
} }
export enum TableVariantTypes {
DEFAULT = "DEFAULT",
VARIANT2 = "VARIANT2",
VARIANT3 = "VARIANT3",
}
export type TableVariant = keyof typeof TableVariantTypes;
export const ORIGINAL_INDEX_KEY = "__originalIndex__"; export const ORIGINAL_INDEX_KEY = "__originalIndex__";
export const PRIMARY_COLUMN_KEY_VALUE = "__primaryKey__"; export const PRIMARY_COLUMN_KEY_VALUE = "__primaryKey__";

View File

@ -31,6 +31,8 @@ export const CONFIG = {
totalRecordsCount: 0, totalRecordsCount: 0,
defaultPageSize: 0, defaultPageSize: 0,
dynamicPropertyPathList: [], dynamicPropertyPathList: [],
borderColor: Colors.GREY_5,
borderWidth: "1",
dynamicBindingPathList: [ dynamicBindingPathList: [
{ {
key: "primaryColumns.step.computedValue", key: "primaryColumns.step.computedValue",

View File

@ -828,7 +828,9 @@ class TableWidgetV2 extends BaseWidget<TableWidgetProps, WidgetState> {
<ReactTableComponent <ReactTableComponent
accentColor={this.props.accentColor} accentColor={this.props.accentColor}
applyFilter={this.updateFilters} applyFilter={this.updateFilters}
borderColor={this.props.borderColor}
borderRadius={this.props.borderRadius} borderRadius={this.props.borderRadius}
borderWidth={this.props.borderWidth}
boxShadow={this.props.boxShadow} boxShadow={this.props.boxShadow}
columnWidthMap={this.props.columnWidthMap} columnWidthMap={this.props.columnWidthMap}
columns={tableColumns} columns={tableColumns}
@ -875,6 +877,7 @@ class TableWidgetV2 extends BaseWidget<TableWidgetProps, WidgetState> {
triggerRowSelection={this.props.triggerRowSelection} triggerRowSelection={this.props.triggerRowSelection}
unSelectAllRow={this.unSelectAllRow} unSelectAllRow={this.unSelectAllRow}
updatePageNo={this.updatePageNumber} updatePageNo={this.updatePageNumber}
variant={this.props.variant}
widgetId={this.props.widgetId} widgetId={this.props.widgetId}
widgetName={this.props.widgetName} widgetName={this.props.widgetName}
width={componentWidth} width={componentWidth}

View File

@ -191,6 +191,29 @@ export default [
{ {
sectionName: "Border and Shadow", sectionName: "Border and Shadow",
children: [ children: [
{
propertyName: "variant",
helpText: "Selects the variant",
label: "Cell borders",
controlType: "DROP_DOWN",
defaultValue: "DEFAULT",
isBindProperty: true,
isTriggerProperty: false,
options: [
{
label: "Default",
value: "DEFAULT",
},
{
label: "No borders",
value: "VARIANT2",
},
{
label: "Horizonal borders only",
value: "VARIANT3",
},
],
},
{ {
propertyName: "borderRadius", propertyName: "borderRadius",
label: "Border Radius", label: "Border Radius",
@ -212,6 +235,26 @@ export default [
isTriggerProperty: false, isTriggerProperty: false,
validation: { type: ValidationTypes.TEXT }, validation: { type: ValidationTypes.TEXT },
}, },
{
helpText: "Use a html color name, HEX, RGB or RGBA value",
placeholderText: "#FFFFFF / Gray / rgb(255, 99, 71)",
propertyName: "borderColor",
label: "Border Color",
controlType: "COLOR_PICKER",
isBindProperty: true,
isTriggerProperty: false,
validation: { type: ValidationTypes.TEXT },
},
{
helpText: "Enter value for border width",
propertyName: "borderWidth",
label: "Border Width",
placeholderText: "Enter value in px",
controlType: "INPUT_TEXT",
isBindProperty: true,
isTriggerProperty: false,
validation: { type: ValidationTypes.NUMBER },
},
], ],
}, },
]; ];