Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

E&A Date Picker (Part One) - Integration and usage within the E&A Timeline header #1044

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .parcelrc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
"resolvers": ["parcel-resolver-ignore", "parcel-resolver-veda", "@parcel/resolver-glob", "..."],
"transformers": {
"raw:*": ["@parcel/transformer-raw"],
"*.mdx": ["parcel-transformer-mdx-frontmatter", "parcel-transformer-mdx"]
"*.mdx": ["parcel-transformer-mdx-frontmatter", "parcel-transformer-mdx"],
"*.css": ["@parcel/transformer-postcss"],
"*.scss": ["@parcel/transformer-sass"]
}
}
9 changes: 9 additions & 0 deletions .sassrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const path = require('path')

const CWD = process.cwd()

module.exports = {
"includePaths": [
path.resolve(CWD, 'node_modules/@uswds/uswds/packages')
]
}
30 changes: 30 additions & 0 deletions app/scripts/components/common/datepicker/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
@use "usa-date-picker/src/styles";

.usa-date-picker {
position: relative;
width: 0;
height: 0;

&__calendar {
width: 20rem;
position: absolute;
top: 100%;
border: 1px solid rgb(230, 230, 230);
}

&--open-upwards .usa-date-picker__calendar {
top: auto;
bottom: 100%;
}

& *:not(:focus), & *:not(:active) {
font-family: themeVal('type.base.family');
z-index: 9999;
}

.usa-input,
&__button,
&__status {
display: none;
}
}
57 changes: 57 additions & 0 deletions app/scripts/components/common/datepicker/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React, { ReactNode, useRef, ReactElement } from "react";
import { DatePicker } from "@trussworks/react-uswds";
import { format } from 'date-fns';

import './index.scss';

interface SimpleDatePickerProps {
disabled: boolean;
tipContent: ReactNode;
onConfirm: (date: string) => void;
triggerHeadReference: string;
id: string;
selectedDay: Date | null;
renderTriggerElement: (props: {
onClick: () => void;
disabled: boolean;
tipContent: ReactNode;
triggerHeadReference: string;
selectedDay: Date | null;
}) => ReactElement;
}

export const SimpleDatePicker = ({ disabled, tipContent, onConfirm, id, triggerHeadReference, selectedDay, renderTriggerElement }: SimpleDatePickerProps) => {
const datePickerRef = useRef<HTMLDivElement>(null);

const toggleCalendar = () => {
// We have no reference to the internals of the react-uswds DatePicker, so we have to query for it's trigger.
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (datePickerRef.current) {
const button = datePickerRef.current.querySelector('button.usa-date-picker__button')! as HTMLButtonElement;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see. This is a sticky problem 😬 . Can we control the visibility of the calendar in this way? If we do a conditional render like {showCalendar && <DatePicker...>}, we will lose the access to this button. (Calendar is not toggling right now, it just re-renders when renderTriggerElement is pressed I think. )

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't unfortunately, since the <Calendar /> comes coupled with the <DatePicker /> and we can't conditionally render only that component. So the only thing I could think of is programmatically toggling it via the usa-date-picker__button.

This gets trickier when we will have to show the MONTH_PICKER or the YEAR_PICKER based on the dataset time density, because these calendar modes exist as a local state in the Calendar. So the only solution I can think of is to click the picker button to open the calendar, then query and click either usa-date-picker__calendar__month-selection or usa-date-picker__calendar__year-selection to toggle the corresponding calendar mode depending on the time density 😰

I opened two issues on react-uswds side:

Copy link
Collaborator

@hanbyul-here hanbyul-here Jul 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Throwing some ideas here. (It might be a terrible idea) Can it be something that we can solve by overwriting the style? I feel like they (calendar trigger element for both uswds date picker and our date picker) are eventually doing the same thing, showing the date, and then a button to trigger the calendar. (I understand our original design wants the whole thing to be a button to trigger - including the text- but maybe we can adjust the design a bit to accommodate USWDS system?)

ex. overwriting the text input style, calendar icon (to show the caret) here?

Screenshot 2024-07-12 at 10 57 42 AM

Maybe we can at least leave the button to trigger and overwrite the style?

Screenshot 2024-07-12 at 10 57 48 AM

Which will be roughly like this - #1047

Orrr 🤔 is this a good component to write React components for our own just using uswds style?

Copy link
Collaborator Author

@dzole0311 dzole0311 Jul 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the idea @hanbyul-here. As you pointed out, we will need to do a lot of manual triggering if we want to sync the calendar with the time density of the dataset, which I think is very error prone.

is this a good component to write React components for our own just using uswds style

Yes, I think so. We need a more robust approach but at the same time not to reinvent the wheel (e.g. implementing basic date picker functionality from scratch). What do you think about using react-calendar (https://www.npmjs.com/package/react-calendar)?

Here's a PR with it: #1048 and here's the deployment:

We could override some of the styles using uswds mixins / functions: https://github.com/NASA-IMPACT/veda-ui/pull/1048/files#diff-88b2701907396a34bbe38997d6970f2f6824389dbefe1dcc112a5fdfaa35d811R24

Also:

  • It works well with Tippy
  • It has out-of-the-box config for showing only the month or year calendar view (it's the maxDetail), so it will save us a lot of time

Any opinions on this?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeh, I Agree that we should not invent the wheel. I will vote for using ReactCalendar for now 👍

button.click();
}
};

return (
<>
{renderTriggerElement({
onClick: toggleCalendar,
disabled,
tipContent,
triggerHeadReference,
selectedDay,
})}
<div ref={datePickerRef}>
<DatePicker
key={selectedDay ? selectedDay.toISOString() : 'default'}
aria-describedby='veda-date-hint'
aria-labelledby='veda-date-label'
id={id}
name={id}
onChange={onConfirm}
defaultValue={format(selectedDay ?? new Date(), 'yyyy-MM-dd')}
/>
</div>
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ interface PanelDateWidgetProps {
children?: ReactNode;
}

const formatDate = (date: Date | null, view: string) => {
export const formatDate = (date: Date | null, view: string) => {
if (!date) return 'Date';

switch (view) {
Expand Down
Loading
Loading