Skip to content

Commit

Permalink
UI edits and changes from VS (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kashargul authored Sep 6, 2024
1 parent 69d3493 commit 893fcd3
Show file tree
Hide file tree
Showing 10 changed files with 154 additions and 74 deletions.
11 changes: 8 additions & 3 deletions lib/components/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
useState,
} from 'react';

import { KEY } from '../common/keys';
import { isEscape, KEY } from '../common/keys';
import { BooleanLike, classes } from '../common/react';
import styles from '../styles/components/Button.module.scss';
import { Box, BoxProps, computeBoxClassName, computeBoxProps } from './Box';
Expand Down Expand Up @@ -56,6 +56,8 @@ type Props = Partial<{
iconPosition: string;
/** Icon rotation */
iconRotation: number;
/** Icon size */
iconSize: number
/** Makes the icon spin */
iconSpin: BooleanLike;
/** Called when element is clicked */
Expand Down Expand Up @@ -89,6 +91,7 @@ export function Button(props: Props) {
iconColor,
iconPosition,
iconRotation,
iconSize,
iconSpin,
onClick,
selected,
Expand Down Expand Up @@ -140,7 +143,7 @@ export function Button(props: Props) {
}

// Refocus layout on pressing escape.
if (event.key === KEY.Escape) {
if (isEscape(event.key)) {
event.preventDefault();
}
}}
Expand All @@ -153,6 +156,7 @@ export function Button(props: Props) {
name={icon}
color={iconColor}
rotation={iconRotation}
size={iconSize}
spin={iconSpin}
/>
)}
Expand All @@ -171,6 +175,7 @@ export function Button(props: Props) {
name={icon}
color={iconColor}
rotation={iconRotation}
size={iconSize}
spin={iconSpin}
/>
)}
Expand Down Expand Up @@ -353,7 +358,7 @@ function ButtonInput(props: InputProps) {
commitResult(event);
return;
}
if (event.key === KEY.Escape) {
if (isEscape(event.key)) {
setInInput(false);
}
}}
Expand Down
14 changes: 12 additions & 2 deletions lib/components/Collapsible.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { Button } from './Button';
type Props = Partial<{
/** Buttons or other content to render inline with the button */
buttons: ReactNode;
/** Top margin of the child nodes, defaulted to 1 */
child_mt: number;
/** Icon to display with the collapsible */
icon: string;
/** Whether the collapsible is open */
Expand All @@ -16,7 +18,15 @@ type Props = Partial<{
BoxProps;

export function Collapsible(props: Props) {
const { children, color, title, buttons, icon, ...rest } = props;
const {
children,
child_mt = 1,
color,
title,
buttons,
icon,
...rest
} = props;
const [open, setOpen] = useState(props.open);

return (
Expand All @@ -37,7 +47,7 @@ export function Collapsible(props: Props) {
<div className="Table__cell Table__cell--collapsing">{buttons}</div>
)}
</div>
{open && <Box mt={1}>{children}</Box>}
{open && <Box mt={child_mt}>{children}</Box>}
</Box>
);
}
17 changes: 15 additions & 2 deletions lib/components/Input.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { KeyboardEvent, SyntheticEvent, useEffect, useRef } from 'react';

import { KEY } from '../common/keys';
import { isEscape, KEY } from '../common/keys';
import { classes } from '../common/react';
import { debounce } from '../common/timer';
import styles from '../styles/components/Input.module.scss';
Expand Down Expand Up @@ -122,7 +122,7 @@ export function Input(props: Props) {
return;
}

if (event.key === KEY.Escape) {
if (isEscape(event.key)) {
onEscape?.(event);

event.currentTarget.value = toInputValue(value);
Expand Down Expand Up @@ -150,6 +150,19 @@ export function Input(props: Props) {
}, 1);
}, []);

useEffect(() => {
const input = inputRef.current;
if (!input) return;

if (document.activeElement === input) {
return;
}

const newValue = toInputValue(value);

if (input.value !== newValue) input.value = newValue;
});

return (
<Box
className={classes([
Expand Down
9 changes: 7 additions & 2 deletions lib/components/NoticeBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Box, BoxProps } from './Box';
type Props = ExclusiveProps & BoxProps;

/** You MUST use only one or none */
type NoticeType = 'info' | 'success' | 'danger';
type NoticeType = 'info' | 'success' | 'warning' | 'danger';

type None = {
[K in NoticeType]?: undefined;
Expand All @@ -21,13 +21,17 @@ type ExclusiveProps =
/** Green notice */
success: boolean;
})
| (Omit<None, 'warning'> & {
/** Orange notice */
warning: boolean;
})
| (Omit<None, 'danger'> & {
/** Red notice */
danger: boolean;
});

export function NoticeBox(props: Props) {
const { className, color, info, success, danger, ...rest } = props;
const { className, color, info, success, warning, danger, ...rest } = props;

return (
<Box
Expand All @@ -36,6 +40,7 @@ export function NoticeBox(props: Props) {
color && styles['color__' + color],
info && styles.info,
success && styles.success,
warning && styles.warning,
danger && styles.danger,
className,
])}
Expand Down
4 changes: 2 additions & 2 deletions lib/components/NumberInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
RefObject,
} from 'react';

import { KEY } from '../common/keys';
import { isEscape, KEY } from '../common/keys';
import { clamp } from '../common/math';
import { BooleanLike, classes } from '../common/react';
import styles from '../styles/components/NumberInput.module.scss';
Expand Down Expand Up @@ -239,7 +239,7 @@ export class NumberInput extends Component<Props, State> {
onChange?.(targetValue);
onDrag?.(targetValue);
}
} else if (event.key === KEY.Escape) {
} else if (isEscape(event.key)) {
this.setState({
editing: false,
});
Expand Down
135 changes: 75 additions & 60 deletions lib/components/Section.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { forwardRef, ReactNode, RefObject, useEffect } from 'react';
import { ReactNode, useEffect, useRef } from 'react';

import { addScrollableNode, removeScrollableNode } from '../common/events';
import { canRender, classes } from '../common/react';
Expand All @@ -14,12 +14,18 @@ type Props = Partial<{
fill: boolean;
/** If true, removes all section padding. */
fitted: boolean;
/** If true, fills the area without forcing height to 100% */
flexGrow: boolean;
/** If true, removes the section top padding */
noTopPadding: boolean;
/** @member Callback function for the `scroll` event */
onScroll: ((this: GlobalEventHandlers, ev: Event) => any) | null;
/** Shows or hides the scrollbar. */
scrollable: boolean;
/** Shows or hides the horizontal scrollbar. */
scrollableHorizontal: boolean;
/** If true, filly the area except for -3rem */
stretchContents: boolean;
/** Title of the section. */
title: ReactNode;
}> &
Expand Down Expand Up @@ -52,69 +58,78 @@ type Props = Partial<{
* </Section>
* ```
*/
export const Section = forwardRef(
(props: Props, forwardedRef: RefObject<HTMLDivElement>) => {
const {
buttons,
children,
className,
fill,
fitted,
onScroll,
scrollable,
scrollableHorizontal,
title,
container_id,
...rest
} = props;
export const Section = (props: Props) => {
const {
buttons,
children,
className,
fill,
fitted,
flexGrow,
noTopPadding,
onScroll,
scrollable,
scrollableHorizontal,
stretchContents,
title,
container_id,
...rest
} = props;

const hasTitle = canRender(title) || canRender(buttons);
const node = useRef(null);

/** We want to be able to scroll on hover, but using focus will steal it from inputs */
useEffect(() => {
if (!forwardedRef?.current) return;
if (!scrollable && !scrollableHorizontal) return;
const hasTitle = canRender(title) || canRender(buttons);

addScrollableNode(forwardedRef.current);
/** We want to be able to scroll on hover, but using focus will steal it from inputs */
useEffect(() => {
if (!node?.current) return;
if (!scrollable && !scrollableHorizontal) return;
const self = node.current;

return () => {
if (!forwardedRef?.current) return;
removeScrollableNode(forwardedRef.current!);
};
}, []);
addScrollableNode(self);

return (
<div
id={container_id || ''}
className={classes([
styles.section,
fill && styles.fill,
fitted && styles.fitted,
scrollable && styles.scrollable,
scrollableHorizontal && styles.scrollableHorizontal,
className,
computeBoxClassName(rest),
])}
{...computeBoxProps(rest)}
>
{hasTitle && (
<div className={styles.title}>
<span className={styles.titleText}>{title}</span>
<div className={styles.buttons}>{buttons}</div>
</div>
)}
<div className={styles.rest}>
<div
className={styles.content}
onScroll={onScroll}
// For posterity: the forwarded ref needs to be here specifically
// to actually let things interact with the scrolling.
ref={forwardedRef}
>
{children}
</div>
return () => {
if (!self) return;
removeScrollableNode(self!);
};
}, []);

return (
<div
id={container_id || ''}
className={classes([
styles.section,
fill && styles.fill,
fitted && styles.fitted,
scrollable && styles.scrollable,
scrollableHorizontal && styles.scrollableHorizontal,
flexGrow && styles.sectionFlex,
className,
computeBoxClassName(rest),
])}
{...computeBoxProps(rest)}
>
{hasTitle && (
<div className={styles.title}>
<span className={styles.titleText}>{title}</span>
<div className={styles.buttons}>{buttons}</div>
</div>
)}
<div className={styles.rest}>
<div
className={classes([
styles.content,
!!stretchContents && styles.stretchContents,
!!noTopPadding && styles.noTopPadding,
])}
onScroll={onScroll}
// For posterity: the forwarded ref needs to be here specifically
// to actually let things interact with the scrolling.
ref={node}
>
{children}
</div>
</div>
);
},
);
</div>
);
};
13 changes: 12 additions & 1 deletion lib/components/Tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type TabProps = Partial<{
className: string;
color: string;
icon: string;
iconSpin: boolean;
leftSlot: ReactNode;
onClick: (e?) => void;
rightSlot: ReactNode;
Expand Down Expand Up @@ -52,12 +53,21 @@ function Tab(props: TabProps) {
selected,
color,
icon,
iconSpin,
leftSlot,
rightSlot,
children,
onClick,
...rest
} = props;

const handleClick = (e) => {
if (onClick) {
onClick(e);
e.target.blur();
}
};

return (
<div
className={classes([
Expand All @@ -68,14 +78,15 @@ function Tab(props: TabProps) {
className,
computeBoxClassName(rest),
])}
onClick={handleClick}
{...computeBoxProps(rest)}
>
{(canRender(leftSlot) && (
<div className={styles.tab__left}>{leftSlot}</div>
)) ||
(!!icon && (
<div className={styles.tab__left}>
<Icon name={icon} />
<Icon name={icon} spin={iconSpin} />
</div>
))}
<div className={styles.tab__text}>{children}</div>
Expand Down
Loading

0 comments on commit 893fcd3

Please sign in to comment.