diff --git a/constants/Layout.ts b/constants/Layout.ts index d6c94cd..524f871 100644 --- a/constants/Layout.ts +++ b/constants/Layout.ts @@ -9,13 +9,13 @@ const pixelRatio = PixelRatio.get(); export const baselineHeight = 680; export const baselineWidth = 350; -export const defaultFontSize = 8 * pixelRatio +export const defaultFontSize = 4 * pixelRatio; export default { window: { width, height, }, - pixelRatio, + defaultFontSize, isSmallDevice: width < 375, }; diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx index 6fb088f..87911d6 100644 --- a/src/components/Button/Button.tsx +++ b/src/components/Button/Button.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { ReactNode } from 'react'; import { LayoutChangeEvent, PressableAndroidRippleConfig, Rect } from 'react-native'; // import UnstyledIcon from '@mdi/react'; // import { mdiLoading } from '@mdi/js'; @@ -13,13 +13,9 @@ import { FoundryContextType, useTheme } from '../../context'; import variants from '../../enums/variants'; // import Progress from '../Progress/Progress'; import { View, Button as ButtonElement, Text } from '../../baseElements'; -import { - getFontColorFromVariant, - getBackgroundColorFromVariant, - disabledStyles, -} from '../../utils/color'; +import { getFontColorFromVariant, getBackgroundColorFromVariant } from '../../utils/color'; import { SubcomponentPropsType } from '../commonTypes'; -import { getShadowStyle } from '../../utils/styles'; +import { getShadowStyle, getTextChildren } from '../../utils/styles'; // import InteractionFeedback from '../InteractionFeedback'; // import { InteractionFeedbackProps } from '../InteractionFeedback/InteractionFeedback'; import FeedbackTypes from '../../enums/feedbackTypes'; @@ -36,6 +32,13 @@ export type ButtonContainerProps = { feedbackType: FeedbackTypes; }; +export type TextContainerProps = { + theme: FoundryContextType; + color: string; + variant: variants; + disabled: boolean; +}; + export enum ButtonTypes { button = 'button', reset = 'reset', @@ -44,14 +47,16 @@ export enum ButtonTypes { export type ButtonProps = { StyledContainer?: string & StyledComponentBase; + StyledTextContainer?: string & StyledComponentBase; StyledLeftIconContainer?: StyledComponentBase; StyledRightIconContainer?: StyledComponentBase; containerProps?: SubcomponentPropsType; + textContainerProps?: SubcomponentPropsType; iconPrefix?: string | JSX.Element; iconSuffix?: string | JSX.Element; isLoading?: boolean; isProcessing?: boolean; - children?: string; + children?: ReactNode[]; elevation?: number; variant?: variants; type?: ButtonTypes; @@ -66,6 +71,7 @@ export type ButtonProps = { LoadingBar?: string & StyledComponentBase; id?: string; containerRef?: React.RefObject; + textContainerRef?: React.RefObject; leftIconContainerRef?: React.RefObject; rightIconContainerRef?: React.RefObject; loadingBarRef?: React.RefObject; @@ -103,10 +109,21 @@ export const ButtonContainer: string & StyledComponentBase = styled( + Text, +)` + ${({ theme, color, variant }: TextContainerProps) => { + const { colors, scale } = theme; + const fontColor = getFontColorFromVariant(variant, color, colors.background, colors.grayDark); + return ` + font-size: ${remToPx(1, scale)}px; + padding: 0px; + color: ${fontColor}; + `; }} `; @@ -135,14 +152,16 @@ const RightIconContainer = styled(IconContainer)` const Button = ({ StyledContainer = ButtonContainer, + StyledTextContainer = TextContainer, StyledLeftIconContainer = LeftIconContainer, StyledRightIconContainer = RightIconContainer, containerProps = {}, + textContainerProps = {}, iconPrefix, iconSuffix, isLoading, isProcessing, - children, + children = [], elevation = 0, hitSlop = 6, android_ripple, @@ -156,6 +175,7 @@ const Button = ({ // LoadingBar = StyledProgress, id, containerRef, + textContainerRef, leftIconContainerRef, rightIconContainerRef, loadingBarRef, @@ -184,6 +204,11 @@ const Button = ({ ...android_ripple, }; + const textChildren = getTextChildren(children); + // const nonTextChildren = React.Children.toArray(children).filter(child => + // !textChildren.includes(child), + // ); + // get everything we expose + anything consumer wants to send to container const mergedContainerProps = { 'data-test-id': 'hsui-button', @@ -205,6 +230,16 @@ const Button = ({ const { colors, scale } = theme; + const mergedTextContainerProps = { + 'data-test-id': 'hsui-button-text', + color: containerColor, + variant, + type, + disabled, + theme, + ...textContainerProps, + }; + const buttonContent = isLoading ? ( // @@ -224,8 +259,13 @@ const Button = ({ )} - {/* // TODO: make Text an exported subcomponent */} - {children} + {textChildren && ( + + {textChildren} + + )} + {/* TODO: decide how/if we want to support them passing in a mixture text/nonText children */} + {/* {nonTextChildren && {nonTextChildren}} */} {iconSuffix && (typeof iconSuffix === 'string' ? ( @@ -247,6 +287,7 @@ const Button = ({ }; Button.Container = ButtonContainer; +Button.TextContainer = TextContainer; Button.ButtonTypes = ButtonTypes; // Button.LoadingBar = StyledProgress; Button.LeftIconContainer = LeftIconContainer; diff --git a/src/utils/styles.ts b/src/utils/styles.ts index 41677f7..9fe313b 100644 --- a/src/utils/styles.ts +++ b/src/utils/styles.ts @@ -1,4 +1,5 @@ -import { Platform } from 'react-native'; +import React, { ReactNode } from 'react'; +import { Platform, Text } from 'react-native'; import { parseToRgb } from 'polished'; import variants from '../enums/variants'; import { getFontColorFromVariant } from './color'; @@ -21,11 +22,18 @@ export type ElevationValues = { * @param {number} [factor = 1] - The factor to scale by * @returns {number} The scaled px value */ -export const remToPx = (size: number, factor = 1) => { - if (!size) return 0; +export const remToPx = (size: number, factor = 1) => + defaultFontSize * (size + factor * ((Layout.window.width / baselineWidth) * size - size)); - return defaultFontSize * (size + factor * ((Layout.window.width / baselineWidth) * size - size)); -}; +/** + * Gets all text container stylable children + * @param {ReactNode []} children - The children object + * @returns {ReactNode []} The children that are capable of being directly nested in a Text container + */ +export const getTextChildren = (children: ReactNode[]): ReactNode[] => + React.Children.toArray(children).filter( + child => typeof child === 'string' || (child && child.type && child.type === Text), + ); /** * Calculates the values for shadows based on the provided elevation diff --git a/yarn.lock b/yarn.lock index 966bf51..3e32b4a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13768,7 +13768,7 @@ react-sizeme@^2.6.7: shallowequal "^1.1.0" throttle-debounce "^2.1.0" -react-spring@^9.2.4: +react-spring@^9.2.3: version "9.2.4" resolved "https://registry.yarnpkg.com/react-spring/-/react-spring-9.2.4.tgz#9d89b0321664d594f957dca9459b13d94b3dfa39" integrity sha512-bMjbyTW0ZGd+/h9cjtohLqCwOGqX2OuaTvalOVfLCGmhzEg/u3GgopI3LAm4UD2Br3MNdVdGgNVoESg4MGqKFQ== @@ -16191,10 +16191,8 @@ watchpack@^1.7.4: resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.5.tgz#1267e6c55e0b9b5be44c2023aed5437a2c26c453" integrity sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ== dependencies: - chokidar "^3.4.1" graceful-fs "^4.1.2" neo-async "^2.5.0" - watchpack-chokidar2 "^2.0.1" optionalDependencies: chokidar "^3.4.1" watchpack-chokidar2 "^2.0.1"