From bdaa78b91970ebc49b6ca36ab3098f8553847f08 Mon Sep 17 00:00:00 2001 From: Matiss Janis Aboltins <matiss@mja.lv> Date: Sun, 2 Jul 2023 15:51:54 +0100 Subject: [PATCH] :recycle: moving some components from common.tsx to separate files (#1248) This is direct copy & paste with no changes. Just moving things a bit to reduce the size of the massive common.tsx file --- .../desktop-client/src/components/common.tsx | 225 +----------------- .../src/components/common/Block.tsx | 20 ++ .../src/components/common/Card.tsx | 41 ++++ .../src/components/common/HoverTarget.tsx | 54 +++++ .../src/components/common/InlineField.tsx | 45 ++++ .../src/components/common/Label.tsx | 31 +++ .../src/components/common/Select.tsx | 40 ++++ .../src/components/common/TextOneLine.tsx | 24 ++ upcoming-release-notes/1248.md | 6 + 9 files changed, 269 insertions(+), 217 deletions(-) create mode 100644 packages/desktop-client/src/components/common/Block.tsx create mode 100644 packages/desktop-client/src/components/common/Card.tsx create mode 100644 packages/desktop-client/src/components/common/HoverTarget.tsx create mode 100644 packages/desktop-client/src/components/common/InlineField.tsx create mode 100644 packages/desktop-client/src/components/common/Label.tsx create mode 100644 packages/desktop-client/src/components/common/Select.tsx create mode 100644 packages/desktop-client/src/components/common/TextOneLine.tsx create mode 100644 upcoming-release-notes/1248.md diff --git a/packages/desktop-client/src/components/common.tsx b/packages/desktop-client/src/components/common.tsx index 9e53e0b36..554b5c6bb 100644 --- a/packages/desktop-client/src/components/common.tsx +++ b/packages/desktop-client/src/components/common.tsx @@ -28,39 +28,26 @@ import ExpandArrow from '../icons/v0/ExpandArrow'; import { styles, colors } from '../style'; import type { HTMLPropsWithStyle } from '../types/utils'; +import Block from './common/Block'; import Button from './common/Button'; import Input, { defaultInputStyle } from './common/Input'; import Text from './common/Text'; import View from './common/View'; export { default as Modal, ModalButtons } from './common/Modal'; +export { default as Block } from './common/Block'; export { default as Button, ButtonWithLoading } from './common/Button'; +export { default as Card } from './common/Card'; +export { default as HoverTarget } from './common/HoverTarget'; +export { default as InlineField } from './common/InlineField'; export { default as Input } from './common/Input'; +export { default as Label } from './common/Label'; export { default as View } from './common/View'; export { default as Text } from './common/Text'; +export { default as TextOneLine } from './common/TextOneLine'; +export { default as Select } from './common/Select'; export { default as Stack } from './Stack'; -type TextOneLineProps = ComponentProps<typeof Text>; - -export function TextOneLine({ children, ...props }: TextOneLineProps) { - return ( - <Text - {...props} - style={[ - props.style, - { - overflow: 'hidden', - textOverflow: 'ellipsis', - whiteSpace: 'nowrap', - display: 'block', - }, - ]} - > - {children} - </Text> - ); -} - type UseStableCallbackArg = (...args: unknown[]) => unknown; export const useStableCallback = (callback: UseStableCallbackArg) => { @@ -75,55 +62,6 @@ export const useStableCallback = (callback: UseStableCallbackArg) => { return memoCallback; }; -type BlockProps = HTMLPropsWithStyle<HTMLDivElement> & { - innerRef?: Ref<HTMLDivElement>; -}; - -export function Block(props: BlockProps) { - const { style, innerRef, ...restProps } = props; - return ( - <div - {...restProps} - ref={innerRef} - className={`${props.className || ''} ${css(props.style)}`} - /> - ); -} - -type CardProps = ComponentProps<typeof View>; - -export const Card = forwardRef<HTMLDivElement, CardProps>( - ({ children, ...props }, ref) => { - return ( - <View - {...props} - ref={ref} - style={[ - { - marginTop: 15, - marginLeft: 5, - marginRight: 5, - borderRadius: 6, - backgroundColor: 'white', - borderColor: colors.p3, - boxShadow: '0 1px 2px #9594A8', - }, - props.style, - ]} - > - <View - style={{ - borderRadius: 6, - overflow: 'hidden', - }} - > - {children} - </View> - </View> - ); - }, -); - type LinkProps = ComponentProps<typeof Button>; export function LinkButton({ style, children, ...nativeProps }: LinkProps) { @@ -337,38 +275,6 @@ export function Search({ ); } -type SelectProps = HTMLPropsWithStyle<HTMLSelectElement>; - -export const Select = forwardRef<HTMLSelectElement, SelectProps>( - ({ style, children, ...nativeProps }, ref) => { - return ( - <select - ref={ref} - {...css( - { - backgroundColor: 'transparent', - height: 28, - fontSize: 14, - flex: 1, - border: '1px solid #d0d0d0', - borderRadius: 4, - color: colors.n1, - ':focus': { - border: '1px solid ' + colors.b5, - boxShadow: '0 1px 1px ' + colors.b7, - outline: 'none', - }, - }, - style, - )} - {...nativeProps} - > - {children} - </select> - ); - }, -); - type CustomSelectProps = { options: Array<[string, string]>; value: string; @@ -644,48 +550,6 @@ export function P({ style, isLast, children, ...props }: PProps) { ); } -type InlineFieldProps = { - label: ReactNode; - labelWidth?: number; - children?: ReactNode; - width: number; - style?: CSSProperties; -}; - -export function InlineField({ - label, - labelWidth, - children, - width, - style, -}: InlineFieldProps) { - return ( - <label - {...css( - { - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - margin: '7px 0', - width, - }, - style, - )} - > - <div - style={{ - width: labelWidth || 75, - textAlign: 'right', - paddingRight: 10, - }} - > - {label}: - </div> - {children} - </label> - ); -} - type FormErrorProps = { style?: CSSProperties; children?: ReactNode; @@ -724,78 +588,5 @@ export function InitialFocus({ children }: InitialFocusProps) { return cloneElement(children, { inputRef: node }); } -type HoverTargetProps = { - style?: CSSProperties; - contentStyle?: CSSProperties; - children: ReactNode; - renderContent: () => ReactNode; - disabled?: boolean; -}; - -export function HoverTarget({ - style, - contentStyle, - children, - renderContent, - disabled, -}: HoverTargetProps) { - let [hovered, setHovered] = useState(false); - - const onMouseEnter = useCallback(() => { - if (!disabled) { - setHovered(true); - } - }, [disabled]); - - const onMouseLeave = useCallback(() => { - if (!disabled) { - setHovered(false); - } - }, [disabled]); - - useEffect(() => { - if (disabled && hovered) { - setHovered(false); - } - }, [disabled, hovered]); - - return ( - <View style={style}> - <View - onMouseEnter={onMouseEnter} - onMouseLeave={onMouseLeave} - style={contentStyle} - > - {children} - </View> - {hovered && renderContent()} - </View> - ); -} - -type LabelProps = { - title: ReactNode; - style?: CSSProperties; -}; - -export function Label({ title, style }: LabelProps) { - return ( - <Text - style={[ - styles.text, - { - color: colors.n2, - textAlign: 'right', - fontSize: 12, - marginBottom: 2, - }, - style, - ]} - > - {title} - </Text> - ); -} - export * from './tooltips'; export { useTooltip } from './tooltips'; diff --git a/packages/desktop-client/src/components/common/Block.tsx b/packages/desktop-client/src/components/common/Block.tsx new file mode 100644 index 000000000..f986b1c2f --- /dev/null +++ b/packages/desktop-client/src/components/common/Block.tsx @@ -0,0 +1,20 @@ +import { type Ref } from 'react'; + +import { css } from 'glamor'; + +import type { HTMLPropsWithStyle } from '../../types/utils'; + +type BlockProps = HTMLPropsWithStyle<HTMLDivElement> & { + innerRef?: Ref<HTMLDivElement>; +}; + +export default function Block(props: BlockProps) { + const { style, innerRef, ...restProps } = props; + return ( + <div + {...restProps} + ref={innerRef} + className={`${props.className || ''} ${css(props.style)}`} + /> + ); +} diff --git a/packages/desktop-client/src/components/common/Card.tsx b/packages/desktop-client/src/components/common/Card.tsx new file mode 100644 index 000000000..dc9a3f2b8 --- /dev/null +++ b/packages/desktop-client/src/components/common/Card.tsx @@ -0,0 +1,41 @@ +import { type ComponentProps, forwardRef } from 'react'; + +import { colors } from '../../style'; + +import View from './View'; + +type CardProps = ComponentProps<typeof View>; + +const Card = forwardRef<HTMLDivElement, CardProps>( + ({ children, ...props }, ref) => { + return ( + <View + {...props} + ref={ref} + style={[ + { + marginTop: 15, + marginLeft: 5, + marginRight: 5, + borderRadius: 6, + backgroundColor: 'white', + borderColor: colors.p3, + boxShadow: '0 1px 2px #9594A8', + }, + props.style, + ]} + > + <View + style={{ + borderRadius: 6, + overflow: 'hidden', + }} + > + {children} + </View> + </View> + ); + }, +); + +export default Card; diff --git a/packages/desktop-client/src/components/common/HoverTarget.tsx b/packages/desktop-client/src/components/common/HoverTarget.tsx new file mode 100644 index 000000000..60f29f5b1 --- /dev/null +++ b/packages/desktop-client/src/components/common/HoverTarget.tsx @@ -0,0 +1,54 @@ +import { useCallback, useEffect, useState, type ReactNode } from 'react'; + +import { type CSSProperties } from 'glamor'; + +import View from './View'; + +type HoverTargetProps = { + style?: CSSProperties; + contentStyle?: CSSProperties; + children: ReactNode; + renderContent: () => ReactNode; + disabled?: boolean; +}; + +export default function HoverTarget({ + style, + contentStyle, + children, + renderContent, + disabled, +}: HoverTargetProps) { + let [hovered, setHovered] = useState(false); + + const onMouseEnter = useCallback(() => { + if (!disabled) { + setHovered(true); + } + }, [disabled]); + + const onMouseLeave = useCallback(() => { + if (!disabled) { + setHovered(false); + } + }, [disabled]); + + useEffect(() => { + if (disabled && hovered) { + setHovered(false); + } + }, [disabled, hovered]); + + return ( + <View style={style}> + <View + onMouseEnter={onMouseEnter} + onMouseLeave={onMouseLeave} + style={contentStyle} + > + {children} + </View> + {hovered && renderContent()} + </View> + ); +} diff --git a/packages/desktop-client/src/components/common/InlineField.tsx b/packages/desktop-client/src/components/common/InlineField.tsx new file mode 100644 index 000000000..b461bc472 --- /dev/null +++ b/packages/desktop-client/src/components/common/InlineField.tsx @@ -0,0 +1,45 @@ +import { type ReactNode } from 'react'; + +import { type CSSProperties, css } from 'glamor'; + +type InlineFieldProps = { + label: ReactNode; + labelWidth?: number; + children?: ReactNode; + width: number; + style?: CSSProperties; +}; + +export default function InlineField({ + label, + labelWidth, + children, + width, + style, +}: InlineFieldProps) { + return ( + <label + {...css( + { + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + margin: '7px 0', + width, + }, + style, + )} + > + <div + style={{ + width: labelWidth || 75, + textAlign: 'right', + paddingRight: 10, + }} + > + {label}: + </div> + {children} + </label> + ); +} diff --git a/packages/desktop-client/src/components/common/Label.tsx b/packages/desktop-client/src/components/common/Label.tsx new file mode 100644 index 000000000..895f4dcf0 --- /dev/null +++ b/packages/desktop-client/src/components/common/Label.tsx @@ -0,0 +1,31 @@ +import { type ReactNode } from 'react'; + +import { type CSSProperties } from 'glamor'; + +import { colors, styles } from '../../style'; + +import Text from './Text'; + +type LabelProps = { + title: ReactNode; + style?: CSSProperties; +}; + +export default function Label({ title, style }: LabelProps) { + return ( + <Text + style={[ + styles.text, + { + color: colors.n2, + textAlign: 'right', + fontSize: 12, + marginBottom: 2, + }, + style, + ]} + > + {title} + </Text> + ); +} diff --git a/packages/desktop-client/src/components/common/Select.tsx b/packages/desktop-client/src/components/common/Select.tsx new file mode 100644 index 000000000..ab951b246 --- /dev/null +++ b/packages/desktop-client/src/components/common/Select.tsx @@ -0,0 +1,40 @@ +import { forwardRef } from 'react'; + +import { css } from 'glamor'; + +import { colors } from '../../style'; +import type { HTMLPropsWithStyle } from '../../types/utils'; + +type SelectProps = HTMLPropsWithStyle<HTMLSelectElement>; + +const Select = forwardRef<HTMLSelectElement, SelectProps>( + ({ style, children, ...nativeProps }, ref) => { + return ( + <select + ref={ref} + {...css( + { + backgroundColor: 'transparent', + height: 28, + fontSize: 14, + flex: 1, + border: '1px solid #d0d0d0', + borderRadius: 4, + color: colors.n1, + ':focus': { + border: '1px solid ' + colors.b5, + boxShadow: '0 1px 1px ' + colors.b7, + outline: 'none', + }, + }, + style, + )} + {...nativeProps} + > + {children} + </select> + ); + }, +); + +export default Select; diff --git a/packages/desktop-client/src/components/common/TextOneLine.tsx b/packages/desktop-client/src/components/common/TextOneLine.tsx new file mode 100644 index 000000000..a928c102a --- /dev/null +++ b/packages/desktop-client/src/components/common/TextOneLine.tsx @@ -0,0 +1,24 @@ +import { type ComponentProps } from 'react'; + +import Text from './Text'; + +type TextOneLineProps = ComponentProps<typeof Text>; + +export default function TextOneLine({ children, ...props }: TextOneLineProps) { + return ( + <Text + {...props} + style={[ + props.style, + { + overflow: 'hidden', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + display: 'block', + }, + ]} + > + {children} + </Text> + ); +} diff --git a/upcoming-release-notes/1248.md b/upcoming-release-notes/1248.md new file mode 100644 index 000000000..d234bbbdd --- /dev/null +++ b/upcoming-release-notes/1248.md @@ -0,0 +1,6 @@ +--- +category: Maintenance +authors: [MatissJanis] +--- + +Moving some components from `common.tsx` to separate files inside the `common` folder -- GitLab