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

Dropdown, DatePicker, CheckboxText Components #133

Merged
merged 12 commits into from
Sep 15, 2024
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ When babies are born to women in the Georgia prison system, the mother is allott

You'll need:

1. [Figma](https://www.figma.com/design/1eq6iy7h2Cd7rYTxPB4s5P/Motherhood-Beyond-Bars-%2F-Spr2022-(Copy)?node-id=6212-1439&node-type=CANVAS&t=c1VA2QufmU1WeN6E-0)
1. [Figma](<https://www.figma.com/design/1eq6iy7h2Cd7rYTxPB4s5P/Motherhood-Beyond-Bars-%2F-Spr2022-(Copy)?node-id=6212-1439&node-type=CANVAS&t=c1VA2QufmU1WeN6E-0>)
2. Firebase Access - In Bitwarden, ask Parker if you need help accessing it!

### Making Changes
Expand Down Expand Up @@ -59,6 +59,7 @@ Both the application (web & mobile) can be ran directly in a development environ
To run both the mobile & web appplications, simply type `docker-compose up` in the root directory.

## Getting Started: Mobile (Caretaker) [OUTDATED]

Note: the mobile repo does not work and will only be met with errors.

```bash
Expand Down
18 changes: 18 additions & 0 deletions web/components/Icons/SmallDownChevron.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export default function SmallDownChevron() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="17"
height="17"
viewBox="0 0 17 17"
fill="none"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M13.0384 6.71967C13.3313 7.01256 13.3313 7.48744 13.0384 7.78033L8.78838 12.0303C8.49549 12.3232 8.02061 12.3232 7.72772 12.0303L3.47772 7.78033C3.18483 7.48744 3.18483 7.01256 3.47772 6.71967C3.77061 6.42678 4.24549 6.42678 4.53838 6.71967L8.25805 10.4393L11.9778 6.71967C12.2707 6.42678 12.7455 6.42678 13.0384 6.71967Z"
className="fill-dark-gray"
/>
</svg>
);
}
35 changes: 35 additions & 0 deletions web/components/atoms/DatePicker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import ReactDatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
import ErrorText from "./ErrorText";
import keyboardScroll from "@lib/utils/KeyboardScroll";

interface Props {
label: string;
value?: Date;
onChange?: (newDate: Date | null) => void;
disabled?: boolean;
error?: string;
}

export default function DatePicker({
label,
value,
onChange,
disabled,
error,
}: Props) {
return (
<div className="flex flex-col">
<label htmlFor={label}>{label}</label>
<ReactDatePicker
name={label}
onFocus={(e) => keyboardScroll(e)}
selected={value}
onChange={onChange}
disabled={disabled}
className={`w-full mt-2 py-2.5 px-2 items-center border-[1px] rounded ${disabled ? "bg-light-gray" : "bg-secondary-background"} ${error ? "border-[#FF3939]" : "border-light-gray"}`}
/>
<ErrorText error={error} />
</div>
);
}
45 changes: 45 additions & 0 deletions web/components/atoms/Dropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import ReactDropdown, { Option, Group } from "react-dropdown";
import "react-dropdown/style.css";
import ErrorText from "./ErrorText";
import keyboardScroll from "@lib/utils/KeyboardScroll";
import { useRef } from "react";
import SmallDownChevron from "@components/Icons/SmallDownChevron";

interface Props {
options: (string | Option | Group)[];
label: string;
placeholder?: string;
error?: string;
disabled?: boolean;
value?: string | Option;
onChange?: (value: Option) => void;
}

export default function Dropdown({
options,
disabled,
label,
onChange,
value,
error,
placeholder = "Select",
}: Props) {
return (
<div className="flex flex-col" onFocus={(e) => keyboardScroll(e)}>
<label>{label}</label>
<ReactDropdown
options={options}
value={value}
disabled={disabled}
onChange={onChange}
placeholder={placeholder}
placeholderClassName={`!text-medium-gray`}
controlClassName={`!flex !items-center !justify-between !w-full !mt-2 !py-2.5 !px-2 !rounded ${disabled ? "!bg-light-gray" : "!bg-secondary-background"} !text-primary-text ${error ? "!border-[#FF3939]" : "!border-light-gray"}`}
menuClassName={`!rounded !py-2 !bg-white !text-primary-text`}
arrowClosed={<SmallDownChevron />}
arrowOpen={<SmallDownChevron />}
/>
{error && <ErrorText error={error} />}
</div>
);
}
27 changes: 27 additions & 0 deletions web/components/atoms/ErrorText.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
interface Props {
error?: string;
}

export default function ErrorText({ error }: Props) {
return (
<div className="flex items-center gap-2 text-[#FF3939] h-6">
{error && (
<>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
>
<path
d="M14.1782 13.9994H1.8229C1.58473 13.9994 1.36465 13.8723 1.24556 13.6661C1.12648 13.4598 1.12648 13.2057 1.24557 12.9994L7.4229 2.33273C7.54208 2.1268 7.76197 2 7.9999 2C8.23783 2 8.45772 2.1268 8.5769 2.33273L14.7542 12.9994C14.8733 13.2056 14.8733 13.4595 14.7544 13.6658C14.6355 13.872 14.4156 13.9991 14.1776 13.9994H14.1782ZM7.33423 10.6661V11.9994H7.95623H7.99957H8.0429H8.66623V10.6661H7.33423ZM7.33423 5.99939V9.33273H8.66757V5.99939H7.33423Z"
className="fill-[#FF3939]"
/>
</svg>
<span>{error}</span>
</>
)}
</div>
);
}
51 changes: 26 additions & 25 deletions web/components/atoms/TextInput.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,41 @@
import React, { useState } from "react";
import React, { ChangeEvent } from "react";
import ErrorText from "./ErrorText";
import keyboardScroll from "@lib/utils/KeyboardScroll";

interface Props {
onChange?: (arg0: any) => any;
label: string;
disabled?: boolean;
onChange?: (value: ChangeEvent<HTMLInputElement>) => void;
formValue?: object;
currentValue?: string;
placeholder?: string;
errorMsg?: string;
error?: string;
}

export default function TextInput({
onChange = undefined,
label,
disabled,
onChange,
formValue = {},
currentValue = "",
placeholder = "",
errorMsg = "",
error,
}: Props) {
const [value, setValue] = useState(currentValue);

return (
<input
type="text"
{...formValue}
className={
"w-full py-2.5 px-2 bg-secondary-background items-center border border-light-gray rounded"
}
onChange={(event) => {
setValue(event.target.value);
if (onChange) {
onChange(event.target.value);
}
}}
placeholder={placeholder}
value={value}
/>
// TODO add error message and error border, if there is an error message, show error border
// There should always be a space for the error message, the space shouldn't disappear
// when the error message isn't there
<div className="flex flex-col">
<label className="font-opensans text-base" htmlFor={label}>
{label}
</label>
<input
type="text"
onFocus={(e) => keyboardScroll(e)}
{...formValue}
name={label}
className={`w-full mt-2 py-2.5 px-2 bg-secondary-background items-center border border-light-gray rounded ${disabled ? "!bg-light-gray" : "!bg-secondary-background"} !text-primary-text ${error ? "!border-[#FF3939]" : "!border-light-gray"}`}
onChange={onChange}
placeholder={placeholder}
/>
<ErrorText error={error} />
</div>
);
}
28 changes: 28 additions & 0 deletions web/components/molecules/CheckboxText.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { ReactNode, useState } from "react";

interface Props {
children: ReactNode;
value?: boolean;
onChange?: (value: boolean) => void;
}

export default function CheckboxText({ value, onChange, children }: Props) {
const [checked, setChecked] = useState(value);

return (
<button
className="flex gap-2 bg-white shadow border border-light-gray"
aria-roledescription="checkbox"
onClick={() =>
setChecked((prev) => {
onChange?.(!prev);
return !prev;
})
}
>
{/** TODO: <Checkbox value={value} /> */}
<input type="checkbox" checked={checked} aria-hidden />
{children}
</button>
);
}
9 changes: 9 additions & 0 deletions web/lib/utils/keyboardScroll.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { FocusEvent } from "react";

export default function keyboardScroll(e: FocusEvent) {
e.target.scrollIntoView({
behavior: 'smooth',
block: 'center',
inline: 'center'
})
}
Loading
Loading