From 67968cc408e2a362d37f9bbfc671284160cc2e72 Mon Sep 17 00:00:00 2001 From: Jared Scott Date: Mon, 2 Sep 2024 14:08:55 +0800 Subject: [PATCH] feat: #6870 Ensure steps can be programmatically styled based on parent and context - Pull code from TabView.js and ensure it works correctly under steps - Put in some initial styling for `step` and `label` - TODO add typing for parent and context --- components/lib/passthrough/tailwind/index.js | 19 ++++++--- components/lib/steps/Steps.js | 44 ++++++++++++++++---- components/lib/steps/StepsBase.js | 5 ++- 3 files changed, 52 insertions(+), 16 deletions(-) diff --git a/components/lib/passthrough/tailwind/index.js b/components/lib/passthrough/tailwind/index.js index 979b489e96..15922964ce 100644 --- a/components/lib/passthrough/tailwind/index.js +++ b/components/lib/passthrough/tailwind/index.js @@ -2109,12 +2109,19 @@ const Tailwind = { 'focus:outline-none focus:outline-offset-0 focus:shadow-[0_0_0_0.2rem_rgba(191,219,254,1)] dark:focus:shadow-[0_0_0_0.2rem_rgba(147,197,253,0.5)]' ) }, - step: { - className: classNames('flex items-center justify-center', 'text-gray-700 dark:text-white/80 border border-gray-300 dark:border-blue-900/40 bg-white dark:bg-gray-900 w-[2rem] h-[2rem] leading-2rem text-sm z-10 rounded-full') - }, - label: { - className: classNames('block', 'whitespace-nowrap overflow-hidden overflow-ellipsis max-w-full', 'mt-2 text-gray-500 dark:text-white/60') - } + step: ({ parent, context }) => ({ + className: classNames('flex items-center justify-center', 'text-gray-700 dark:text-white/80 border border-gray-300 dark:border-blue-900/40 bg-white dark:bg-gray-900 w-[2rem] h-[2rem] leading-2rem text-sm z-10 rounded-full', { + 'bg-white': parent.state.activeIndex !== context.index, // unselected item. + 'bg-blue-500': parent.state.activeIndex === context.index // Selected item. + }) + }), + label: ({ parent, context }) => ({ + className: classNames('block', 'whitespace-nowrap overflow-hidden overflow-ellipsis max-w-full', 'mt-2 text-gray-500 dark:text-white/60', { + 'font-normal': parent.state.activeIndex !== context.index, // unselected item. + 'font-bold': parent.state.activeIndex === context.index, // Selected item. + 'text-gray-500/60': context.disabled + }) + }) }, tabmenu: { root: 'overflow-x-auto', diff --git a/components/lib/steps/Steps.js b/components/lib/steps/Steps.js index 4cbed933b6..612630824e 100644 --- a/components/lib/steps/Steps.js +++ b/components/lib/steps/Steps.js @@ -12,18 +12,44 @@ export const Steps = React.memo( const props = StepsBase.getProps(inProps, context); const [idState, setIdState] = React.useState(props.id); + const [activeIndexState, setActiveIndexState] = React.useState(props.activeIndex); const elementRef = React.useRef(null); const listRef = React.useRef(null); + const count = React.Children.count(props.children); - const { ptm, cx, isUnstyled } = StepsBase.setMetaData({ + const metaData = { props, state: { - id: idState + id: idState, + activeIndex: activeIndexState } + }; + + const { ptm, ptmo, cx, isUnstyled } = StepsBase.setMetaData({ + ...metaData }); useHandleStyle(StepsBase.css.styles, isUnstyled, { name: 'steps' }); + const getStepPT = (step, key, index) => { + const stepMetaData = { + props: step.props, + parent: metaData, + context: { + index, + count, + first: index === 0, + last: index === count - 1, + active: index === activeIndexState, + disabled: getStepProp(step, 'disabled') + } + }; + + return mergeProps(ptm(`step.${key}`, { step: stepMetaData }), ptm(`steps.${key}`, { steps: stepMetaData }), ptm(`steps.${key}`, stepMetaData), ptmo(getStepProp(step, 'pt'), key, stepMetaData)); + }; + + const getStepProp = (step, name) => StepsBase.getCProp(step, name); + const itemClick = (event, item, index) => { if (props.readOnly || item.disabled) { event.preventDefault(); @@ -47,6 +73,8 @@ export const Steps = React.memo( }); } + setActiveIndexState(index); + if (!item.url) { event.preventDefault(); event.stopPropagation(); @@ -163,15 +191,15 @@ export const Steps = React.memo( } const key = item.id || idState + '_' + index; - const active = index === props.activeIndex; - const disabled = item.disabled || (index !== props.activeIndex && props.readOnly); + const active = index === activeIndexState; + const disabled = item.disabled || (index !== activeIndexState && props.readOnly); const iconClassName = classNames('p-menuitem-icon', item.icon); const iconProps = mergeProps( { className: cx('icon', { item }) }, - ptm('icon') + getStepPT(item, 'icon', index) ); const icon = IconUtils.getJSXIcon(item.icon, { ...iconProps }, { props }); @@ -180,7 +208,7 @@ export const Steps = React.memo( { className: cx('label') }, - ptm('label') + getStepPT(item, 'label', index) ); const label = item.label && {item.label}; @@ -189,7 +217,7 @@ export const Steps = React.memo( { className: cx('step') }, - ptm('step') + getStepPT(item, 'step', index) ); const actionProps = mergeProps( @@ -202,7 +230,7 @@ export const Steps = React.memo( onKeyDown: (event) => onItemKeyDown(event, item, index), onClick: (event) => itemClick(event, item, index) }, - ptm('action') + getStepPT(item, 'action', index) ); let content = ( diff --git a/components/lib/steps/StepsBase.js b/components/lib/steps/StepsBase.js index f3dd6f1bac..bad7a72b82 100644 --- a/components/lib/steps/StepsBase.js +++ b/components/lib/steps/StepsBase.js @@ -1,5 +1,5 @@ import { ComponentBase } from '../componentbase/ComponentBase'; -import { classNames } from '../utils/Utils'; +import { classNames, ObjectUtils } from '../utils/Utils'; const classes = { icon: ({ item }) => classNames('p-menuitem-icon', item.icon), @@ -84,5 +84,6 @@ export const StepsBase = ComponentBase.extend({ css: { classes, styles - } + }, + getCProp: (step, name) => ObjectUtils.getComponentProp(step, name, StepsBase.defaultProps) });