Skip to content

Commit

Permalink
Add Textarea component
Browse files Browse the repository at this point in the history
  • Loading branch information
tomcur committed Jul 20, 2023
1 parent 4e1d3cd commit f5d4437
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 0 deletions.
53 changes: 53 additions & 0 deletions astroplant-frontend/src/Components/Textarea.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
.textarea {
display: inline-flex;
margin: 2px 0.2rem;
font-size: 1rem;

&::placeholder {
color: var(--gray-300);
opacity: 1;
}

&.adorned {
&:focus-visible {
outline: 0;
}
}

&:not(.adorned) {
border-radius: 0.5rem;
border: 1px solid var(--gray-100);
padding: 0.5rem 1.5rem;

&:focus-visible {
outline: 2px solid var(--outline-color);
}

&:disabled {
border: 1px solid var(--gray-50);
}
}
}

.textareaContainer {
display: inline-flex;
align-items: center;
border-radius: 0.5rem;
border: 1px solid var(--gray-100);
padding: 0.5rem 0.5rem;
gap: 0.25rem;

&:focus-within {
outline: 2px solid var(--outline-color);
}

> .textarea {
border-radius: 0;
border: 0;
flex: 1;
}
}

.fullWidth {
width: 100%;
}
61 changes: 61 additions & 0 deletions astroplant-frontend/src/Components/Textarea.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React, { useCallback, useRef } from "react";
import clsx from "clsx";

import style from "./Textarea.module.css";

export type TextareaProps = React.HTMLProps<HTMLTextAreaElement> & {
/** A React node to use as an adornment at the left side of the textarea. */
leftAdornment?: React.ReactNode;
/** A React node to use as an adornment at the right side of the textarea. */
rightAdornment?: React.ReactNode;
/** Whether the textarea takes up the full width of its container. */
fullWidth?: boolean;
};

export function Textarea({
leftAdornment,
rightAdornment,
fullWidth = false,
rows = 7,
...props
}: TextareaProps) {
const textareaRef = useRef<HTMLTextAreaElement>(null);

// When the textarea's container is clicked, focus the textarea element. Only
// used when the textarea is internally rendered in a container because of
// adornments.
const containerClickCb = useCallback(() => {
if (textareaRef.current) {
textareaRef.current.focus();
}
}, [textareaRef]);

const adorned = leftAdornment !== undefined || rightAdornment !== undefined;
const textarea = (
<textarea
{...props}
ref={textareaRef}
className={clsx(
style.textarea,
!adorned && fullWidth && style.fullWidth,
adorned && style.adorned,
)}
rows={rows}
/>
);

if (adorned) {
return (
<div
className={clsx(style.textContainer, fullWidth && style.fullWidth)}
onClick={containerClickCb}
>
{leftAdornment}
{textarea}
{rightAdornment}
</div>
);
} else {
return textarea;
}
}

0 comments on commit f5d4437

Please sign in to comment.