From f41dd991ce23de14fa53272ba88fc04164e8185b Mon Sep 17 00:00:00 2001 From: Daniil Suvorov Date: Fri, 18 Aug 2023 13:23:34 +0300 Subject: [PATCH 1/2] =?UTF-8?q?feat(AppRoot):=20add=20`layout`=20=D0=94?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D1=8F=D0=B5=D0=BC=20=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=BE=D0=B5=20=D1=81=D0=B2=D0=BE=D0=B9=D1=81=D1=82=D0=B2?= =?UTF-8?q?=D0=BE=20`layout:=20'plain'=20|=20'card'`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Изменяем вид Group при mode="card" и sizeX="compact" - closed #3018 --- .../vkui/src/components/AppRoot/AppRoot.tsx | 34 +++++++++++++--- .../src/components/AppRoot/AppRootContext.ts | 1 + .../src/components/Group/Group.module.css | 34 ++++++++++++++++ packages/vkui/src/components/Group/Group.tsx | 39 ++++++++++++++----- packages/vkui/src/components/Group/Readme.md | 2 +- .../src/components/Panel/Panel.module.css | 10 ++++- packages/vkui/src/components/Panel/Panel.tsx | 3 ++ .../vkui/src/components/SplitLayout/Readme.md | 2 +- packages/vkui/src/styles/common.css | 8 ++++ .../Playground/PlaygroundRenderer.js | 2 + styleguide/Components/Preview.js | 4 +- styleguide/Components/Setting/Setting.js | 10 ++++- .../Components/Settings/LayoutSelect.js | 25 ++++++++++++ styleguide/Components/Settings/Settings.js | 9 ++++- .../StyleGuide/StyleGuideRenderer.js | 1 + 15 files changed, 161 insertions(+), 23 deletions(-) create mode 100644 styleguide/Components/Settings/LayoutSelect.js diff --git a/packages/vkui/src/components/AppRoot/AppRoot.tsx b/packages/vkui/src/components/AppRoot/AppRoot.tsx index 941e8e15e0..671b33b741 100644 --- a/packages/vkui/src/components/AppRoot/AppRoot.tsx +++ b/packages/vkui/src/components/AppRoot/AppRoot.tsx @@ -28,6 +28,25 @@ const vkuiSizeXClassNames = { [SizeType.REGULAR]: 'vkui--sizeX-regular', }; +const vkuiLayoutClassNames = { + card: 'vkui--layout-card', + plain: 'vkui--layout-plain', +}; + +function containerClassNames(layout: AppRootProps['layout'], sizeX: SizeType | 'none'): string[] { + const classNames: string[] = []; + + if (layout) { + classNames.push(vkuiLayoutClassNames[layout]); + } + + if (sizeX !== SizeType.COMPACT) { + classNames.push(vkuiSizeXClassNames[sizeX]); + } + + return classNames; +} + const INSET_CUSTOM_PROPERTY_PREFIX = `--vkui_internal--safe_area_inset_`; // Используйте classList, но будьте осторожны @@ -54,6 +73,7 @@ export interface AppRootProps extends React.HTMLAttributes { * Это поведение можно отключить с помощью этого параметра. */ disableParentTransformForPositionFixedElements?: boolean; + layout?: 'card' | 'plain'; } /** @@ -68,6 +88,7 @@ export const AppRoot = ({ disableParentTransformForPositionFixedElements, className, safeAreaInsets, + layout, ...props }: AppRootProps) => { const isKeyboardInputActive = useKeyboardInputTracker(); @@ -180,18 +201,20 @@ export const AppRoot = ({ if (mode === 'partial') { return noop; } - const className = sizeX !== SizeType.COMPACT ? vkuiSizeXClassNames[sizeX] : null; + + const classNames = containerClassNames(layout, sizeX); + const container = mode === 'embedded' ? rootRef.current?.parentElement : document!.body; - if (className === null || !container) { + if (!classNames.length || !container) { return noop; } - container.classList.add(className); + container.classList.add(...classNames); return () => { - container.classList.remove(className); + container.classList.remove(...classNames); }; - }, [sizeX]); + }, [sizeX, layout]); useIsomorphicLayoutEffect(() => { if (mode !== 'full' || appearance === undefined) { @@ -216,6 +239,7 @@ export const AppRoot = ({ keyboardInput: isKeyboardInputActive, mode, disablePortal, + layout, }} > diff --git a/packages/vkui/src/components/AppRoot/AppRootContext.ts b/packages/vkui/src/components/AppRoot/AppRootContext.ts index 5ff48a36f7..32d4d9ecf3 100644 --- a/packages/vkui/src/components/AppRoot/AppRootContext.ts +++ b/packages/vkui/src/components/AppRoot/AppRootContext.ts @@ -7,6 +7,7 @@ export interface AppRootContextInterface { mode?: 'partial' | 'embedded' | 'full'; keyboardInput?: boolean; disablePortal?: boolean; + layout?: 'card' | 'plain'; } export const AppRootContext = React.createContext({ diff --git a/packages/vkui/src/components/Group/Group.module.css b/packages/vkui/src/components/Group/Group.module.css index fcd926ac1d..0829a7d2b6 100644 --- a/packages/vkui/src/components/Group/Group.module.css +++ b/packages/vkui/src/components/Group/Group.module.css @@ -64,6 +64,18 @@ } } +.Group--sizeX-compact.Group--mode-card { + padding-left: 0; + padding-right: 0; +} + +@media (--sizeX-compact) { + .Group--sizeX-none.Group--mode-card { + padding-left: 0; + padding-right: 0; + } +} + .Group--sizeX-compact { padding-left: 0; padding-right: 0; @@ -90,6 +102,18 @@ } } +.Group--sizeX-compact.Group--mode-card:first-of-type { + border-radius: 0 0 var(--vkui--size_border_radius_paper--regular) + var(--vkui--size_border_radius_paper--regular); +} + +@media (--sizeX-compact) { + .Group--sizeX-none.Group--mode-card:first-of-type { + border-radius: 0 0 var(--vkui--size_border_radius_paper--regular) + var(--vkui--size_border_radius_paper--regular); + } +} + /** * Изменено с ::after на ::before * потому что при ::after абсолютно позиционированный элемент накладывается @@ -123,6 +147,16 @@ } } +.Group--sizeX-compact.Group--mode-card::before { + box-shadow: none; +} + +@media (--sizeX-compact) { + .Group--sizeX-none.Group--mode-card::before { + box-shadow: none; + } +} + .Group--mode-plain + .Group__separator, .Group--mode-plain + .Group__separator + .Group__separator { padding-top: 8px; diff --git a/packages/vkui/src/components/Group/Group.tsx b/packages/vkui/src/components/Group/Group.tsx index 2a34a07719..3b4b21a3dc 100644 --- a/packages/vkui/src/components/Group/Group.tsx +++ b/packages/vkui/src/components/Group/Group.tsx @@ -6,6 +6,7 @@ import { SizeType } from '../../lib/adaptivity'; import { Platform } from '../../lib/platform'; import { warnOnce } from '../../lib/warnOnce'; import { HTMLAttributesWithRootRef } from '../../types'; +import { AppRootContext } from '../AppRoot/AppRootContext'; import { ModalRootContext } from '../ModalRoot/ModalRootContext'; import { RootComponent } from '../RootComponent/RootComponent'; import { Separator } from '../Separator/Separator'; @@ -29,6 +30,33 @@ const stylesPadding = { m: styles['Group--padding-m'], }; +/** + * Вычисляем mode для Group. + */ +function useGroupMode(modeProps: GroupProps['mode']): 'plain' | 'card' | 'none' { + const { isInsideModal } = React.useContext(ModalRootContext); + const { layout } = React.useContext(AppRootContext); + const { sizeX = 'none' } = useAdaptivity(); + + if (modeProps) { + return modeProps; + } + + if (isInsideModal) { + return 'plain'; + } + + if (layout) { + return layout; + } + + if (sizeX !== 'none') { + return sizeX === SizeType.REGULAR ? 'card' : 'plain'; + } + + return 'none'; +} + export interface GroupProps extends HTMLAttributesWithRootRef { header?: React.ReactNode; description?: React.ReactNode; @@ -69,16 +97,7 @@ export const Group = ({ const platform = usePlatform(); const { sizeX = 'none' } = useAdaptivity(); - let mode: GroupProps['mode'] | 'none' = modeProps; - - if (!modeProps) { - // Подробнее в "none" можно прочитать в ADAPTIVITY_GUIDE.md - mode = isInsideModal ? 'plain' : 'none'; - } - - if (mode === 'none' && sizeX !== 'none') { - mode = sizeX === SizeType.REGULAR ? 'card' : 'plain'; - } + const mode = useGroupMode(modeProps); const isTabPanel = restProps.role === 'tabpanel'; diff --git a/packages/vkui/src/components/Group/Readme.md b/packages/vkui/src/components/Group/Readme.md index 43bd0d4fbc..531edb05af 100644 --- a/packages/vkui/src/components/Group/Readme.md +++ b/packages/vkui/src/components/Group/Readme.md @@ -1,6 +1,6 @@ Группа – базовый компонент для группировки контента по смыслу. -```jsx { "props": { "layout": false, "adaptivity": true } } +```jsx { "props": { "layout": false, "showLayoutSelect": true, "adaptivity": true } } const MODAL_NAME = 'modal'; const Example = () => { diff --git a/packages/vkui/src/components/Panel/Panel.module.css b/packages/vkui/src/components/Panel/Panel.module.css index b77ae8eb76..b78da9ded8 100644 --- a/packages/vkui/src/components/Panel/Panel.module.css +++ b/packages/vkui/src/components/Panel/Panel.module.css @@ -162,8 +162,8 @@ background-color: var(--vkui--color_background_content); } -.Panel.Panel--sizeX-regular .Panel__in, -.Panel.Panel--sizeX-regular::before { +.Panel--sizeX-regular .Panel__in, +.Panel--sizeX-regular::before { background-color: transparent; } @@ -173,3 +173,9 @@ background-color: transparent; } } + +/* В AppRoot была установлена layout настройка */ +.Panel--layoutSetting .Panel__in, +.Panel--layoutSetting::before { + background-color: transparent; +} diff --git a/packages/vkui/src/components/Panel/Panel.tsx b/packages/vkui/src/components/Panel/Panel.tsx index 21a673fafb..a58fd54f20 100644 --- a/packages/vkui/src/components/Panel/Panel.tsx +++ b/packages/vkui/src/components/Panel/Panel.tsx @@ -6,6 +6,7 @@ import { SizeType } from '../../lib/adaptivity'; import { NavIdProps } from '../../lib/getNavId'; import { Platform } from '../../lib/platform'; import { HTMLAttributesWithRootRef } from '../../types'; +import { AppRootContext } from '../AppRoot/AppRootContext'; import { RootComponent } from '../RootComponent/RootComponent'; import { TooltipContainer } from '../Tooltip/TooltipContainer'; import { Touch } from '../Touch/Touch'; @@ -27,6 +28,7 @@ export interface PanelProps extends HTMLAttributesWithRootRef, N export const Panel = ({ centered = false, children, nav, ...restProps }: PanelProps) => { const platform = usePlatform(); const { sizeX = 'none' } = useAdaptivity(); + const { layout } = React.useContext(AppRootContext); return (
{cloneElement(preview, { diff --git a/styleguide/Components/Preview.js b/styleguide/Components/Preview.js index 78999e87f5..ef77f23355 100644 --- a/styleguide/Components/Preview.js +++ b/styleguide/Components/Preview.js @@ -39,11 +39,11 @@ const Layout = ({ children }) => { ); }; -const Config = ({ hasPointer, children, ...config }) => { +const Config = ({ hasPointer, layout, children, ...config }) => { return ( - {children} + {children} ); diff --git a/styleguide/Components/Setting/Setting.js b/styleguide/Components/Setting/Setting.js index fb7aa989ae..28feb90e63 100644 --- a/styleguide/Components/Setting/Setting.js +++ b/styleguide/Components/Setting/Setting.js @@ -25,6 +25,14 @@ export const Setting = ({ [], ); + const title = + options?.find((option) => { + if (typeof option === 'string' || typeof option === 'number') { + return false; + } + return option.value === value; + })?.title || value; + const labelJsx = {label}: ; return ( @@ -69,7 +77,7 @@ export const Setting = ({ ); }} > - {value} + {title} )} diff --git a/styleguide/Components/Settings/LayoutSelect.js b/styleguide/Components/Settings/LayoutSelect.js new file mode 100644 index 0000000000..11835a4253 --- /dev/null +++ b/styleguide/Components/Settings/LayoutSelect.js @@ -0,0 +1,25 @@ +import React from 'react'; +import { Link } from '@vkui'; +import { Setting } from '../Setting/Setting'; + +const layouts = [{ title: 'Не задано', value: undefined }, 'card', 'plain']; + +export const LayoutSelect = ({ onChange, value }) => { + const onChangeValue = (changeValue) => { + onChange(changeValue); + }; + + return ( + + Свойство AppRoot + + } + label="layout" + onChange={onChangeValue} + value={value} + options={layouts} + /> + ); +}; diff --git a/styleguide/Components/Settings/Settings.js b/styleguide/Components/Settings/Settings.js index a5991892b5..503ba1e715 100644 --- a/styleguide/Components/Settings/Settings.js +++ b/styleguide/Components/Settings/Settings.js @@ -4,12 +4,13 @@ import { StyleGuideContext } from '../StyleGuide/StyleGuideRenderer'; import { AppearanceSelect } from './AppearanceSelect'; import { HasCustomPanelHeaderAfter } from './HasCustomPanelHeaderAfter'; import { HasPointerCheckbox } from './HasPointerCheckbox'; +import { LayoutSelect } from './LayoutSelect'; import { PlatformSelect } from './PlatformSelect'; import { ViewHeightSelect } from './ViewHeightSelect'; import { ViewWidthSelect } from './ViewWidthSelect'; import './Settings.css'; -export const Settings = ({ adaptivity, showCustomPanelHeaderAfterProps }) => { +export const Settings = ({ adaptivity, showCustomPanelHeaderAfterProps, showLayoutSelect }) => { const { sizeX } = useAdaptivityConditionalRender(); return ( @@ -58,6 +59,12 @@ export const Settings = ({ adaptivity, showCustomPanelHeaderAfterProps }) => { )} )} + {showLayoutSelect && ( + context.setContext({ layout })} + value={context.layout} + /> + )}
); diff --git a/styleguide/Components/StyleGuide/StyleGuideRenderer.js b/styleguide/Components/StyleGuide/StyleGuideRenderer.js index b1bb5b2f65..488808bc15 100644 --- a/styleguide/Components/StyleGuide/StyleGuideRenderer.js +++ b/styleguide/Components/StyleGuide/StyleGuideRenderer.js @@ -16,6 +16,7 @@ let initialState = { styleguideAppearance: Appearance.LIGHT, hasCustomPanelHeaderAfter: true, transitionMotionEnabled: true, + layout: undefined, }; try { From 3a7b44fe0c4270fc5f54b06d11e6082df982d6e1 Mon Sep 17 00:00:00 2001 From: Daniil Suvorov Date: Wed, 30 Aug 2023 11:51:24 +0300 Subject: [PATCH 2/2] fix: review by inomdzhon Co-authored-by: Inomdzhon Mirdzhamolov --- .../vkui/src/components/Group/Group.module.css | 14 ++------------ packages/vkui/src/components/Group/Group.tsx | 14 ++++++++------ 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/packages/vkui/src/components/Group/Group.module.css b/packages/vkui/src/components/Group/Group.module.css index 0829a7d2b6..f146529c29 100644 --- a/packages/vkui/src/components/Group/Group.module.css +++ b/packages/vkui/src/components/Group/Group.module.css @@ -64,30 +64,20 @@ } } +.Group--sizeX-compact, .Group--sizeX-compact.Group--mode-card { padding-left: 0; padding-right: 0; } @media (--sizeX-compact) { + .Group--sizeX-none, .Group--sizeX-none.Group--mode-card { padding-left: 0; padding-right: 0; } } -.Group--sizeX-compact { - padding-left: 0; - padding-right: 0; -} - -@media (--sizeX-compact) { - .Group--sizeX-none { - padding-left: 0; - padding-right: 0; - } -} - .Group--mode-card { background: var(--vkui--color_background_content); border-radius: var(--vkui--size_border_radius_paper--regular); diff --git a/packages/vkui/src/components/Group/Group.tsx b/packages/vkui/src/components/Group/Group.tsx index 3b4b21a3dc..5fe75dd599 100644 --- a/packages/vkui/src/components/Group/Group.tsx +++ b/packages/vkui/src/components/Group/Group.tsx @@ -33,13 +33,15 @@ const stylesPadding = { /** * Вычисляем mode для Group. */ -function useGroupMode(modeProps: GroupProps['mode']): 'plain' | 'card' | 'none' { - const { isInsideModal } = React.useContext(ModalRootContext); +function useGroupMode( + forcedMode: GroupProps['mode'], + sizeX: SizeType | 'none', + isInsideModal: boolean, +): 'plain' | 'card' | 'none' { const { layout } = React.useContext(AppRootContext); - const { sizeX = 'none' } = useAdaptivity(); - if (modeProps) { - return modeProps; + if (forcedMode) { + return forcedMode; } if (isInsideModal) { @@ -97,7 +99,7 @@ export const Group = ({ const platform = usePlatform(); const { sizeX = 'none' } = useAdaptivity(); - const mode = useGroupMode(modeProps); + const mode = useGroupMode(modeProps, sizeX, isInsideModal); const isTabPanel = restProps.role === 'tabpanel';