diff --git a/docs/spec.md b/docs/spec.md index cc7b9a92..6ce2d67c 100644 --- a/docs/spec.md +++ b/docs/spec.md @@ -136,9 +136,9 @@ type Spec = ArraySpec | BooleanSpec | NumberSpec | ObjectSpec | StringSpec; #### OneOfParams -| Property | Type | Required | Description | -| :------- | :------------------- | :------: | :---------- | -| toggler | `'select'` `'radio'` | | Switch type | +| Property | Type | Required | Description | +| :------- | :---------------------------- | :------: | :---------- | +| toggler | `'select'` `'radio'` `'card'` | | Switch type | #### FileInput diff --git a/src/lib/core/types/specs.ts b/src/lib/core/types/specs.ts index 5a1c416b..56be3e3b 100644 --- a/src/lib/core/types/specs.ts +++ b/src/lib/core/types/specs.ts @@ -87,7 +87,7 @@ export interface ObjectSpec { order?: string[]; link?: LinkType; oneOfParams?: { - toggler?: 'select' | 'radio'; + toggler?: 'select' | 'radio' | 'card'; }; placeholder?: string; }; diff --git a/src/lib/kit/components/TogglerCard/TogglerCard.scss b/src/lib/kit/components/TogglerCard/TogglerCard.scss new file mode 100644 index 00000000..cc760ca6 --- /dev/null +++ b/src/lib/kit/components/TogglerCard/TogglerCard.scss @@ -0,0 +1,22 @@ +@import '../../styles/variables.scss'; + +.#{$ns}toggler-card { + width: 254px; + padding: 10px; + height: 88px; + + &__header { + display: flex; + justify-content: space-between; + align-items: baseline; + } + + &__text { + margin-top: 12px; + display: block; + margin-right: 15px; + height: 36px; + overflow: hidden; + text-overflow: ellipsis; + } +} diff --git a/src/lib/kit/components/TogglerCard/TogglerCard.tsx b/src/lib/kit/components/TogglerCard/TogglerCard.tsx new file mode 100644 index 00000000..547275d3 --- /dev/null +++ b/src/lib/kit/components/TogglerCard/TogglerCard.tsx @@ -0,0 +1,51 @@ +import React from 'react'; + +import {HelpPopover} from '@gravity-ui/components'; +import {Card, Text} from '@gravity-ui/uikit'; + +import {block} from '../../utils'; + +import './TogglerCard.scss'; + +const b = block('toggler-card'); + +interface TogglerCardProps { + description?: string; + title: string; + text: string; + onClick: () => void; + disabled?: boolean; + selected: boolean; +} + +export const TogglerCard: React.FC = ({ + description, + title, + text, + onClick, + disabled, + selected, +}) => { + return ( + +
+ + {title} + + {description ? ( + + ) : null} +
+ + {text} + +
+ ); +}; diff --git a/src/lib/kit/components/TogglerCard/index.ts b/src/lib/kit/components/TogglerCard/index.ts new file mode 100644 index 00000000..959ea1a0 --- /dev/null +++ b/src/lib/kit/components/TogglerCard/index.ts @@ -0,0 +1 @@ +export * from './TogglerCard'; diff --git a/src/lib/kit/components/index.ts b/src/lib/kit/components/index.ts index 0325f1ea..474f41ea 100644 --- a/src/lib/kit/components/index.ts +++ b/src/lib/kit/components/index.ts @@ -7,5 +7,6 @@ export * from './Inputs'; export * from './Layouts'; export * from './LongValue'; export * from './SimpleVerticalAccordeon'; +export * from './TogglerCard'; export * from './Views'; export * from './ViewLayouts'; diff --git a/src/lib/kit/hooks/useOneOf/useOneOf.scss b/src/lib/kit/hooks/useOneOf/useOneOf.scss index 6ab30f8a..3571bc9a 100644 --- a/src/lib/kit/hooks/useOneOf/useOneOf.scss +++ b/src/lib/kit/hooks/useOneOf/useOneOf.scss @@ -8,5 +8,22 @@ max-width: unset; } } + + &_card { + & + .#{$ns}group-indent { + & > .#{$ns}use-search:not(.#{$ns}group-indent) { + padding-top: 0px; + margin-top: 15px; + } + } + } + } + + &__card { + display: flex; + + & > :first-child { + margin-right: 8px; + } } } diff --git a/src/lib/kit/hooks/useOneOf/useOneOf.tsx b/src/lib/kit/hooks/useOneOf/useOneOf.tsx index 8fb20c9a..2880436a 100644 --- a/src/lib/kit/hooks/useOneOf/useOneOf.tsx +++ b/src/lib/kit/hooks/useOneOf/useOneOf.tsx @@ -4,6 +4,7 @@ import {RadioButton, Select} from '@gravity-ui/uikit'; import _ from 'lodash'; import {ObjectIndependentInputProps} from '../../../core'; +import {TogglerCard} from '../../components'; import {block} from '../../utils'; import './useOneOf.scss'; @@ -68,17 +69,49 @@ export const useOneOf = ({props, onTogglerChange}: UseOneOfParams) => { [spec.description, spec.viewSpec.order, specProperties], ); - const selectToggler = React.useMemo( - () => + const togglerType = React.useMemo(() => { + if (spec.viewSpec.oneOfParams?.toggler === 'card' && options.length < 3) { + return 'card'; + } + + if ( spec.viewSpec.oneOfParams?.toggler !== 'radio' && (spec.viewSpec.oneOfParams?.toggler === 'select' || options.length > 3 || - _.some(options, ({title}) => title.length > MAX_TAB_TITLE_LENGTH)), - [options, spec.viewSpec.oneOfParams?.toggler], - ); + _.some(options, ({title}) => title.length > MAX_TAB_TITLE_LENGTH)) + ) { + return 'select'; + } + + return 'radio'; + }, [options, spec.viewSpec.oneOfParams?.toggler]); const togglerInput = React.useMemo(() => { - if (selectToggler) { + if (togglerType === 'card') { + return ( +
+ {options.map(({value}) => { + const onClick = () => { + onOneOfChange([value]); + }; + + return ( + + ); + })} +
+ ); + } + + if (togglerType === 'select') { return (