Skip to content

Commit

Permalink
Various ag grid theme fixes (#3822)
Browse files Browse the repository at this point in the history
  • Loading branch information
origami-z authored Jul 22, 2024
1 parent 43d9b5a commit d92fe9e
Show file tree
Hide file tree
Showing 13 changed files with 322 additions and 39 deletions.
21 changes: 21 additions & 0 deletions .changeset/large-carrots-end.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
"@salt-ds/ag-grid-theme": patch
---

- Fixed background color for custom editor component.
- Fixed header text being cropped in HD compact. Closes #3675.
- Fixed Country Symbol taller than expected in HD compact. This alters `--salt-size-base` token so Salt Button, form controls (Input, Dropdown, Combo Box) will be impacted as well. Closes #3775.
- Fixed group value not center aligned vertically.
- Updated ag grid menu styling to match closer to Salt Menu component.
- Updated floating filter column chooser item styles. Closes #3671.

Note: We previously made a mistake on `rowHeight` recommendation when configurating AG Grid, which should be 1px more to account for border between row.
`useAgGridHelpers` example hook is updated to reflect this.

| Density | Row height ([`rowHeight`](https://www.ag-grid.com/javascript-data-grid/row-height/)) | Header height ([`headerHeight`](https://www.ag-grid.com/javascript-data-grid/column-headers/#header-height)) |
| ------------ | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ |
| HD (Compact) | 21 | 20 |
| HD | 25 | 24 |
| MD | 37 | 36 |
| LD | 49 | 48 |
| TD | 61 | 60 |
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"prettier:ci": "prettier --check .",
"lint": "biome check",
"lint:fix": "biome check --fix",
"lint:check:error": "biome check --diagnostic-level=error",
"lint:style": "yarn lint:style:core && yarn lint:style:icon && yarn lint:style:lab && yarn lint:style:ag-theme",
"lint:style:core": "yarn stylelint -f verbose \"packages/core/src/**/*.css\"",
"lint:style:icon": "yarn stylelint -f verbose \"packages/icons/src/**/*.css\"",
Expand Down
54 changes: 41 additions & 13 deletions packages/ag-grid-theme/css/salt-ag-grid-theme.css
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,13 @@ div[class*="ag-theme-salt"] {
}

div[class*="ag-theme-salt-compact"] {
--ag-row-height: var(--salt-size-base);
--ag-header-height: var(--salt-size-base);
/*
Ensures icon / country symbol renders correct height.
This also means we don't need to touch `--ag-row-height`, which would impact some internal ag grid height calculation like `--ag-internal-padded-row-height` vs `--ag-internal-calculated-line-height`
*/
--salt-size-base: 16px;
/* This is a deprecated token, until Salt Checkbox uses a new token, temparily pin it to HD size. */
--salt-size-selectable: 12px;
}

div[class*="ag-theme-salt"] .ag-root-wrapper {
Expand Down Expand Up @@ -155,13 +160,33 @@ div[class*="ag-theme-salt"] .ag-header-cell.ag-column-menu-visible .ag-icon {
color: var(--salt-actionable-secondary-foreground-active);
}

div[class*="ag-theme-salt"] .ag-cell-label-container {
/* row height is base size + 50 spacing on top/bottom */
padding: var(--salt-spacing-50) 0;
}

div[class*="ag-theme-salt"] .ag-list-item:hover,
div[class*="ag-theme-salt"] .ag-virtual-list-item:hover {
background-color: var(--salt-selectable-background-hover);
cursor: pointer;
}

div[class*="ag-theme-salt"] .ag-label-align-right .ag-label {
margin-inline-start: var(--salt-spacing-100);
margin-inline-end: 0;
}

/* MENU */

div[class*="ag-theme-salt"] .ag-menu {
padding: var(--salt-spacing-100);
padding: 0;
border: var(--salt-size-border) var(--salt-container-borderStyle) var(--salt-selectable-borderColor-selected);
}

div[class*="ag-theme-salt"] .ag-tabs {
padding: var(--salt-spacing-100);
}

div[class*="ag-theme-salt"] .ag-popup-child:not(.ag-tooltip-custom) {
box-shadow: var(--salt-overlayable-shadow-popout);
}
Expand All @@ -187,8 +212,9 @@ div[class*="ag-theme-salt"] .ag-menu-option {
height: calc(var(--salt-size-base) + var(--salt-spacing-100));
}

div[class*="ag-theme-salt"] .ag-menu-option-icon {
padding: 0 var(--salt-spacing-100);
div[class*="ag-theme-salt"] .ag-menu-option-icon,
div[class*="ag-theme-salt"] .ag-compact-menu-option-icon {
padding-inline-start: var(--salt-spacing-100);
}

div[class*="ag-theme-salt"] .ag-tab {
Expand Down Expand Up @@ -236,6 +262,16 @@ div[class*="ag-theme-salt"] .ag-cell {
padding-right: var(--salt-spacing-100);
}

/* This is not restricted to `.editable-cell`, so any custom editor would get the same background treatment */
div[class*="ag-theme-salt"] .ag-cell-inline-editing:focus-within {
background: var(--salt-container-primary-background);
}

/* This makes sure custom cell editor would start from no padding. Built-in ag grid editor's padding is added below. */
div[class*="ag-theme-salt"] .ag-cell-inline-editing {
padding: 0;
}

div[class*="ag-theme-salt"] .editable-cell,
div[class*="ag-theme-salt"] .editable-numeric-cell {
outline: var(--salt-size-border) var(--salt-container-borderStyle) var(--salt-editable-borderColor);
Expand Down Expand Up @@ -286,14 +322,6 @@ div[class*="ag-theme-salt"] .editable-cell.ag-cell-inline-editing:before {
z-index: 2;
}

div[class*="ag-theme-salt"] .editable-cell.ag-cell-inline-editing {
padding: 0;
}

div[class*="ag-theme-salt"] .editable-cell.ag-cell-inline-editing:focus-within {
background: var(--salt-container-primary-background);
}

div[class*="ag-theme-salt"] .editable-numeric-cell input,
div[class*="ag-theme-salt"] input[class^="ag-"][type="number"] {
padding: 0 var(--salt-spacing-100);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { Dropdown, type DropdownProps, Option } from "@salt-ds/core";
import type { ICellEditorParams } from "ag-grid-community";
import {
type KeyboardEvent,
type SyntheticEvent,
forwardRef,
useCallback,
useEffect,
useImperativeHandle,
useRef,
useState,
} from "react";

export type GridCellValue = string | boolean | number;

export interface DropdownEditorParams extends ICellEditorParams {
source?: Array<GridCellValue>;
dropdownProps?: Partial<DropdownProps<string>>;
}

export const DropdownEditor = forwardRef((props: DropdownEditorParams, ref) => {
const { value: initialValue, source = [], dropdownProps } = props;
const [value, setValue] = useState(initialValue);

const buttonRef = useRef<HTMLButtonElement>(null);

const onSelect = useCallback(
(_event: SyntheticEvent, selectedValue: Array<GridCellValue>) => {
setValue(selectedValue[0]);

// hack to make selection actually record the edit.
// timeout is necessary because otherwise the grid stops editing
// before the useImperativeHandle getValue returns the new value state
setTimeout(() => {
props.api?.stopEditing();
}, 100);
},
[props.api],
);

const onEscapeKeyPressed = useCallback(
(e: KeyboardEvent) => {
if (e.key === "Escape") {
props.api?.stopEditing();
}
},
[props.api],
);

useEffect(() => {
buttonRef.current?.focus();
}, []);

useImperativeHandle(ref, () => ({ getValue: (): typeof value => value }));

return (
<Dropdown
onSelectionChange={onSelect}
defaultOpen={props.cellStartedEdit}
selected={[value || ""]}
ref={buttonRef}
onKeyDown={onEscapeKeyPressed}
className="DropdownEditor"
{...dropdownProps}
style={{
// Outline will be shown on the cell
outline: "none",
// Leave room for cell focus ring
marginInline: "2px",
width: "calc(100% - 4px)",
}}
>
<div
ref={(elem): void => {
if (!elem) return;
// current element -> list container -> list box that matters
(
(elem.parentElement as HTMLElement).parentElement as HTMLElement
).className += " ag-custom-component-popup"; // https://www.ag-grid.com/react-data-grid/component-filter/#custom-filters-containing-a-popup-element
}}
>
{source.map((item) => (
<Option value={item} key={String(item)} />
))}
</div>
</Dropdown>
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { countryMetaMap } from "@salt-ds/countries";
import type { CustomCellRendererProps } from "ag-grid-react";

export const FlagRenderer = (props: CustomCellRendererProps) => {
const isoCode = props.value as keyof typeof countryMetaMap;
return (
<div
style={{
display: "flex",
flexFlow: "row",
justifyContent: "center",
width: "100%",
height: "100%",
alignItems: "center",
}}
>
<span
className={`saltCountrySharp-${isoCode}`}
aria-label={countryMetaMap[isoCode]?.countryName}
/>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import type { ColDef } from "ag-grid-community";
import { DropdownEditor } from "./cell-editors/DropdownEditor";
import { FlagRenderer } from "./cell-renderers/FlagRenderer";

const dataGridExampleColumnsHdCompact: ColDef[] = [
{
headerName: "",
field: "on",
width: 70,
flex: 1,
checkboxSelection: true,
headerCheckboxSelection: true,
pinned: "left",
suppressHeaderMenuButton: true,
resizable: false,
suppressColumnsToolPanel: true,
},
{
headerName: "Name",
field: "name",
filterParams: {
buttons: ["reset", "apply"],
},
editable: false,
},
{
headerName: "Code",
field: "code",
},
{
headerName: "Capital",
field: "capital",
filter: "agSetColumnFilter",
},
{
headerName: "Population",
type: "numericColumn",
field: "population",
filter: "agNumberColumnFilter",
editable: true,
cellClass: ["editable-cell"],
},
{
headerName: "Date",
field: "date",
filter: "agDateColumnFilter",
},
{
headerName: "Rating",
field: "rating",
// Not using `editable-cell` as it doesn't work with Dropdown focus style
editable: true,
cellEditor: "DropdownEditor",
cellEditorParams: {
source: [10, 20, 30, 40, 50, 60],
},
},
{
headerName: "Flag",
field: "country",
cellRenderer: FlagRenderer,
initialWidth: 80,
},
];
export default dataGridExampleColumnsHdCompact;
Loading

0 comments on commit d92fe9e

Please sign in to comment.