Skip to content

Commit

Permalink
feat: custom date selector component (#417)
Browse files Browse the repository at this point in the history
* Add custome date selector

* Ensure the same border-radius for both selected and highlighted calendar grid cell when selecting date.

* Remove  minValue property, as there is no limit to how far back in time a user can go back to report an incident.
  • Loading branch information
jonasbrunvoll authored Nov 6, 2024
1 parent 73c2a52 commit a13ee5f
Show file tree
Hide file tree
Showing 12 changed files with 249 additions and 50 deletions.
83 changes: 83 additions & 0 deletions src/page-modules/contact/components/form/date-selector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import style from './form.module.css';
import { MonoIcon } from '@atb/components/icon';
import { TranslatedString, useTranslation } from '@atb/translations';
import { fromDate, parseDate } from '@internationalized/date';
import {
Button,
Calendar,
CalendarCell,
CalendarGrid,
DateInput,
DatePicker,
DateSegment,
Dialog,
Group,
Heading,
Label,
Popover,
} from 'react-aria-components';

export type DateSelectorProps = {
label: TranslatedString;
value?: string;
onChange: (value: string) => void;
};

export default function DateSelector({
label,
value,
onChange,
}: DateSelectorProps) {
const { t } = useTranslation();

return (
<div className={style.dateSelectorContainer}>
<Label>{t(label)}</Label>
<DatePicker
granularity="day"
value={fromDate(new Date(value || ''), 'Europe/Oslo')}
onChange={(e) => onChange(e.toString().slice(0, 10))}
className={style.dateSelector}
shouldForceLeadingZeros
>
<Group className={style.calendarSelectorGroup}>
<DateInput className={style.dateSelectorInput}>
{(segment) => <DateSegment segment={segment} />}
</DateInput>
<Button className={style.calendarButton}>
<MonoIcon icon="time/Date" />
</Button>
</Group>
<Popover className={style.calendarDialog} placement="bottom right">
<Dialog>
<Calendar>
<header className={style.calendarDialog__header}>
<Button
slot="previous"
className={style.calendarDialog__headerButtons}
>
<MonoIcon icon="navigation/ArrowLeft" />
</Button>
<Heading className={style.calendarDialog__title} />
<Button
slot="next"
className={style.calendarDialog__headerButtons}
>
<MonoIcon icon="navigation/ArrowRight" />
</Button>
</header>
<CalendarGrid className={style.calendarGrid}>
{(date) => (
<CalendarCell
date={date}
className={style.calendarGrid__cell}
/>
)}
</CalendarGrid>
</Calendar>
</Dialog>
</Popover>
</DatePicker>
</div>
);
}
131 changes: 129 additions & 2 deletions src/page-modules/contact/components/form/form.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -498,11 +498,14 @@
opacity: 0.7;
padding-right: var(--spacings-small);
}

@media (max-width: 600px) {
.select,
.select__placholder,
.select__listBoxItem,
.select__select_container,
.searchable_select__comboBox,
.searchable_select__listBoxItem {
.searchable_select__listBoxItem,
.searchable_select__input:not(:focus):placeholder-shown {
font-size: 1.25rem;
}
.select__popover,
Expand All @@ -511,3 +514,127 @@
box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.3);
}
}

/* Time and date selector */
.dateSelectorContainer {
display: flex;
flex-direction: column;
gap: var(--spacings-small);
font-size: 1rem !important;
}

.dateSelector,
.timeSelector {
--height: 2.75rem;
border-radius: var(--border-radius-small);
overflow: hidden;
}

.dateSelector input[type='date'],
.timeSelector input[type='time'] {
height: var(--height);
padding: var(--spacings-medium);
border: none;
background-color: transparent;
color: var(--static-background-background_0-text);
flex: 1;
}

.calendarSelectorGroup {
display: flex;
position: relative;
width: 100%;
}

.calendarButton {
position: absolute;
right: 0;
border: none;
cursor: pointer;
background: none;
margin: var(--spacings-medium);
border-radius: var(--border-radius-small);
}

.calendarDialog {
padding: var(--spacings-xSmall);
background: var(--static-background-background_0-background);
box-shadow: 0.2rem 0.2rem 0.3rem rgba(0, 0, 0, 0.15);
}

.calendarDialog__header {
display: flex;
gap: var(--spacings-medium);
justify-content: center;
align-items: center;
padding: var(--spacings-small);
}

.calendarDialog__title {
composes: typo-heading__component from '@atb/theme/typography.module.css';
}

.calendarDialog__headerButtons {
background: none;
border: none;
padding: var(--spacings-xSmall) var(--spacings-medium);
cursor: pointer;
}

.calendarGrid {
width: 100%;
}

.calendarGrid__cell {
padding: var(--spacings-xSmall) var(--spacings-medium);
cursor: pointer;
text-align: center;
border-radius: var(--border-radius-small);
}

.calendarGrid__cell[data-disabled] {
opacity: 0.3;
cursor: default;
}

.calendarGrid__cell[data-selected] {
background-color: var(--interactive-interactive_2-active-background);
color: var(--interactive-interactive_2-active-text);
font-weight: bold;
border-radius: var(--border-radius-small);
}

.dateSelectorInput,
.timeSelectorInput {
height: var(--height);
padding: var(--spacings-medium);
color: var(--static-background-background_0-text);
border-top-right-radius: 0.75rem;
border-bottom-right-radius: 0.75rem;
display: flex;
border: var(--border-width-slim) solid var(--text-colors-primary);
width: 100%;

border: var(--border-width-slim) solid var(--text-colors-primary);
align-items: center;
}

.dateSelector input[type='date']:focus,
.timeSelector input[type='time']:focus {
outline: 0;
}

.dateSelector:focus-within,
.timeSelector:focus-within {
box-shadow: inset 0 0 0 var(--border-width-medium)
var(--interactive-interactive_2-outline-background);
}

:global(.dark)
.dateSelector
input[type='date']::-webkit-calendar-picker-indicator,
:global(.dark)
.timeSelector
input[type='time']::-webkit-calendar-picker-indicator {
filter: invert(1);
}
1 change: 1 addition & 0 deletions src/page-modules/contact/components/form/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export { default as Input } from './input';
export { default as Radio } from './radio';
export { default as Select } from './select';
export { default as Textarea } from './textarea';
export { default as DateSelector } from './date-selector';
export {
SearchableSelect,
getLineOptions,
Expand Down
1 change: 1 addition & 0 deletions src/page-modules/contact/components/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ export {
SearchableSelect,
getLineOptions,
getStopOptions,
DateSelector,
} from './form';
export { SectionCard } from './section-card';
10 changes: 4 additions & 6 deletions src/page-modules/contact/means-of-transport/forms/delayForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
SearchableSelect,
getLineOptions,
getStopOptions,
DateSelector,
} from '../../components';

type DelayFormProps = {
Expand Down Expand Up @@ -128,17 +129,14 @@ export const DelayForm = ({ state, send }: DelayFormProps) => {
}
/>

<Input
<DateSelector
label={PageText.Contact.input.date.label}
type="date"
name="date"
value={state.context.date}
errorMessage={state.context?.errorMessages['date']?.[0]}
onChange={(e) =>
onChange={(date) =>
send({
type: 'ON_INPUT_CHANGE',
inputName: 'date',
value: e.target.value,
value: date,
})
}
/>
Expand Down
10 changes: 4 additions & 6 deletions src/page-modules/contact/means-of-transport/forms/driverForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
SearchableSelect,
getLineOptions,
getStopOptions,
DateSelector,
} from '../../components';

type DriverFormProps = {
Expand Down Expand Up @@ -150,17 +151,14 @@ export const DriverForm = ({ state, send }: DriverFormProps) => {
}
/>

<Input
<DateSelector
label={PageText.Contact.input.date.label}
type="date"
name="date"
value={state.context.date}
errorMessage={state.context?.errorMessages['date']?.[0]}
onChange={(e) =>
onChange={(date) =>
send({
type: 'ON_INPUT_CHANGE',
inputName: 'date',
value: e.target.value,
value: date,
})
}
/>
Expand Down
10 changes: 4 additions & 6 deletions src/page-modules/contact/means-of-transport/forms/injuryForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
SearchableSelect,
getLineOptions,
getStopOptions,
DateSelector,
} from '../../components';

type InjuryFormProps = {
Expand Down Expand Up @@ -149,17 +150,14 @@ export const InjuryForm = ({ state, send }: InjuryFormProps) => {
}
/>

<Input
<DateSelector
label={PageText.Contact.input.date.label}
type="date"
name="date"
value={state.context.date}
errorMessage={state.context?.errorMessages['date']?.[0]}
onChange={(e) =>
onChange={(date) =>
send({
type: 'ON_INPUT_CHANGE',
inputName: 'date',
value: e.target.value,
value: date,
})
}
/>
Expand Down
10 changes: 4 additions & 6 deletions src/page-modules/contact/means-of-transport/forms/stopForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
SearchableSelect,
getLineOptions,
getStopOptions,
DateSelector,
} from '../../components';

type StopFormProps = {
Expand Down Expand Up @@ -104,17 +105,14 @@ export const StopForm = ({ state, send }: StopFormProps) => {
}
/>

<Input
<DateSelector
label={PageText.Contact.input.date.label}
type="date"
name="date"
value={state.context.date}
errorMessage={state.context?.errorMessages['date']?.[0]}
onChange={(e) =>
onChange={(date) =>
send({
type: 'ON_INPUT_CHANGE',
inputName: 'date',
value: e.target.value,
value: date,
})
}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
SearchableSelect,
getLineOptions,
getStopOptions,
DateSelector,
} from '../../components';

type TransportationFormProps = {
Expand Down Expand Up @@ -132,17 +133,14 @@ export const TransportationForm = ({
}
/>

<Input
<DateSelector
label={PageText.Contact.input.date.label}
type="date"
name="date"
value={state.context.date}
errorMessage={state.context?.errorMessages['date']?.[0]}
onChange={(e) =>
onChange={(date) =>
send({
type: 'ON_INPUT_CHANGE',
inputName: 'date',
value: e.target.value,
value: date,
})
}
/>
Expand Down
Loading

0 comments on commit a13ee5f

Please sign in to comment.