Skip to content

Commit

Permalink
feat(DataTable): handle conditional shadow on pinned header
Browse files Browse the repository at this point in the history
  • Loading branch information
booc0mtaco committed Sep 17, 2024
1 parent c903ece commit 9a8985e
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 4 deletions.
8 changes: 5 additions & 3 deletions src/components/DataTable/DataTable.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

/* Visible table caption */
/* TODO-AH: make it so that we have the search bar and actions wrap together instead of separately */
/* TODO-AH: implement showing of shadow below sticky headers and column */
/* - https://stackoverflow.com/questions/38122751/positionsticky-adding-style-when-the-element-detaches-from-normal-flow */
.data-table__caption-container {
display: flex;
align-items: flex-end;
Expand Down Expand Up @@ -163,7 +161,7 @@
.data-table__header-row {
border-bottom: calc(var(--eds-border-width-sm) * 1px) solid;
position: sticky;
top: 0;
top: -1px;
}

.data-table__group-row {
Expand All @@ -182,6 +180,10 @@
padding: calc(var(--eds-size-2) / 16 * 1rem)
calc(var(--eds-size-3) / 16 * 1rem);
}
}

.data-table--is-pinned {
box-shadow: var(--eds-box-shadow-sm);

}

Expand Down
25 changes: 25 additions & 0 deletions src/components/DataTable/DataTable.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,31 @@ import { generateSnapshots } from '@chanzuckerberg/story-utils';
import * as stories from './DataTable.stories';
import type { StoryFile } from '../../util/utility-types';

// Stubbing out this class b/c it doesn't exist in non-browser contexts
export class IntersectionObserver {
root = null;
rootMargin = '';
thresholds = [];

disconnect() {
return null;
}

observe() {
return null;
}

takeRecords() {
return [];
}

unobserve() {
return null;
}
}
window.IntersectionObserver = IntersectionObserver;
global.IntersectionObserver = IntersectionObserver;

describe('<DataTable />', () => {
generateSnapshots(stories as StoryFile);
});
40 changes: 39 additions & 1 deletion src/components/DataTable/DataTable.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { flexRender, type Table } from '@tanstack/react-table';
import clsx from 'clsx';
import React from 'react';
import React, { useEffect } from 'react';

import type { EDSBase, Size, Status, Align } from '../../util/variant-types';

Expand Down Expand Up @@ -411,6 +411,44 @@ export const DataTableTable = ({
size && styles[`data-table--size-${size}`],
);

// eslint-disable-next-line @chanzuckerberg/edu-react/use-effect-deps-presence
useEffect(() => {
/**
* Here, we set up a selector on the header of a table, and look for it to start
* clipping off the top edge of its visible area. Once it does the observer will trigger
* causing the state class to be added / removed (depending on the intersection value).
*
* We use the generated class names from the module for both the trigger and whats toggled
*/
let observer: IntersectionObserver;
let el: Element | null;
function triggerEffect() {
el = document.querySelector(`.${styles['data-table__table']} thead`);
if (el && typeof window !== 'undefined') {
observer = new IntersectionObserver(
([event]) => {
return event.target.classList.toggle(
styles['data-table--is-pinned'],
event.intersectionRatio < 1,
);
},

{ threshold: [1] },
);

observer.observe(el);
}
}
triggerEffect();

// TODO: anything to de-allocate when using `observer`?
return () => {
if (el) {
observer.unobserve(el);
}
};
});

return <table className={tableClassNames}>{children}</table>;
};

Expand Down

0 comments on commit 9a8985e

Please sign in to comment.