diff --git a/apps/docs/components/docs/props-table.tsx b/apps/docs/components/docs/props-table.tsx new file mode 100644 index 00000000..24709179 --- /dev/null +++ b/apps/docs/components/docs/props-table.tsx @@ -0,0 +1,50 @@ +import React from 'react'; + +interface Property { + type: string; + required: boolean; + defaultValue?: string; +} + +interface PropsTableProps { + description: string; + prop: Property; +} + +const PropsTable: React.FC = ({ description, prop }) => { + return ( +
+

{description}

+
+ + + + + + + + + + + + + + + +
+ Type + + Required + + Default +
+ {prop.type} + {prop.required ? 'Yes' : 'No'}{prop.defaultValue}
+
+
+ ); +}; + +export default PropsTable; diff --git a/apps/docs/pages/docs/v2/Components/badge.en-US.mdx b/apps/docs/pages/docs/v2/Components/badge.en-US.mdx new file mode 100644 index 00000000..984a8199 --- /dev/null +++ b/apps/docs/pages/docs/v2/Components/badge.en-US.mdx @@ -0,0 +1,83 @@ +--- +searchable: true +--- + +import { CodeEditor } from '@components/code-editor'; +import PropsTable from "@components/docs/props-table"; + + +# Badge + +Component to highlight an item's status for quick recognition. + +## Import + +```js +import { Badge } from 'react-native-ficus-ui'; +``` + +## Usage + +### Change color scheme + + + New + New + New + New + New + New +`} /> + +### Change font size + + + New + + New + + + New + + + New + + + New + + + New + +`} +/> + +### Variants + + + + Outline + + + Solid + + + Subtle + +`} /> + +## Props + +Extends every `Box` and `Text` props. + +### `colorScheme` + + +### `variant` + + diff --git a/apps/examples/app/components-v2/Badge.tsx b/apps/examples/app/components-v2/Badge.tsx new file mode 100644 index 00000000..82371012 --- /dev/null +++ b/apps/examples/app/components-v2/Badge.tsx @@ -0,0 +1,62 @@ +import { SafeAreaView } from "react-native"; +import { ScrollBox, Text, VStack } from "react-native-ficus-ui"; +import ExampleSection from "@/src/ExampleSection"; +import { Badge } from "@ficus-ui/native"; + +const BadgeComponent = () => { + return ( + + + Badge component + + + + + New + New + New + New + New + New + + + + + New + + New + + + New + + + New + + + New + + + New + + + + + + + + Outline + + + Solid + + + Subtle + + + + + + ); +}; + +export default BadgeComponent; diff --git a/apps/examples/app/items-v2.ts b/apps/examples/app/items-v2.ts index 99730320..b3440f9f 100644 --- a/apps/examples/app/items-v2.ts +++ b/apps/examples/app/items-v2.ts @@ -1,5 +1,6 @@ import { ComponentType } from 'react'; import BoxComponent from './components-v2/Box'; +import BadgeComponent from './components-v2/Badge'; type ExampleComponentType = { onScreenName: string; @@ -8,7 +9,6 @@ type ExampleComponentType = { }; export const components: ExampleComponentType[] = [ - { navigationPath: 'Box', onScreenName: 'Box', component: BoxComponent }, - + { navigationPath: 'Badge', onScreenName: 'Badge', component: BadgeComponent }, ]; diff --git a/packages/components/src/badge/index.tsx b/packages/components/src/badge/index.tsx new file mode 100644 index 00000000..b8c8229b --- /dev/null +++ b/packages/components/src/badge/index.tsx @@ -0,0 +1,31 @@ +import { + TextStyleProps, + ThemingProps, + omitThemingProps, + splitTextProps, +} from '@ficus-ui/style-system'; + +import { + type NativeFicusProps, + ficus, + forwardRef, + useStyleConfig, +} from '../system'; + +export interface BadgeProps + extends NativeFicusProps<'View'>, + TextStyleProps, + ThemingProps<'Badge'> {} + +export const Badge = forwardRef(function Badge(props, ref) { + const styles = useStyleConfig('Badge', props); + + const { children, ...rest } = omitThemingProps(props); + const [textStyles, restStyles] = splitTextProps(styles); + + return ( + + {children} + + ); +}); diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index 7604f697..66bd1dcb 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -1,2 +1,4 @@ export * from './box'; +export * from './badge'; + export { ThemeProvider } from '@ficus-ui/theme'; diff --git a/packages/components/src/system/system.ts b/packages/components/src/system/system.ts index caf6b8f8..67d402c5 100644 --- a/packages/components/src/system/system.ts +++ b/packages/components/src/system/system.ts @@ -61,17 +61,18 @@ export function styled< const ficusComponent = forwardRef( function FicusComponent(props, ref) { - const { children, style, as, ...rest } = props; + const { children, style, as, __styles, ...rest } = props; const { theme } = useTheme(); - const restProps = splitProps(rest, isStyleProp)[1]; + const [styleProps, restProps] = splitProps(rest, isStyleProp); const AsComponent = as ? getComponent(as) : Component; const propsWithTheme = { style, theme, - ...rest, + __styles, + ...styleProps, }; const computedStyle = styleObject(propsWithTheme); diff --git a/packages/components/src/system/use-style-config.ts b/packages/components/src/system/use-style-config.ts index 9146aa57..3150182e 100644 --- a/packages/components/src/system/use-style-config.ts +++ b/packages/components/src/system/use-style-config.ts @@ -1,6 +1,6 @@ import { useRef } from 'react'; -import { compact, get, mergeWith, omit } from '@chakra-ui/utils'; +import { compact, memoizedGet as get, mergeWith, omit } from '@chakra-ui/utils'; import { Dict, type SystemStyleObject, @@ -14,7 +14,7 @@ type StylesRef = SystemStyleObject | Record; function useStyleConfigFn( themeKey: string | null, - props: ThemingProps & Record = {} + props: ThemingProps & Dict = {} ) { const { styleConfig: styleConfigProp, ...rest } = props; diff --git a/packages/style-system/src/config/background.ts b/packages/style-system/src/config/background.ts index 4e0777f5..a7f97be9 100644 --- a/packages/style-system/src/config/background.ts +++ b/packages/style-system/src/config/background.ts @@ -3,8 +3,10 @@ import { Config } from '../utils/prop-config'; export const background: Config = { bg: t.colors('backgroundColor'), + backgroundColor: t.colors('backgroundColor'), }; export interface BackgroundProps { bg?: string; + backgroundColor?: string; } diff --git a/packages/style-system/src/config/colors.ts b/packages/style-system/src/config/colors.ts index 0f69cd86..7838427d 100644 --- a/packages/style-system/src/config/colors.ts +++ b/packages/style-system/src/config/colors.ts @@ -2,13 +2,11 @@ import { t } from '../utils'; import { Config } from '../utils/prop-config'; export const color: Config = { - color: t.colors('color'), overlayColor: t.colors('overlayColor'), shadowColor: t.colors('shadowColor'), }; export interface ColorProps { - color?: string; overlayColor?: string; shadowColor?: string; } diff --git a/packages/style-system/src/config/radius.ts b/packages/style-system/src/config/radius.ts index e1626263..ccdaa19b 100644 --- a/packages/style-system/src/config/radius.ts +++ b/packages/style-system/src/config/radius.ts @@ -3,6 +3,7 @@ import { Config } from '../utils/prop-config'; import { ResponsiveValue } from '../utils/types'; export const radius: Config = { + rounded: t.radius('borderRadius'), borderRadius: t.radius('borderRadius'), borderTopLeftRadius: t.radius('borderTopLeftRadius'), borderTopRightRadius: t.radius('borderTopRightRadius'), @@ -21,6 +22,7 @@ export const radius: Config = { }; export interface RadiusProps { + rounded?: ResponsiveValue; borderRadius?: ResponsiveValue; borderTopLeftRadius?: ResponsiveValue; borderTopRightRadius?: ResponsiveValue; diff --git a/packages/style-system/src/config/text.ts b/packages/style-system/src/config/text.ts index 1e3d9a2e..5d9bd5f3 100644 --- a/packages/style-system/src/config/text.ts +++ b/packages/style-system/src/config/text.ts @@ -6,6 +6,7 @@ import { transforms } from '../utils/transform-functions'; import { ResponsiveValue } from '../utils/types'; export const text: Config = { + color: t.colors('color'), textColor: t.colors('color'), fontSize: t.prop('fontSize', 'fontSizes', transforms.getThemeProp), textDecorLine: t.prop('textDecorationLine'), @@ -35,11 +36,12 @@ export const text: Config = { * Only for React native Text Component */ export interface TextStyleProps { + color?: string; textColor?: string; fontSize?: ResponsiveValue; textDecorLine?: ResponsiveValue; textDecorStyle?: ResponsiveValue; - fontStyle?: ResponsiveValue; + fontStyle?: ResponsiveValue; textDecorColor?: ResponsiveValue; fontWeight?: ResponsiveValue; fontFamily?: ResponsiveValue<'heading' | 'mono' | (string & {})>; diff --git a/packages/style-system/src/style-config.ts b/packages/style-system/src/style-config.ts index 77fcb38f..e2e9c7bf 100644 --- a/packages/style-system/src/style-config.ts +++ b/packages/style-system/src/style-config.ts @@ -1,5 +1,6 @@ -import { isObject, mergeWith, runIfFn } from '@chakra-ui/utils'; +import { isObject, mergeWith, runIfFn, splitProps } from '@chakra-ui/utils'; +import { isStyleProp } from './system'; import { Dict, ResponsiveValue } from './utils'; import { expandResponsive } from './utils'; @@ -84,12 +85,13 @@ export function resolveStyleConfig(config: Config) { const { variant, size, theme, ...rest } = props; const recipe = createResolver(theme); + const [restStyles] = splitProps(rest, isStyleProp); return mergeWith( {}, runIfFn(config.baseStyle ?? {}, props), recipe(config, 'sizes', size, props), recipe(config, 'variants', variant, props), - rest + restStyles ); }; } diff --git a/packages/style-system/src/style-sheet.ts b/packages/style-system/src/style-sheet.ts index a337074b..6c85ee00 100644 --- a/packages/style-system/src/style-sheet.ts +++ b/packages/style-system/src/style-sheet.ts @@ -28,9 +28,17 @@ export function getStyleSheet({ configs = {}, theme }: GetStyleSheetOptions) { config = { property: key } as PropConfig; } + /** + * Useful for objects containing styles. + * E.g: React Native `style` prop + */ if (isObject(value)) { computedStyles[key] = computedStyles[key] ?? {}; - computedStyles = mergeWith({}, computedStyles[key], styleSheet(value)); + computedStyles[key] = mergeWith( + {}, + computedStyles[key], + styleSheet(value) + ); continue; } diff --git a/packages/style-system/src/system.types.ts b/packages/style-system/src/system.types.ts index c8e7acb5..100b9526 100644 --- a/packages/style-system/src/system.types.ts +++ b/packages/style-system/src/system.types.ts @@ -59,8 +59,16 @@ export type SystemStyleObject = type Assign = Omit & U; /** - * We might need to extend SystemProps. - * For example for Text + * We might need to extend SystemProps with ExtraProps. + * For example for Text style props + * + * To be able to use React Native `style` prop with theme value, each prop should be added to the System Config. + * + * @example + * If `backgroundColor` is not in the style system config: + * ❌ + * ✅ + * */ export type SystemProps = Assign< StyleProps, diff --git a/packages/theme/src/components/badge.ts b/packages/theme/src/components/badge.ts index a1dd6591..03848575 100644 --- a/packages/theme/src/components/badge.ts +++ b/packages/theme/src/components/badge.ts @@ -1 +1,53 @@ -export const badgeTheme = {}; +import { defineStyle, defineStyleConfig } from '@ficus-ui/style-system'; + +const baseStyle = defineStyle({ + px: 4, + py: 2, + textTransform: 'uppercase', + fontSize: 'xs', + borderRadius: 'sm', + fontWeight: 'bold', + alignSelf: 'flex-start', +}); + +const variantSolid = defineStyle((props) => { + const { colorScheme: c } = props; + + return { + bg: `${c}.500`, + color: 'white', + }; +}); + +const variantSubtle = defineStyle((props) => { + const { colorScheme: c } = props; + + return { + bg: `${c}.100`, + color: `${c}.800`, + }; +}); + +const variantOutline = defineStyle((props) => { + const { colorScheme: c } = props; + + return { + color: `${c}.500`, + boxShadow: '0 0 0 1 rgba(0, 0, 0, 0.5)', + }; +}); + +const variants = { + solid: variantSolid, + subtle: variantSubtle, + outline: variantOutline, +}; + +export const badgeTheme = defineStyleConfig({ + baseStyle, + variants, + defaultProps: { + variant: 'subtle', + colorScheme: 'gray', + }, +});