/* * SonarQube * Copyright (C) 2009-2023 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import styled from '@emotion/styled'; import classNames from 'classnames'; import tw from 'twin.macro'; import { translate } from '../helpers/l10n'; import { themeBorder, themeColor, themeContrast, themeShadow } from '../helpers/theme'; import { RadioButtonStyled } from './RadioButton'; import { LightLabel } from './Text'; import { RecommendedIcon } from './icons/RecommendedIcon'; export interface SelectionCardProps { children?: React.ReactNode; className?: string; disabled?: boolean; onClick?: VoidFunction; recommended?: boolean; recommendedReason?: string; selected?: boolean; title: string; titleInfo?: React.ReactNode; vertical?: boolean; } export function SelectionCard(props: SelectionCardProps) { const { children, className, disabled, onClick, recommended, recommendedReason, selected = false, title, titleInfo, vertical = false, } = props; const isActionable = Boolean(onClick); return ( {isActionable && (
)}
{title} {titleInfo} {children}
{recommended && ( {translate('recommended')} {recommendedReason} )}
); } const StyledButton = styled.button` ${tw`sw-relative sw-flex sw-flex-col`} ${tw`sw-rounded-2`} ${tw`sw-box-border`} background-color: ${themeColor('backgroundSecondary')}; border: ${themeBorder('default', 'selectionCardBorder')}; &:focus { outline: none; border: ${themeBorder('default', 'selectionCardBorderHover')}; box-shadow: ${themeShadow('sm')}; } &.card-vertical { ${tw`sw-w-full`} min-height: auto; } &.card-actionable { ${tw`sw-cursor-pointer`} &:hover { border: ${themeBorder('default', 'selectionCardBorderHover')}; box-shadow: ${themeShadow('sm')}; } &.selected { border: ${themeBorder('default', 'selectionCardBorderSelected')}; } } &.disabled { ${tw`sw-cursor-not-allowed`} background-color: ${themeColor('selectionCardDisabled')}; border: ${themeBorder('default', 'selectionCardBorderDisabled')}; } `; const StyledContent = styled.div` ${tw`sw-my-4 sw-mx-3`} ${tw`sw-flex sw-grow`} ${tw`sw-text-left`} `; const StyledRecommended = styled.div` ${tw`sw-body-sm`} ${tw`sw-py-2 sw-px-4`} ${tw`sw-box-border`} ${tw`sw-rounded-b-2`} color: ${themeContrast('infoBackground')}; background-color: ${themeColor('infoBackground')}; `; const StyledRecommendedIcon = styled(RecommendedIcon)` color: ${themeColor('iconInfo')}; ${tw`sw-align-middle`} `; const StyledLabel = styled.label` ${tw`sw-flex`} ${tw`sw-mb-3 sw-gap-2`} ${tw`sw-body-sm-highlight`} color: ${themeColor('selectionCardHeader')}; .disabled & { color: ${themeContrast('selectionCardDisabled')}; } `; const StyledBody = styled.div` ${tw`sw-flex sw-grow`} ${tw`sw-flex-col sw-justify-between`} `;