diff --git a/.changeset/honest-beers-learn.md b/.changeset/honest-beers-learn.md new file mode 100644 index 000000000..cba1a2be3 --- /dev/null +++ b/.changeset/honest-beers-learn.md @@ -0,0 +1,7 @@ +--- +"@interlay/ui": patch +"@interlay/hooks": patch +"@interlay/theme": patch +--- + +Fix/design system diff --git a/packages/components/src/Card/Card.style.tsx b/packages/components/src/Card/Card.style.tsx index c8308921a..e87210862 100644 --- a/packages/components/src/Card/Card.style.tsx +++ b/packages/components/src/Card/Card.style.tsx @@ -24,7 +24,7 @@ const StyledCard = styled(Flex)` const { border, boxShadow, backgroundColor, ...baseCss } = theme.card.base; return css` - border: ${typeof $bordered === 'boolean' ? border : `1px solid ${$bordered}`}; + border: ${typeof $bordered === 'boolean' ? border : `1px solid ${theme.color($bordered)}`}; box-shadow: ${$shadowed && boxShadow}; background-color: ${$background ? theme.color($background) : backgroundColor}; ${baseCss} diff --git a/packages/components/src/Card/Card.tsx b/packages/components/src/Card/Card.tsx index 859072189..c971b9c04 100644 --- a/packages/components/src/Card/Card.tsx +++ b/packages/components/src/Card/Card.tsx @@ -36,7 +36,7 @@ const Card = forwardRef( elementType, isDisabled, rounded = 'xl', - padding = 'md', + padding = 'xl', shadowed = false, bordered = true, ...props diff --git a/packages/components/src/Flex/Flex.stories.tsx b/packages/components/src/Flex/Flex.stories.tsx index 6fc61a05f..c68775455 100644 --- a/packages/components/src/Flex/Flex.stories.tsx +++ b/packages/components/src/Flex/Flex.stories.tsx @@ -5,7 +5,6 @@ import { Flex, FlexProps } from '.'; export default { title: 'Layout/Flex', component: Flex, - args: { gap: 'md' }, diff --git a/packages/components/src/Flex/Flex.style.tsx b/packages/components/src/Flex/Flex.style.tsx index cec5757f1..49d91a58d 100644 --- a/packages/components/src/Flex/Flex.style.tsx +++ b/packages/components/src/Flex/Flex.style.tsx @@ -1,30 +1,35 @@ -import type { AlignItems, AlignSelf, Direction, JustifyContent, Spacing, Wrap } from '@interlay/theme'; +import type { AlignItems, AlignSelf, Direction, JustifyContent, ResponsiveProp, Spacing, Wrap } from '@interlay/theme'; import { styled } from 'styled-components'; -import { StyledMarginProps } from '@interlay/hooks'; +import { StyledMarginProps, StyledPaddingProps } from '@interlay/hooks'; +import { paddingCSS } from '../utils/padding'; import { marginCSS } from '../utils/margin'; +import { getResponsiveCSS, getSpacingResponsiveCSS } from '../utils/responsive'; type StyledFlexProps = { - $gap?: Spacing; - $justifyContent?: JustifyContent; - $alignItems?: AlignItems; - $direction?: Direction; - $flex?: string | number; - $wrap?: Wrap; - $alignSelf?: AlignSelf; -} & StyledMarginProps; + $gap?: ResponsiveProp; + $justifyContent?: ResponsiveProp; + $alignItems?: ResponsiveProp; + $direction?: ResponsiveProp; + $flex?: ResponsiveProp; + $wrap?: ResponsiveProp; + $alignSelf?: ResponsiveProp; +} & StyledMarginProps & + StyledPaddingProps; const StyledFlex = styled.div` display: flex; - flex-direction: ${(props) => props.$direction}; - justify-content: ${(props) => props.$justifyContent}; - align-items: ${(props) => props.$alignItems}; - gap: ${({ theme, $gap }) => $gap && theme.spacing($gap)}; - flex: ${(props) => props.$flex}; - flex-wrap: ${(props) => (typeof props.$wrap === 'boolean' ? 'wrap' : props.$wrap)}; align-self: ${(props) => props.$alignSelf}; ${(props) => marginCSS(props)}; + ${(props) => paddingCSS(props)}; + ${({ $gap, theme }) => getSpacingResponsiveCSS(theme, 'gap', $gap)} + ${({ $justifyContent, theme }) => getResponsiveCSS(theme, 'justify-content', $justifyContent)} + ${({ $alignItems, theme }) => getResponsiveCSS(theme, 'align-items', $alignItems)} + ${({ $flex, theme }) => getResponsiveCSS(theme, 'flex', $flex)} + ${({ $wrap, theme }) => + getResponsiveCSS(theme, 'flex-wrap', $wrap, (prop) => (typeof prop === 'boolean' ? 'wrap' : prop))} + ${({ $alignSelf, theme }) => getResponsiveCSS(theme, 'align-self', $alignSelf)} `; export { StyledFlex }; diff --git a/packages/components/src/Flex/Flex.tsx b/packages/components/src/Flex/Flex.tsx index ef3f58710..30146b182 100644 --- a/packages/components/src/Flex/Flex.tsx +++ b/packages/components/src/Flex/Flex.tsx @@ -2,25 +2,35 @@ import type { HTMLAttributes } from 'react'; import { forwardRef } from 'react'; import { useStyleProps } from '@interlay/hooks'; -import { AlignItems, AlignSelf, Direction, JustifyContent, MarginProps, Spacing, Wrap } from '@interlay/theme'; +import { + AlignItems, + AlignSelf, + Direction, + JustifyContent, + MarginProps, + PaddingProps, + ResponsiveProp, + Spacing, + Wrap +} from '@interlay/theme'; import { ElementTypeProp } from '../utils/types'; import { StyledFlex } from './Flex.style'; type Props = { - gap?: Spacing; - justifyContent?: JustifyContent; - alignItems?: AlignItems; - direction?: Direction; - flex?: string | number; - wrap?: Wrap | boolean; - alignSelf?: AlignSelf; + gap?: ResponsiveProp; + justifyContent?: ResponsiveProp; + alignItems?: ResponsiveProp; + direction?: ResponsiveProp; + flex?: ResponsiveProp; + wrap?: ResponsiveProp; + alignSelf?: ResponsiveProp; }; type NativeAttrs = Omit, keyof Props>; -type FlexProps = Props & NativeAttrs & ElementTypeProp & MarginProps; +type FlexProps = Props & NativeAttrs & ElementTypeProp & MarginProps & PaddingProps; const Flex = forwardRef( ( diff --git a/packages/components/src/Text/Dl/Dt.tsx b/packages/components/src/Text/Dl/Dt.tsx index d1f852d41..8c9328eb5 100644 --- a/packages/components/src/Text/Dl/Dt.tsx +++ b/packages/components/src/Text/Dl/Dt.tsx @@ -7,7 +7,9 @@ import { mapTextProps } from '../utils'; type DtProps = TextProps; const Dt = forwardRef( - ({ color = 'light', ...props }, ref): JSX.Element => + ({ color = 'grey-200', ...props }, ref): JSX.Element => ( + + ) ); Dt.displayName = 'Dt'; diff --git a/packages/components/src/Text/style.tsx b/packages/components/src/Text/style.tsx index 56a872c06..9d5e4f970 100644 --- a/packages/components/src/Text/style.tsx +++ b/packages/components/src/Text/style.tsx @@ -3,19 +3,22 @@ import styled, { css } from 'styled-components'; type StyledTextProps = { $color: Color | 'inherit'; - $size: Typography; - $weight: FontWeight; + $size: Typography | 'inherit'; + $weight: FontWeight | 'inherit'; $align?: NormalAlignments; $rows?: number; $noWrap?: boolean; + $fontFamily?: string; }; const Text = styled.p` - ${({ theme, $size }) => theme.typography($size)} - color: ${({ theme, $color }) => ($color === 'inherit' ? 'inherit' : theme.color($color))}; - font-weight: ${({ theme, $weight }) => theme.fontWeight($weight)}; + ${({ theme, $size }) => + $size === 'inherit' ? { fontSize: 'inherit', lineHeight: 'inherit' } : theme.typography($size)} + color: ${({ theme, $color }) => ($color === 'inherit' ? $color : theme.color($color))}; + font-weight: ${({ theme, $weight }) => ($weight === 'inherit' ? $weight : theme.fontWeight($weight))}; text-align: ${({ $align }) => $align}; white-space: ${({ $noWrap }) => $noWrap && 'nowrap'}; + font-family: ${({ $fontFamily }) => $fontFamily}; ${({ $rows }) => $rows && diff --git a/packages/components/src/Text/types.ts b/packages/components/src/Text/types.ts index 245489dd5..0498970db 100644 --- a/packages/components/src/Text/types.ts +++ b/packages/components/src/Text/types.ts @@ -10,6 +10,7 @@ type Props = { weight?: FontWeight; rows?: number; noWrap?: boolean; + fontFamily?: string; }; type NativeAttrs = Omit, keyof Props>; diff --git a/packages/components/src/Text/utils.ts b/packages/components/src/Text/utils.ts index f501af359..a05aeeb85 100644 --- a/packages/components/src/Text/utils.ts +++ b/packages/components/src/Text/utils.ts @@ -8,15 +8,17 @@ const mapTextProps = ({ align, rows, noWrap, + fontFamily, ...props -}: T): Omit & StyledTextProps => ({ +}: T): Omit & StyledTextProps => ({ ...props, $color: color, $size: size, $weight: weight, $align: align, $rows: rows, - $noWrap: noWrap + $noWrap: noWrap, + $fontFamily: fontFamily }); export { mapTextProps }; diff --git a/packages/components/src/utils/margin.ts b/packages/components/src/utils/margin.ts index b3e052821..116a35a40 100644 --- a/packages/components/src/utils/margin.ts +++ b/packages/components/src/utils/margin.ts @@ -1,5 +1,7 @@ import { css } from 'styled-components'; +import { getSpacingResponsiveCSS } from './responsive'; + const marginCSS = ({ theme, ...props }: any) => { const marginTop = props.$marginTop || props.$marginY; const marginBottom = props.$marginBottom || props.$marginY; @@ -7,11 +9,11 @@ const marginCSS = ({ theme, ...props }: any) => { const marginRight = props.$marginRight || props.$marginX; return css` - margin: ${props.$margin && theme.spacing(props.$margin)}; - margin-top: ${marginTop && theme.spacing(marginTop)}; - margin-bottom: ${marginBottom && theme.spacing(marginBottom)}; - margin-left: ${marginLeft && theme.spacing(marginLeft)}; - margin-right: ${marginRight && theme.spacing(marginRight)}; + ${getSpacingResponsiveCSS(theme, 'margin', props.$margin)} + ${getSpacingResponsiveCSS(theme, 'margin-top', marginTop)} + ${getSpacingResponsiveCSS(theme, 'margin-bottom', marginBottom)} + ${getSpacingResponsiveCSS(theme, 'margin-left', marginLeft)} + ${getSpacingResponsiveCSS(theme, 'margin-right', marginRight)} `; }; diff --git a/packages/components/src/utils/padding.ts b/packages/components/src/utils/padding.ts new file mode 100644 index 000000000..d3c565357 --- /dev/null +++ b/packages/components/src/utils/padding.ts @@ -0,0 +1,20 @@ +import { css } from 'styled-components'; + +import { getSpacingResponsiveCSS } from './responsive'; + +const paddingCSS = ({ theme, ...props }: any) => { + const paddingTop = props.$paddingTop || props.$paddingY; + const paddingBottom = props.$paddingBottom || props.$paddingY; + const paddingLeft = props.$paddingLeft || props.$paddingX; + const paddingRight = props.$paddingRight || props.$paddingX; + + return css` + ${getSpacingResponsiveCSS(theme, 'padding', props.$padding)} + ${getSpacingResponsiveCSS(theme, 'padding-top', paddingTop)} + ${getSpacingResponsiveCSS(theme, 'padding-bottom', paddingBottom)} + ${getSpacingResponsiveCSS(theme, 'padding-left', paddingLeft)} + ${getSpacingResponsiveCSS(theme, 'padding-right', paddingRight)} + `; +}; + +export { paddingCSS }; diff --git a/packages/components/src/utils/responsive.ts b/packages/components/src/utils/responsive.ts index 1d35c5201..ef1d3494e 100644 --- a/packages/components/src/utils/responsive.ts +++ b/packages/components/src/utils/responsive.ts @@ -1,25 +1,31 @@ -import { theme, BreakPoints, ResponsiveProp } from '@interlay/theme'; +import { ResponsiveProp, Spacing } from '@interlay/theme'; +import { DefaultTheme, css } from 'styled-components'; -const getResponsiveCSS = (key: string, prop?: ResponsiveProp): string | undefined => { - if (!prop) return undefined; +const getSpacingResponsiveCSS = (theme: DefaultTheme, attribute: string, prop?: ResponsiveProp) => + typeof prop === 'object' + ? css` + ${prop.xs && theme.breakpoints.media.xs`${attribute}: ${theme.spacing(prop.xs)};`} + ${prop.s && theme.breakpoints.media.s`${attribute}: ${theme.spacing(prop.s)};`} + ${prop.md && theme.breakpoints.media.md`${attribute}: ${theme.spacing(prop.md)};`} + ${prop.lg && theme.breakpoints.media.lg`${attribute}: ${theme.spacing(prop.lg)};`} + ${prop.xl && theme.breakpoints.media.xl`${attribute}: ${theme.spacing(prop.xl)};`} + ` + : prop && `${attribute}:${theme.spacing(prop)};`; - if (typeof prop === 'object') { - let finalQuery = ''; +const getResponsiveCSS = ( + theme: DefaultTheme, + attribute: string, + prop?: ResponsiveProp, + condition?: (prop: string | number | boolean) => string | number +) => + typeof prop === 'object' + ? css` + ${prop.xs && theme.breakpoints.media.xs`${attribute}: ${condition ? condition(prop.xs) : prop.xs};`} + ${prop.s && theme.breakpoints.media.s`${attribute}: ${condition ? condition(prop.s) : prop.s};`} + ${prop.md && theme.breakpoints.media.md`${attribute}: ${condition ? condition(prop.md) : prop.md};`} + ${prop.lg && theme.breakpoints.media.lg`${attribute}: ${condition ? condition(prop.lg) : prop.lg};`} + ${prop.xl && theme.breakpoints.media.xl`${attribute}: ${condition ? condition(prop.xl) : prop.xl};`} + ` + : prop && `${attribute}:${prop};`; - for (const breakpoint of Object.keys(prop)) { - const query = ` - @media (min-width: ${theme.breakpoints.values[breakpoint as BreakPoints]}px){ - ${key}: ${prop[breakpoint as BreakPoints]}; - } - `; - - finalQuery = finalQuery.concat(query); - } - - return finalQuery; - } - - return `${key}: ${prop};`; -}; - -export { getResponsiveCSS }; +export { getResponsiveCSS, getSpacingResponsiveCSS }; diff --git a/packages/core/theme/src/core/breakpoints.ts b/packages/core/theme/src/core/breakpoints.ts index e7abff6b4..94dcfae5a 100644 --- a/packages/core/theme/src/core/breakpoints.ts +++ b/packages/core/theme/src/core/breakpoints.ts @@ -1,10 +1,13 @@ -type BreakPoints = 'xs' | 'sm' | 'md' | 'lg' | 'xl'; +// @ts-nocheck +import { css } from 'styled-components'; -type ResponsiveProp = T | Partial<{ [K in BreakPoints]: T }>; +type BreakPoints = 'xs' | 's' | 'md' | 'lg' | 'xl'; + +type ResponsiveProp = T | Partial<{ [K in BreakPoints]: T }>; const values: Record = { xs: 0, // phone - sm: 600, // tablet + s: 600, // tablet md: 900, // small laptop lg: 1200, // desktop xl: 1536 // large screen @@ -13,7 +16,34 @@ const values: Record = { const breakpoints = { values, up: (key: BreakPoints): string => `(min-width:${values[key]}px)`, - down: (key: BreakPoints): string => `(max-width:${values[key]}px)` + down: (key: BreakPoints): string => `(max-width:${values[key]}px)`, + media: { + xs: (...args) => css` + @media (min-width: ${values.xs}px) { + ${css(...args)}; + } + `, + s: (...args) => css` + @media (min-width: ${values.s}px) { + ${css(...args)}; + } + `, + md: (...args) => css` + @media (min-width: ${values.md}px) { + ${css(...args)}; + } + `, + lg: (...args) => css` + @media (min-width: ${values.lg}px) { + ${css(...args)}; + } + `, + xl: (...args) => css` + @media (min-width: ${values.xl}px) { + ${css(...args)}; + } + ` + } }; export { breakpoints }; diff --git a/packages/core/theme/src/core/index.ts b/packages/core/theme/src/core/index.ts index d98c541f9..134577479 100644 --- a/packages/core/theme/src/core/index.ts +++ b/packages/core/theme/src/core/index.ts @@ -1,3 +1,4 @@ +import { ResponsiveProp } from './breakpoints'; import { Spacing } from './space'; export type Status = 'error' | 'warning' | 'success'; @@ -27,13 +28,23 @@ export type AlignSelf = export type Placement = 'top' | 'right' | 'bottom' | 'left'; export interface MarginProps { - margin?: Spacing; - marginTop?: Spacing; - marginBottom?: Spacing; - marginLeft?: Spacing; - marginRight?: Spacing; - marginX?: Spacing; - marginY?: Spacing; + margin?: ResponsiveProp; + marginTop?: ResponsiveProp; + marginBottom?: ResponsiveProp; + marginLeft?: ResponsiveProp; + marginRight?: ResponsiveProp; + marginX?: ResponsiveProp; + marginY?: ResponsiveProp; +} + +export interface PaddingProps { + padding?: ResponsiveProp; + paddingTop?: ResponsiveProp; + paddingBottom?: ResponsiveProp; + paddingLeft?: ResponsiveProp; + paddingRight?: ResponsiveProp; + paddingX?: ResponsiveProp; + paddingY?: ResponsiveProp; } export type Orientation = 'horizontal' | 'vertical'; diff --git a/packages/core/theme/src/define.ts b/packages/core/theme/src/define.ts index f13e0b1b8..71ab3802b 100644 --- a/packages/core/theme/src/define.ts +++ b/packages/core/theme/src/define.ts @@ -42,7 +42,7 @@ const baseTheme = { typography, transition, maxWidth, - ...breakpoints + breakpoints }; type ThemeParams = { diff --git a/packages/core/theme/src/index.ts b/packages/core/theme/src/index.ts index 2cee7a78c..a671aa41b 100644 --- a/packages/core/theme/src/index.ts +++ b/packages/core/theme/src/index.ts @@ -38,7 +38,9 @@ export type { Overflow, Placement, Status, - Wrap + Wrap, + ResponsiveProp, + PaddingProps } from './core'; export { bobTheme } from './themes'; export type { Theme } from './define'; diff --git a/packages/hooks/src/index.ts b/packages/hooks/src/index.ts index 6b40e33ff..4f7a6020b 100644 --- a/packages/hooks/src/index.ts +++ b/packages/hooks/src/index.ts @@ -1,6 +1,12 @@ export { useMediaQuery } from './use-media-query'; export { useStyleProps } from './use-style-props'; export * from './use-form'; -export type { MarginProps, StyleProps, UseStylePropsResult, StyledMarginProps } from './use-style-props'; +export type { + MarginProps, + StyleProps, + UseStylePropsResult, + StyledMarginProps, + StyledPaddingProps +} from './use-style-props'; export { useDOMRef } from './use-dom-ref'; export * from './use-currency-formatter'; diff --git a/packages/hooks/src/use-style-props.tsx b/packages/hooks/src/use-style-props.tsx index 8bc8792b8..40255b446 100644 --- a/packages/hooks/src/use-style-props.tsx +++ b/packages/hooks/src/use-style-props.tsx @@ -1,29 +1,39 @@ -import { Spacing } from '@interlay/theme'; - -type MarginProps = { - margin?: Spacing; - marginTop?: Spacing; - marginBottom?: Spacing; - marginLeft?: Spacing; - marginRight?: Spacing; - marginX?: Spacing; - marginY?: Spacing; -}; +import { MarginProps, PaddingProps } from '@interlay/theme'; type StyledMarginProps = { [K in keyof MarginProps as `$${string & K}`]: MarginProps[K]; }; -type StyleProps = StyledMarginProps; +type StyledPaddingProps = { + [K in keyof PaddingProps as `$${string & K}`]: PaddingProps[K]; +}; + +type StyleProps = StyledMarginProps & StyledPaddingProps; -type ComponentProps> = Omit; +type ComponentProps> = Omit; type UseStylePropsResult> = { styleProps: StyleProps; componentProps: ComponentProps }; // Extracts props that are solely for styling so that they get mapped to styled props // This approach is used for a set of styling props that could be reused across different component const useStyleProps = >(props: T): UseStylePropsResult => { - const { margin, marginTop, marginBottom, marginLeft, marginRight, marginX, marginY, ...componentProps } = props; + const { + margin, + marginTop, + marginBottom, + marginLeft, + marginRight, + marginX, + marginY, + padding, + paddingLeft, + paddingRight, + paddingTop, + paddingBottom, + paddingX, + paddingY, + ...componentProps + } = props; return { styleProps: { @@ -33,11 +43,18 @@ const useStyleProps = >(props: T): UseStylePropsRe $marginLeft: marginLeft, $marginRight: marginRight, $marginX: marginX, - $marginY: marginY + $marginY: marginY, + $padding: padding, + $paddingBottom: paddingBottom, + $paddingLeft: paddingLeft, + $paddingRight: paddingRight, + $paddingTop: paddingTop, + $paddingX: paddingX, + $paddingY: paddingY }, componentProps }; }; -export type { StyleProps, UseStylePropsResult, StyledMarginProps, MarginProps }; export { useStyleProps }; +export type { MarginProps, StyleProps, StyledMarginProps, UseStylePropsResult, StyledPaddingProps };