[Security Solution][Onboarding] Card icons poor contrast on dark mode (#210870)
## Summary This PR addresses https://github.com/elastic/kibana/issues/206086 <img width="1142" alt="Screenshot 2025-02-12 at 16 50 32" src="https://github.com/user-attachments/assets/22d3fe32-729a-499b-8f5e-5a1e30f85e09" /> <img width="1097" alt="Screenshot 2025-02-12 at 16 51 10" src="https://github.com/user-attachments/assets/778d21ac-eec9-4184-9bc0-7714391217c1" /> ### Checklist Check the PR satisfies following conditions. Reviewers should verify this PR satisfies this list as well. - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios
Before Width: | Height: | Size: 124 KiB |
Before Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 3.3 KiB |
|
@ -9,12 +9,12 @@ import React from 'react';
|
|||
import type { OnboardingCardConfig } from '../../../../types';
|
||||
import { OnboardingCardId } from '../../../../constants';
|
||||
import { ALERTS_CARD_TITLE } from './translations';
|
||||
import alertsIcon from './images/alerts_icon.png';
|
||||
import { getCardIcon } from '../common/card_icon';
|
||||
|
||||
export const alertsCardConfig: OnboardingCardConfig = {
|
||||
id: OnboardingCardId.alerts,
|
||||
title: ALERTS_CARD_TITLE,
|
||||
icon: alertsIcon,
|
||||
icon: () => getCardIcon(OnboardingCardId.alerts),
|
||||
Component: React.lazy(
|
||||
() =>
|
||||
import(
|
||||
|
|
After Width: | Height: | Size: 1.5 KiB |
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { useDarkMode } from '@kbn/kibana-react-plugin/public';
|
||||
import { OnboardingCardId } from '../../../../constants';
|
||||
import rulesIcon from '../rules/images/rules_icon.png';
|
||||
import rulesDarkIcon from '../rules/images/rules_icon_dark.png';
|
||||
import integrationsIcon from '../integrations/images/integrations_icon.png';
|
||||
import integrationsDarkIcon from '../integrations/images/integrations_icon_dark.png';
|
||||
import dashboardsIcon from '../dashboards/images/dashboards_icon.png';
|
||||
import dashboardsDarkIcon from '../dashboards/images/dashboards_icon_dark.png';
|
||||
import alertsIcon from '../alerts/images/alerts_icon.png';
|
||||
import alertsDarkIcon from '../alerts/images/alerts_icon_dark.png';
|
||||
import startMigrationIcon from '../siem_migrations/start_migration/images/start_migration_icon.png';
|
||||
import startMigrationDarkIcon from '../siem_migrations/start_migration/images/start_migration_icon_dark.png';
|
||||
|
||||
interface CardIcons {
|
||||
[key: string]: {
|
||||
light: string;
|
||||
dark: string;
|
||||
};
|
||||
}
|
||||
|
||||
const cardIcons: CardIcons = {
|
||||
[OnboardingCardId.rules]: {
|
||||
light: rulesIcon,
|
||||
dark: rulesDarkIcon,
|
||||
},
|
||||
[OnboardingCardId.integrations]: {
|
||||
light: integrationsIcon,
|
||||
dark: integrationsDarkIcon,
|
||||
},
|
||||
[OnboardingCardId.dashboards]: {
|
||||
light: dashboardsIcon,
|
||||
dark: dashboardsDarkIcon,
|
||||
},
|
||||
[OnboardingCardId.alerts]: {
|
||||
light: alertsIcon,
|
||||
dark: alertsDarkIcon,
|
||||
},
|
||||
[OnboardingCardId.siemMigrationsStart]: {
|
||||
light: startMigrationIcon,
|
||||
dark: startMigrationDarkIcon,
|
||||
},
|
||||
};
|
||||
|
||||
interface CardIconProps {
|
||||
cardId: OnboardingCardId;
|
||||
}
|
||||
|
||||
export const CardIcon = React.memo<CardIconProps>(({ cardId }) => {
|
||||
const isDarkMode = useDarkMode();
|
||||
const icon = cardIcons[cardId]?.[isDarkMode ? 'dark' : 'light'] || '';
|
||||
|
||||
if (!icon) return null;
|
||||
|
||||
return <img src={icon} alt={`${cardId}-card-icon`} width={24} height={24} />;
|
||||
});
|
||||
|
||||
CardIcon.displayName = 'CardIcon';
|
||||
|
||||
export const getCardIcon = (cardId: OnboardingCardId) => <CardIcon cardId={cardId} />;
|
Before Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.5 KiB |
|
@ -9,12 +9,12 @@ import React from 'react';
|
|||
import type { OnboardingCardConfig } from '../../../../types';
|
||||
import { OnboardingCardId } from '../../../../constants';
|
||||
import { DASHBOARDS_CARD_TITLE } from './translations';
|
||||
import dashboardsIcon from './images/dashboards_icon.png';
|
||||
import { getCardIcon } from '../common/card_icon';
|
||||
|
||||
export const dashboardsCardConfig: OnboardingCardConfig = {
|
||||
id: OnboardingCardId.dashboards,
|
||||
title: DASHBOARDS_CARD_TITLE,
|
||||
icon: dashboardsIcon,
|
||||
icon: () => getCardIcon(OnboardingCardId.dashboards),
|
||||
Component: React.lazy(
|
||||
() =>
|
||||
import(
|
||||
|
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.6 KiB |
|
@ -10,15 +10,15 @@ import { i18n } from '@kbn/i18n';
|
|||
import type { OnboardingCardConfig } from '../../../../types';
|
||||
import { checkIntegrationsCardComplete } from './integrations_check_complete';
|
||||
import { OnboardingCardId } from '../../../../constants';
|
||||
import integrationsIcon from './images/integrations_icon.png';
|
||||
import type { IntegrationCardMetadata } from './types';
|
||||
import { getCardIcon } from '../common/card_icon';
|
||||
|
||||
export const integrationsCardConfig: OnboardingCardConfig<IntegrationCardMetadata> = {
|
||||
id: OnboardingCardId.integrations,
|
||||
title: i18n.translate('xpack.securitySolution.onboarding.integrationsCard.title', {
|
||||
defaultMessage: 'Add data with integrations',
|
||||
}),
|
||||
icon: integrationsIcon,
|
||||
icon: () => getCardIcon(OnboardingCardId.integrations),
|
||||
Component: React.lazy(
|
||||
() =>
|
||||
import(
|
||||
|
|
Before Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.3 KiB |
|
@ -9,13 +9,13 @@ import React from 'react';
|
|||
import type { OnboardingCardConfig } from '../../../../types';
|
||||
import { OnboardingCardId } from '../../../../constants';
|
||||
import { RULES_CARD_TITLE } from './translations';
|
||||
import rulesIcon from './images/rules_icon.png';
|
||||
import { checkRulesComplete } from './rules_check_complete';
|
||||
import { getCardIcon } from '../common/card_icon';
|
||||
|
||||
export const rulesCardConfig: OnboardingCardConfig = {
|
||||
id: OnboardingCardId.rules,
|
||||
title: RULES_CARD_TITLE,
|
||||
icon: rulesIcon,
|
||||
icon: () => getCardIcon(OnboardingCardId.rules),
|
||||
Component: React.lazy(
|
||||
() =>
|
||||
import(
|
||||
|
|
Before Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.3 KiB |
|
@ -9,14 +9,14 @@ import React from 'react';
|
|||
import type { OnboardingCardConfig } from '../../../../../types';
|
||||
import { OnboardingCardId } from '../../../../../constants';
|
||||
import { START_MIGRATION_CARD_TITLE } from './translations';
|
||||
import cardIcon from './images/card_header_icon.png';
|
||||
import type { StartMigrationCardMetadata } from './types';
|
||||
import { checkStartMigrationCardComplete } from './start_migration_check_complete';
|
||||
import { getCardIcon } from '../../common/card_icon';
|
||||
|
||||
export const startMigrationCardConfig: OnboardingCardConfig<StartMigrationCardMetadata> = {
|
||||
id: OnboardingCardId.siemMigrationsStart,
|
||||
title: START_MIGRATION_CARD_TITLE,
|
||||
icon: cardIcon,
|
||||
icon: () => getCardIcon(OnboardingCardId.siemMigrationsStart),
|
||||
licenseTypeRequired: 'enterprise',
|
||||
Component: React.lazy(
|
||||
() =>
|
||||
|
|
|
@ -12,7 +12,7 @@ export const HEIGHT_ANIMATION_DURATION = 250;
|
|||
|
||||
export const useCardPanelStyles = () => {
|
||||
const { euiTheme, colorMode } = useEuiTheme();
|
||||
const successBackgroundColor = euiTheme.colors.backgroundLightSuccess;
|
||||
const successBackgroundColor = euiTheme.colors.backgroundBaseSuccess;
|
||||
const isDarkMode = colorMode === COLOR_MODES_STANDARD.dark;
|
||||
const darkModeStyles = useDarkPanelStyles(isDarkMode);
|
||||
|
||||
|
@ -24,14 +24,18 @@ export const useCardPanelStyles = () => {
|
|||
.onboardingCardIcon {
|
||||
padding: ${euiTheme.size.m};
|
||||
border-radius: 50%;
|
||||
background-color: ${euiTheme.colors.backgroundBaseSubdued};
|
||||
background-color: ${isDarkMode
|
||||
? euiTheme.colors.lightShade
|
||||
: euiTheme.colors.backgroundBaseSubdued};
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.onboardingCardHeaderTitle {
|
||||
font-weight: ${euiTheme.font.weight.semiBold};
|
||||
}
|
||||
.onboardingCardHeaderCompleteBadge {
|
||||
background-color: ${successBackgroundColor};
|
||||
color: ${euiTheme.colors.textSuccess};
|
||||
background-color: ${isDarkMode ? euiTheme.colors.success : successBackgroundColor};
|
||||
color: ${isDarkMode ? euiTheme.colors.emptyShade : euiTheme.colors.textSuccess};
|
||||
}
|
||||
.onboardingCardContentWrapper {
|
||||
display: grid;
|
||||
|
|