Skip to content

Commit

Permalink
improvement: enrich the feedback experience (#426)
Browse files Browse the repository at this point in the history
  • Loading branch information
abvthecity authored Feb 3, 2024
1 parent 3580d5f commit 53c5b38
Show file tree
Hide file tree
Showing 5 changed files with 326 additions and 50 deletions.
51 changes: 30 additions & 21 deletions packages/ui/app/src/components/FernButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,27 +48,36 @@ export const FernButton: FC<FernButtonProps> = ({
return (
<button
{...props}
className={classNames(className, "fern-button transition-shadow text-center align-middle", {
"rounded-md": small && !className?.includes("rounded"),
"rounded-lg": !small && !className?.includes("rounded"),
"px-2 py-1 text-xs h-6": small,
"px-3.5 py-1.5 text-sm h-9": !small,
"border ring-0 hover:ring-2": !minimal,
"border-border-primary dark:border-border-primary-dark ring-border-primary/10 dark:ring-border-primary-dark/10":
!minimal && intent === "primary",
"ring-text-primary dark:ring-text-primary-dark": !minimal && intent === "none",
"ring-intent-success-light dark:ring-intent-success-dark": !minimal && intent === "success",
"ring-intent-danger-light dark:ring-intent-danger-dark": !minimal && intent === "danger",
"hover:bg-tag-primary text-accent-primary dark:text-accent-primary-dark": intent === "primary",
"hover:bg-tag-primary bg-transparent dark:bg-transparent-dark text-text-primary-light/60 dark:text-text-primary-dark/60":
intent === "none",
"hover:bg-tag-success text-intent-success-light dark:text-intent-success-dark": intent === "success",
"hover:bg-tag-danger text-intent-danger-light dark:text-intent-danger-dark": intent === "danger",
"bg-tag-primary": intent === "primary" && active,
"bg-tag-success": intent === "success" && active,
"bg-tag-danger": intent === "danger" && active,
"w-full": full,
})}
className={classNames(
className,
"fern-button transition-shadow hover:transition-[background] text-center align-middle",
{
"rounded-md": small && !className?.includes("rounded"),
"rounded-lg": !small && !className?.includes("rounded"),
"px-2 py-1 text-xs h-6": small,
"px-3.5 py-1.5 text-sm h-9": !small,
"border ring-0": !minimal,
"hover:ring-2": !minimal && !disabled,
"border-border-primary dark:border-border-primary-dark ring-border-primary/10 dark:ring-border-primary-dark/10":
!minimal && intent === "primary",
"ring-text-primary dark:ring-text-primary-dark": !minimal && intent === "none",
"ring-intent-success-light dark:ring-intent-success-dark": !minimal && intent === "success",
"ring-intent-danger-light dark:ring-intent-danger-dark": !minimal && intent === "danger",
"text-accent-primary dark:text-accent-primary-dark": intent === "primary",
"hover:bg-tag-primary": (intent === "primary" || intent === "none") && !disabled,
"bg-transparent dark:bg-transparent-dark text-text-primary-light/60 dark:text-text-primary-dark/60":
intent === "none",
"text-intent-success-light dark:text-intent-success-dark": intent === "success",
"hover:bg-tag-success": intent === "success" && !disabled,
"text-intent-danger-light dark:text-intent-danger-dark": intent === "danger",
"hover:bg-tag-danger": intent === "danger" && !disabled,
"bg-tag-primary": intent === "primary" && active,
"bg-tag-success": intent === "success" && active,
"bg-tag-danger": intent === "danger" && active,
"w-full": full,
"cursor-not-allowed opacity-70": disabled,
},
)}
onClick={
props.onClick != null
? (e) => {
Expand Down
19 changes: 19 additions & 0 deletions packages/ui/app/src/components/FernRadio.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import classNames from "classnames";
import { DetailedHTMLProps, FC, InputHTMLAttributes } from "react";

interface FernRadioProps extends DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement> {
onChecked?: (checked: boolean) => void;
}
export const FernRadio: FC<FernRadioProps> = ({ className, children, onChecked, onChange, tabIndex, ...props }) => {
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
onChange?.(e);
onChecked?.(e.target.checked);
};
return (
<label className={classNames(className, "inline-flex cursor-pointer items-start group")} tabIndex={tabIndex}>
<input type="radio" className="peer h-0 w-0 opacity-0" {...props} onChange={handleChange} />
<span className="ring-border-default-light dark:ring-border-default-dark peer-checked:bg-accent-primary dark:peer-checked:bg-accent-primary-dark peer-checked:after:bg-background dark:peer-checked:after:bg-background-dark group-hover:bg-tag-primary dark:group-hover:bg-tag-primary-dark relative mt-0.5 inline-block h-4 w-4 rounded-lg ring-1 ring-inset peer-checked:after:absolute peer-checked:after:left-1 peer-checked:after:top-1 peer-checked:after:h-2 peer-checked:after:w-2 peer-checked:after:rounded peer-checked:after:content-['']"></span>
<div className="ml-2 flex-1">{children}</div>
</label>
);
};
49 changes: 49 additions & 0 deletions packages/ui/app/src/components/FernTextarea.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import classNames from "classnames";
import { DetailedHTMLProps, forwardRef, InputHTMLAttributes, useEffect, useImperativeHandle, useRef } from "react";

interface FernTextareaProps extends DetailedHTMLProps<InputHTMLAttributes<HTMLTextAreaElement>, HTMLTextAreaElement> {
onValueChange?: (value: string) => void;
value?: string;
minLines?: number;
}
export const FernTextarea = forwardRef<HTMLTextAreaElement, FernTextareaProps>(function FernTextarea(
{ className, onValueChange, minLines = 2, ...props },
ref,
) {
const inputRef = useRef<HTMLTextAreaElement>(null);

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
useImperativeHandle(ref, () => inputRef.current!);
const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
onValueChange?.(e.target.value);
props.onChange?.(e);
};
useAutosizeTextArea(inputRef.current, props.value ?? "", minLines);
return (
<textarea
{...props}
ref={inputRef}
className={classNames(
className,
"border-border-default-light dark:border-border-default-dark focus-visible:ring-tag-primary focus-visible:dark:ring-tag-primary-dark focus-visible:border-accent-primary caret-accent-primary focus-visible:dark:border-accent-primary-dark rounded-md border bg-white p-2 text-sm focus:outline-none focus-visible:ring-4 dark:bg-white/10 resize-none",
)}
onChange={handleChange}
/>
);
});

// Updates the height of a <textarea> when the value changes.
function useAutosizeTextArea(textAreaRef: HTMLTextAreaElement | null, value: string, minLines: number): void {
const minHeight = minLines * 20 + 16;
useEffect(() => {
if (textAreaRef) {
// We need to reset the height momentarily to get the correct scrollHeight for the textarea
textAreaRef.style.height = "0px";
const scrollHeight = textAreaRef.scrollHeight;

// We then set the height directly, outside of the render loop
// Trying to set this with state or a ref will product an incorrect value.
textAreaRef.style.height = Math.max(minHeight, scrollHeight) + "px";
}
}, [minHeight, textAreaRef, value]);
}
5 changes: 4 additions & 1 deletion packages/ui/app/src/custom-docs-page/CustomDocsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ export const CustomDocsPage: React.FC<CustomDocsPage.Props> = ({ resolvedPath })
<div className="h-20" />
</article>
</div>
<aside className="scroll-contain smooth-scroll hide-scrollbar sticky top-16 hidden h-[calc(100vh-64px)] w-[19rem] shrink-0 overflow-auto overflow-x-hidden px-8 pb-12 pt-8 xl:block">
<aside
id="right-sidebar"
className="scroll-contain smooth-scroll hide-scrollbar sticky top-16 hidden h-[calc(100vh-64px)] w-[19rem] shrink-0 overflow-auto overflow-x-hidden px-8 pb-12 pt-8 xl:block"
>
<TableOfContents renderedHtml={mdxString} />
{editThisPage != null && (
<Link
Expand Down
Loading

0 comments on commit 53c5b38

Please sign in to comment.