From ddd04da13f993d944021f412c8587b52d8c780e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sim=C3=A3o?= Date: Fri, 19 Apr 2024 16:14:33 +0100 Subject: [PATCH] feat: theme radio, icon size, card fix (#89) --- .changeset/loud-melons-cough.md | 7 ++ packages/components/src/Card/Card.tsx | 3 +- packages/components/src/Radio/Radio.style.tsx | 54 +++++++------ packages/components/src/Radio/Radio.tsx | 8 +- .../components/src/Radio/RadioContext.tsx | 5 +- packages/components/src/Radio/RadioGroup.tsx | 7 +- packages/core/theme/src/components/radio.ts | 19 ++++- packages/core/theme/src/core/icon.ts | 6 +- packages/core/theme/src/index.ts | 3 +- packages/core/theme/src/themes/bob/radio.ts | 80 ++++++++++++++++++- packages/icons/src/ArrowLongRight.tsx | 2 +- 11 files changed, 154 insertions(+), 40 deletions(-) create mode 100644 .changeset/loud-melons-cough.md diff --git a/.changeset/loud-melons-cough.md b/.changeset/loud-melons-cough.md new file mode 100644 index 000000000..3c660133e --- /dev/null +++ b/.changeset/loud-melons-cough.md @@ -0,0 +1,7 @@ +--- +"@interlay/ui": patch +"@interlay/icons": patch +"@interlay/theme": patch +--- + +feat: theme radio, icon size, card fix diff --git a/packages/components/src/Card/Card.tsx b/packages/components/src/Card/Card.tsx index 028a386e9..5640c9e55 100644 --- a/packages/components/src/Card/Card.tsx +++ b/packages/components/src/Card/Card.tsx @@ -38,13 +38,14 @@ const Card = forwardRef( padding = 'xl', shadowed = false, bordered = true, + onPress, ...props }, ref ): JSX.Element => { const cardRef = useDOMRef(ref); const { buttonProps } = useButton( - { elementType: elementType || 'div', isDisabled: !isPressable || isDisabled, ...props }, + { elementType: elementType || 'div', isDisabled: !isPressable || isDisabled, onPress, ...props }, cardRef ); diff --git a/packages/components/src/Radio/Radio.style.tsx b/packages/components/src/Radio/Radio.style.tsx index cdefb0892..531c7e4ba 100644 --- a/packages/components/src/Radio/Radio.style.tsx +++ b/packages/components/src/Radio/Radio.style.tsx @@ -1,5 +1,5 @@ -import styled from 'styled-components'; -import { Orientation, Spacing, theme } from '@interlay/theme'; +import styled, { css } from 'styled-components'; +import { Orientation, RadioSize, Spacing } from '@interlay/theme'; import { Flex } from '../Flex'; import { visuallyHidden } from '../utils/visually-hidden'; @@ -16,6 +16,7 @@ type StyledLabelProps = { }; type StyledButtonProps = { + $size: RadioSize; $isSelected: boolean; $isHovered: boolean; }; @@ -32,7 +33,7 @@ const StyledRadioGroup = styled(Flex)` const StyledLabel = styled(Label)` padding: 0; display: flex; - gap: ${theme.spacing.spacing2}; + gap: ${({ theme }) => theme.spacing('md')}; align-items: center; opacity: ${({ $isDisabled }) => $isDisabled && 0.5}; flex: ${({ $flex }) => (typeof $flex === 'boolean' ? '1' : $flex)}; @@ -46,32 +47,35 @@ const StyledButton = styled.span` position: relative; flex-grow: 0; flex-shrink: 0; - width: 24px; - height: 24px; - margin: ${theme.spacing.spacing2} 0; outline: none; - border-width: 2px; - border-style: solid; - border-color: ${({ $isSelected }) => ($isSelected ? theme.colors.textSecondary : theme.colors.textPrimary)}; border-radius: 50%; opacity: ${({ $isHovered }) => $isHovered && 0.9}; - transition: - border-color ${theme.transition.duration.duration100}ms ease-in-out, - opacity ${theme.transition.duration.duration100}ms ease-in-out; - &::after { - content: ''; - border-radius: 50%; - position: absolute; - transition: border-width ${theme.transition.duration.duration100}ms ease-in-out; - border-color: ${theme.colors.textSecondary}; - border-style: solid; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - border-width: ${({ $isSelected }) => ($isSelected ? '7px' : 0)}; - opacity: inherit; - } + ${({ theme, $size, $isSelected }) => { + const { button, selected, size } = theme.radio; + const { button: buttonSize, selected: selectedSize } = size[$size]; + + return css` + ${button.base} + ${buttonSize.base} + ${$isSelected && selected.button.base} + + &::after { + content: ''; + border-radius: 50%; + position: absolute; + + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + opacity: inherit; + + ${button.inside} + ${$isSelected && selected.button.inside} + ${$isSelected && selectedSize.button.inside} + } + `; + }} `; export { StyledLabel, StyledRadioGroup, StyledButton, StyledInput }; diff --git a/packages/components/src/Radio/Radio.tsx b/packages/components/src/Radio/Radio.tsx index e8ebb6696..104208779 100644 --- a/packages/components/src/Radio/Radio.tsx +++ b/packages/components/src/Radio/Radio.tsx @@ -3,6 +3,7 @@ import { Placement } from '@interlay/theme'; import { useHover } from '@react-aria/interactions'; import { AriaRadioProps, useRadio } from '@react-aria/radio'; import { HTMLAttributes, forwardRef, useRef } from 'react'; +import { useTheme } from 'styled-components'; import { Span, TextProps } from '../Text'; @@ -25,11 +26,12 @@ type RadioProps = Props & NativeAttrs & InheritAttrs; const Radio = forwardRef( ({ labelProps, isDisabled: isDisabledProp, children, className, style, flex, ...props }, ref): JSX.Element => { let { hoverProps, isHovered } = useHover({ isDisabled: isDisabledProp }); + const { radio } = useTheme(); const labelRef = useDOMRef(ref); const inputRef = useRef(null); - const state = useRadioProvider(); + const { size, state } = useRadioProvider(); const { inputProps, isSelected, isDisabled } = useRadio( { @@ -52,8 +54,8 @@ const Radio = forwardRef( style={style} > - - {children && {children}} + + {children && {children}} ); } diff --git a/packages/components/src/Radio/RadioContext.tsx b/packages/components/src/Radio/RadioContext.tsx index c289de375..6611ff58c 100644 --- a/packages/components/src/Radio/RadioContext.tsx +++ b/packages/components/src/Radio/RadioContext.tsx @@ -1,9 +1,10 @@ +import { RadioSize } from '@interlay/theme'; import { RadioGroupState } from '@react-stately/radio'; import React, { useContext } from 'react'; -type RadioGroupContext = RadioGroupState; +type RadioGroupContext = { state: RadioGroupState; size: RadioSize }; -export const RadioContext = React.createContext({} as RadioGroupContext); +export const RadioContext = React.createContext({ size: 'md' } as RadioGroupContext); export function useRadioProvider(): RadioGroupContext { return useContext(RadioContext); diff --git a/packages/components/src/Radio/RadioGroup.tsx b/packages/components/src/Radio/RadioGroup.tsx index 2152d6afb..4f5fb7d86 100644 --- a/packages/components/src/Radio/RadioGroup.tsx +++ b/packages/components/src/Radio/RadioGroup.tsx @@ -1,5 +1,5 @@ import { useDOMRef } from '@interlay/hooks'; -import { Orientation, Spacing } from '@interlay/theme'; +import { Orientation, RadioSize, Spacing } from '@interlay/theme'; import { AriaRadioGroupProps, useRadioGroup } from '@react-aria/radio'; import { ChangeEvent, forwardRef } from 'react'; import { useRadioGroupState } from '@react-stately/radio'; @@ -12,6 +12,7 @@ import { StyledRadioGroup } from './Radio.style'; type Props = { gap?: Spacing; orientation?: Orientation; + size?: RadioSize; onChange?: (e: ChangeEvent) => void; onValueChange?: (value: string) => void; }; @@ -23,7 +24,7 @@ type FieldAttrs = Omit; type RadioGroupProps = Props & FieldAttrs & InheritAttrs; const RadioGroup = forwardRef( - ({ orientation = 'vertical', children, onValueChange, onChange, gap, ...props }, ref): JSX.Element => { + ({ orientation = 'vertical', children, onValueChange, onChange, gap, size = 'md', ...props }, ref): JSX.Element => { const { fieldProps } = useFieldProps(props); let domRef = useDOMRef(ref); @@ -46,7 +47,7 @@ const RadioGroup = forwardRef( direction={orientation === 'vertical' ? 'column' : 'row'} onChange={onChange} > - {children} + {children} ); diff --git a/packages/core/theme/src/components/radio.ts b/packages/core/theme/src/components/radio.ts index 6851e137a..076e3351c 100644 --- a/packages/core/theme/src/components/radio.ts +++ b/packages/core/theme/src/components/radio.ts @@ -1,5 +1,20 @@ import { StyledObject } from 'styled-components'; -type RadioTheme = StyledObject; +import { Typography } from '../core'; -export type { RadioTheme }; +type RadioSize = 's' | 'md' | 'lg'; + +type RadioTheme = { + button: { base: StyledObject; inside: StyledObject }; + selected: { button: { base: StyledObject; inside: StyledObject } }; + size: Record< + RadioSize, + { + button: { base: StyledObject; inside?: StyledObject }; + label: Typography; + selected: { button: { inside: StyledObject } }; + } + >; +}; + +export type { RadioTheme, RadioSize }; diff --git a/packages/core/theme/src/core/icon.ts b/packages/core/theme/src/core/icon.ts index 5f0ec1208..e1c2b35a4 100644 --- a/packages/core/theme/src/core/icon.ts +++ b/packages/core/theme/src/core/icon.ts @@ -4,9 +4,13 @@ import { css } from 'styled-components'; import { spacing } from './space'; import { Color, Palette, color } from './colors'; -type IconsSizes = 'xs' | 's' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl'; +type IconsSizes = 'xxs' | 'xs' | 's' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl'; const iconSizeBase: Record> = { + xxs: { + height: spacing('lg'), + width: spacing('lg') + }, xs: { height: spacing('xl'), width: spacing('xl') diff --git a/packages/core/theme/src/index.ts b/packages/core/theme/src/index.ts index d35594c47..83686f475 100644 --- a/packages/core/theme/src/index.ts +++ b/packages/core/theme/src/index.ts @@ -12,7 +12,8 @@ export type { AlertStatus, TokenInputSize, TabsSize, - SwitchSize + SwitchSize, + RadioSize } from './components'; export type { IconsSizes, diff --git a/packages/core/theme/src/themes/bob/radio.ts b/packages/core/theme/src/themes/bob/radio.ts index 6b30b3eee..734117f9b 100644 --- a/packages/core/theme/src/themes/bob/radio.ts +++ b/packages/core/theme/src/themes/bob/radio.ts @@ -1,8 +1,86 @@ +import { spacing, transition } from '../../core'; import { RadioTheme } from '../../components'; +import { color } from './colors'; + const radio: RadioTheme = { + button: { + base: { + marginTop: spacing('xs'), + marginBottom: spacing('xs'), + borderWidth: '2px', + borderStyle: 'solid', + borderColor: color('grey-300'), + ...transition('common', 'fast') + }, + inside: { + width: '0rem', + height: '0rem', + ...transition('dimensions', 'fast') + } + }, + selected: { + button: { + base: { + borderColor: color('primary-500') + }, + inside: { + backgroundColor: color('primary-500') + } + } + }, size: { - xs: {} + s: { + button: { + base: { + width: spacing('2xl'), + height: spacing('2xl') + } + }, + selected: { + button: { + inside: { + width: spacing('md'), + height: spacing('md') + } + } + }, + label: 's' + }, + md: { + button: { + base: { + width: spacing('3xl'), + height: spacing('3xl') + } + }, + selected: { + button: { + inside: { + width: spacing('lg'), + height: spacing('lg') + } + } + }, + label: 'md' + }, + lg: { + button: { + base: { + width: spacing('4xl'), + height: spacing('4xl') + } + }, + selected: { + button: { + inside: { + width: spacing('xl'), + height: spacing('xl') + } + } + }, + label: 'lg' + } } }; diff --git a/packages/icons/src/ArrowLongRight.tsx b/packages/icons/src/ArrowLongRight.tsx index 629ca2698..39cc96bf5 100644 --- a/packages/icons/src/ArrowLongRight.tsx +++ b/packages/icons/src/ArrowLongRight.tsx @@ -8,7 +8,7 @@ const ArrowLongRight = forwardRef((props, ref) => ( ref={ref} fill='none' stroke='currentColor' - stroke-width='1.5' + strokeWidth='1.5' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg' >