Updated side panel for score L launch (#1022)

* Remove un-needed state and useEffect vars

* Add initial Accordion UI to side panel

- abstract out Indicators to separate component
- add snapshot test
- define new indicators in EXPLORE copy
- intl copy to AreaDetail component

* Make side panel indicators styling match design

* Rename export IndicatorCategory -> CategoryCard

* Add disadvangted dots to category and indicators

- add new Category component
- add new DisadvantageDot component
- make copy corrections
- comment out send feedback link in side panel

* Integrate MapLegend's dot into component

- change color to 'blue-warm-70v'
- update map stroke to 'blue-warm-70v'

* Add new indicator names from BE

- add abbreviations and use key in json file to decode
This commit is contained in:
Vim 2021-12-13 15:52:27 -05:00 committed by GitHub
commit 8a0e3a1293
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 1780 additions and 825 deletions

View file

@ -1,30 +1,19 @@
@use '../../styles/design-system.scss' as *;
@import "../utils.scss";
$sidePanelLabelFontColor: #171716;
@mixin sidePanelLabelStyle {
font-size: small;
font-size: medium;
color: $sidePanelLabelFontColor;
font-weight: 600;
}
@mixin categorizationCircleStyle {
height: 0.6rem;
width: 0.6rem;
border-radius: 100%;
align-self: center;
margin-top: 2rem;
margin-right: 0.5rem;
opacity: 0.6;
}
@mixin indicatorBox {
display: flex;
flex-direction: column;
padding: 0 1rem 1.5rem;
&:last-child {
border-bottom: none;
}
.versionInfo {
padding: .5rem 1rem .5rem 1.2rem;
font-size: medium;
font-weight: bold;
border-bottom: 1px solid $sidePanelBorderColor;
}
.areaDetailContainer {
@ -39,14 +28,25 @@ $sidePanelLabelFontColor: #171716;
align-items: center;
padding-bottom: 2rem;
.isInFocus {
padding: .5rem 1rem .25rem 1.2rem;
font-size: small;
font-weight: bold;
@include u-margin-top(2);
}
.communityOfFocus {
display: flex;
.communityOfFocusCircle {
@include categorizationCircleStyle;
background: #1a4480;
h3 {
margin-top: 0;
margin-bottom: 0;
}
}
.feedbackLink {
font-size: small;
@include u-margin-top(1);
}
}
@ -64,12 +64,10 @@ $sidePanelLabelFontColor: #171716;
}
.censusText {
font-size: small;
font-size: medium;
}
}
//Divider styles
.divider {
@include sidePanelLabelStyle;
@ -79,45 +77,3 @@ $sidePanelLabelFontColor: #171716;
border-top: 1px solid $sidePanelBorderColor;
border-bottom: 1px solid $sidePanelBorderColor;
}
//Indicator box styles
.indicatorBoxMain {
@include indicatorBox;
border-bottom: $sidePanelBorder;
}
.indicatorBoxAdditional {
@include indicatorBox;
border-bottom: 1px solid #1b1b1b;
background-color: $additionalCardsBGColor;
}
.indicatorRow {
display: flex;
@media screen and (max-width: $mobileBreakpoint) {
flex: 1 0 40%;
align-self: inherit;
padding-left: 3rem;
padding-top: 1rem;
}
.indicatorName {
flex: 0 1 77%;
}
.indicatorValue {
margin-top: 1.2rem;
margin-left: 2.2rem;
.indicatorSuperscript {
top: -0.2em
}
}
.indicatorDesc {
max-width: 10rem;
}
}

View file

@ -8,13 +8,9 @@ declare namespace MapModuleScssNamespace {
censusLabel:string;
censusText: string;
divider:string;
indicatorBoxMain:string;
indicatorBoxAdditional:string;
indicatorRow:string;
indicatorName:string;
indicatorValue:string;
indicatorSuperscript:string;
indicatorDesc:string;
feedbackLink:string;
isInFocus:string;
versionInfo: string;
}
}

View file

@ -1,46 +1,32 @@
/* eslint-disable quotes */
// External Libs:
import React, {useEffect} from 'react';
import React from 'react';
import {useIntl} from 'gatsby-plugin-intl';
import {Accordion} from '@trussworks/react-uswds';
// Components:
// import {Accordion} from '@trussworks/react-uswds';
import Category from '../Category';
import DisadvantageDot from '../DisadvantageDot';
import Indicator from '../Indicator';
// Styles and constants
import * as styles from './areaDetail.module.scss';
import * as constants from '../../data/constants';
import * as EXPLORE_COPY from '../../data/copy/explore';
import * as METHODOLOGY_COPY from '../../data/copy/methodology';
export const readablePercentile = (percentile: number | null) => {
return percentile ? Math.round(percentile * 100) : 'N/A';
};
// Todo: Add internationalization to superscript ticket #582
const getSuperscriptOrdinal = (percentile: number | string) => {
if (typeof percentile === "number") {
const englishOrdinalRules = new Intl.PluralRules('en', {
type: 'ordinal',
});
const suffixes = {
zero: 'th',
one: 'st',
two: 'nd',
few: 'rd',
many: 'th',
other: 'th',
};
return suffixes[englishOrdinalRules.select(percentile)];
}
};
interface IAreaDetailProps {
properties: constants.J40Properties,
}
export interface indicatorInfo {
label: string,
description: string,
value: number,
isDisadvagtaged: boolean,
}
const AreaDetail = ({properties}:IAreaDetailProps) => {
const intl = useIntl();
const [isCommunityFocus, setIsCommunityFocus] = React.useState<boolean>(true);
console.log("Area Detail properies: ", properties);
@ -50,122 +36,298 @@ const AreaDetail = ({properties}:IAreaDetailProps) => {
const countyName = properties[constants.COUNTY_NAME] ? properties[constants.COUNTY_NAME] : "N/A";
const stateName = properties[constants.STATE_NAME] ? properties[constants.STATE_NAME] : "N/A";
useEffect(() => {
if (score >= constants.SCORE_BOUNDARY_PRIORITIZED ) {
setIsCommunityFocus(true);
} else {
setIsCommunityFocus(false);
}
}, [score]);
const isCommunityFocus = score >= constants.SCORE_BOUNDARY_PRIORITIZED;
// const sidePanelFeedbackHref = `
// mailto:screeningtool.feedback@usds.gov?subject=Feedback on Census Tract: ${blockGroup}
// `;
interface indicatorInfo {
label: string,
description: string,
value: number,
}
// Define each indicator in the side panel with constants from copy file (for intl)
// Indicators are grouped by category
const expAgLoss:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.EXP_AG_LOSS),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.EXP_AG_LOSS),
value: properties[constants.EXP_AGRICULTURE_LOSS_PERCENTILE] ?
properties[constants.EXP_AGRICULTURE_LOSS_PERCENTILE] : null,
isDisadvagtaged: properties[constants.IS_GTE_90_EXP_AGR_LOSS_AND_IS_LOW_INCOME] ?
properties[constants.IS_GTE_90_EXP_AGR_LOSS_AND_IS_LOW_INCOME] : null,
};
const expBldLoss:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.EXP_BLD_LOSS),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.EXP_BLD_LOSS),
value: properties[constants.EXP_BUILDING_LOSS_PERCENTILE] ?
properties[constants.EXP_BUILDING_LOSS_PERCENTILE] : null,
isDisadvagtaged: properties[constants.IS_GTE_90_EXP_BLD_LOSS_AND_IS_LOW_INCOME] ?
properties[constants.IS_GTE_90_EXP_BLD_LOSS_AND_IS_LOW_INCOME] : null,
};
const expPopLoss:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.EXP_POP_LOSS),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.EXP_POP_LOSS),
value: properties[constants.EXP_POPULATION_LOSS_PERCENTILE] ?
properties[constants.EXP_POPULATION_LOSS_PERCENTILE] : null,
isDisadvagtaged: properties[constants.IS_GTE_90_EXP_POP_LOSS_AND_IS_LOW_INCOME] ?
properties[constants.IS_GTE_90_EXP_POP_LOSS_AND_IS_LOW_INCOME] : null,
};
const lowInc:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.LOW_INCOME),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.LOW_INCOME),
value: properties[constants.POVERTY_BELOW_200_PERCENTILE] ?
properties[constants.POVERTY_BELOW_200_PERCENTILE] : null,
isDisadvagtaged: properties[constants.IS_FEDERAL_POVERTY_LEVEL_200] ?
properties[constants.IS_FEDERAL_POVERTY_LEVEL_200] : null,
};
// Todo: Ticket #367 will be replacing descriptions with YAML file
const areaMedianIncome:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.AREA_MEDIAN_INCOME),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.AREA_MEDIAN_INCOME),
value: properties[constants.AREA_MEDIAN_INCOME_PERCENTILE] ?
properties[constants.AREA_MEDIAN_INCOME_PERCENTILE] : null,
};
const eduInfo:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.EDUCATION),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.EDUCATION),
value: properties[constants.EDUCATION_PROPERTY_PERCENTILE] ?
properties[constants.EDUCATION_PROPERTY_PERCENTILE] : null,
};
const poverty:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.POVERTY),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.POVERTY),
value: properties[constants.POVERTY_PROPERTY_PERCENTILE] ?
properties[constants.POVERTY_PROPERTY_PERCENTILE] : null,
};
const asthma:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.ASTHMA),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.ASTHMA),
value: properties[constants.ASTHMA_PERCENTILE] ?
properties[constants.ASTHMA_PERCENTILE] : null,
};
const diabetes:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.DIABETES),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.DIABETES),
value: properties[constants.DIABETES_PERCENTILE] ?
properties[constants.DIABETES_PERCENTILE] : null,
};
const dieselPartMatter:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.DIESEL_PARTICULATE_MATTER),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.DIESEL_PARTICULATE_MATTER),
value: properties[constants.DIESEL_MATTER_PERCENTILE] ?
properties[constants.DIESEL_MATTER_PERCENTILE] : null,
};
const lifeExpect:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.LIFE_EXPECT),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.LIFE_EXPECT),
value: properties[constants.LIFE_PERCENTILE] ?
properties[constants.LIFE_PERCENTILE] : null,
};
const energyBurden:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.ENERGY_BURDEN),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.ENERGY_BURDEN),
value: properties[constants.ENERGY_PERCENTILE] ?
properties[constants.ENERGY_PERCENTILE] : null,
isDisadvagtaged: properties[constants.IS_GTE_90_ENERGY_BURDEN_AND_IS_LOW_INCOME] ?
properties[constants.IS_GTE_90_ENERGY_BURDEN_AND_IS_LOW_INCOME] : null,
};
const pm25:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.PM_2_5),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.PM_2_5),
value: properties[constants.PM25_PERCENTILE] ?
properties[constants.PM25_PERCENTILE] : null,
isDisadvagtaged: properties[constants.IS_GTE_90_PM25_AND_IS_LOW_INCOME] ?
properties[constants.IS_GTE_90_PM25_AND_IS_LOW_INCOME] : null,
};
const leadPaint:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.LEAD_PAINT),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.LEAD_PAINT),
value: properties[constants.LEAD_PAINT_PERCENTILE] ?
properties[constants.LEAD_PAINT_PERCENTILE] : null,
const dieselPartMatter:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.DIESEL_PARTICULATE_MATTER),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.DIESEL_PARTICULATE_MATTER),
value: properties[constants.DIESEL_MATTER_PERCENTILE] ?
properties[constants.DIESEL_MATTER_PERCENTILE] : null,
isDisadvagtaged: properties[constants.IS_GTE_90_DIESEL_PM_AND_IS_LOW_INCOME] ?
properties[constants.IS_GTE_90_DIESEL_PM_AND_IS_LOW_INCOME] : null,
};
const trafficVolume:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.TRAFFIC_VOLUME),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.TRAFFIC_VOLUME),
value: properties[constants.TRAFFIC_PERCENTILE] ?
properties[constants.TRAFFIC_PERCENTILE] : null,
isDisadvagtaged: properties[constants.IS_GTE_90_TRAFFIC_PROX_AND_IS_LOW_INCOME] ?
properties[constants.IS_GTE_90_TRAFFIC_PROX_AND_IS_LOW_INCOME] : null,
};
const houseBurden:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.HOUSE_BURDEN),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.HOUSE_BURDEN),
value: properties[constants.HOUSING_BURDEN_PROPERTY_PERCENTILE] ?
properties[constants.HOUSING_BURDEN_PROPERTY_PERCENTILE] : null,
isDisadvagtaged: properties[constants.IS_GTE_90_HOUSE_BURDEN_AND_IS_LOW_INCOME] ?
properties[constants.IS_GTE_90_HOUSE_BURDEN_AND_IS_LOW_INCOME] : null,
};
const leadPaint:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.LEAD_PAINT),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.LEAD_PAINT),
value: properties[constants.LEAD_PAINT_PERCENTILE] ?
properties[constants.LEAD_PAINT_PERCENTILE] : null,
isDisadvagtaged: properties[constants.IS_GTE_90_LEAD_PAINT_AND_MEDIAN_HOME_VAL_AND_IS_LOW_INCOME] ?
properties[constants.IS_GTE_90_LEAD_PAINT_AND_MEDIAN_HOME_VAL_AND_IS_LOW_INCOME] : null,
};
// const medHomeVal:indicatorInfo = {
// label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.MED_HOME_VAL),
// description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.MED_HOME_VAL),
// value: properties[constants.MEDIAN_HOME_VALUE_PERCENTILE] ?
// properties[constants.MEDIAN_HOME_VALUE_PERCENTILE] : null,
// isDisadvagtaged: false, // TODO
// };
const proxHaz:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.PROX_HAZ),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.PROX_HAZ),
value: properties[constants.PROXIMITY_TSDF_SITES_PERCENTILE] ?
properties[constants.PROXIMITY_TSDF_SITES_PERCENTILE] : null,
isDisadvagtaged: properties[constants.IS_GTE_90_HAZARD_WASTE_AND_IS_LOW_INCOME] ?
properties[constants.IS_GTE_90_HAZARD_WASTE_AND_IS_LOW_INCOME] : null,
};
const proxNPL:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.PROX_NPL),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.PROX_NPL),
value: properties[constants.PROXIMITY_NPL_SITES_PERCENTILE] ?
properties[constants.PROXIMITY_NPL_SITES_PERCENTILE] : null,
isDisadvagtaged: properties[constants.IS_GTE_90_SUPERFUND_AND_IS_LOW_INCOME] ?
properties[constants.IS_GTE_90_SUPERFUND_AND_IS_LOW_INCOME] : null,
};
const proxRMP:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.PROX_RMP),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.PROX_RMP),
value: properties[constants.PROXIMITY_RMP_SITES_PERCENTILE] ?
properties[constants.PROXIMITY_RMP_SITES_PERCENTILE] : null,
isDisadvagtaged: properties[constants.IS_GTE_90_RMP_AND_IS_LOW_INCOME] ?
properties[constants.IS_GTE_90_RMP_AND_IS_LOW_INCOME] : null,
};
const wasteWater:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.WASTE_WATER),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.WASTE_WATER),
value: properties[constants.WASTEWATER_PERCENTILE] ?
properties[constants.WASTEWATER_PERCENTILE] : null,
isDisadvagtaged: properties[constants.IS_GTE_90_WASTEWATER_AND_IS_LOW_INCOME] ?
properties[constants.IS_GTE_90_WASTEWATER_AND_IS_LOW_INCOME] : null,
};
const femaRisk:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.FEMA_RISK),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.FEMA_RISK),
value: properties[constants.FEMA_PERCENTILE] ?
properties[constants.FEMA_PERCENTILE] : null,
const asthma:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.ASTHMA),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.ASTHMA),
value: properties[constants.ASTHMA_PERCENTILE] ?
properties[constants.ASTHMA_PERCENTILE] : null,
isDisadvagtaged: properties[constants.IS_GTE_90_ASTHMA_AND_IS_LOW_INCOME] ?
properties[constants.IS_GTE_90_ASTHMA_AND_IS_LOW_INCOME] : null,
};
const diabetes:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.DIABETES),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.DIABETES),
value: properties[constants.DIABETES_PERCENTILE] ?
properties[constants.DIABETES_PERCENTILE] : null,
isDisadvagtaged: properties[constants.IS_GTE_90_DIABETES_AND_IS_LOW_INCOME] ?
properties[constants.IS_GTE_90_DIABETES_AND_IS_LOW_INCOME] : null,
};
const heartDisease:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.HEART_DISEASE),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.HEART_DISEASE),
value: properties[constants.HEART_PERCENTILE] ?
properties[constants.HEART_PERCENTILE] : null,
isDisadvagtaged: properties[constants.IS_GTE_90_HEART_DISEASE_AND_IS_LOW_INCOME] ?
properties[constants.IS_GTE_90_HEART_DISEASE_AND_IS_LOW_INCOME] : null,
};
const houseBurden:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.HOUSE_BURDEN),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.HOUSE_BURDEN),
value: properties[constants.HOUSING_BURDEN_PROPERTY_PERCENTILE] ?
properties[constants.HOUSING_BURDEN_PROPERTY_PERCENTILE] : null,
const lifeExpect:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.LIFE_EXPECT),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.LOW_LIFE_EXPECT),
value: properties[constants.LIFE_PERCENTILE] ?
properties[constants.LIFE_PERCENTILE] : null,
isDisadvagtaged: properties[constants.IS_GTE_90_LOW_LIFE_EXP_AND_IS_LOW_INCOME] ?
properties[constants.IS_GTE_90_LOW_LIFE_EXP_AND_IS_LOW_INCOME] : null,
};
const lowMedInc:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.LOW_MED_INC),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.LOW_MED_INCOME),
value: properties[constants.LOW_MEDIAN_INCOME_PERCENTILE] ?
properties[constants.LOW_MEDIAN_INCOME_PERCENTILE] : null,
isDisadvagtaged: properties[constants.IS_GTE_90_LOW_MEDIAN_INCOME_AND_LOW_HIGH_SCHOOL_EDU] ?
properties[constants.IS_GTE_90_LOW_MEDIAN_INCOME_AND_LOW_HIGH_SCHOOL_EDU] : null,
};
const lingIso:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.LING_ISO),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.LING_ISO),
value: properties[constants.LINGUISTIC_ISOLATION_PROPERTY_PERCENTILE] ?
properties[constants.LINGUISTIC_ISOLATION_PROPERTY_PERCENTILE] : null,
isDisadvagtaged: properties[constants.IS_GTE_90_LINGUISITIC_ISO_AND_IS_LOW_INCOME] ?
properties[constants.IS_GTE_90_LINGUISITIC_ISO_AND_IS_LOW_INCOME] : null,
};
const unemploy:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.UNEMPLOY),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.UNEMPLOY),
value: properties[constants.UNEMPLOYMENT_PROPERTY_PERCENTILE] ?
properties[constants.UNEMPLOYMENT_PROPERTY_PERCENTILE] : null,
isDisadvagtaged: properties[constants.IS_GTE_90_UNEMPLOYMENT_AND_LOW_HIGH_SCHOOL_EDU] ?
properties[constants.IS_GTE_90_UNEMPLOYMENT_AND_LOW_HIGH_SCHOOL_EDU] : null,
};
const poverty:indicatorInfo = {
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.POVERTY),
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.POVERTY),
value: properties[constants.POVERTY_PROPERTY_PERCENTILE] ?
properties[constants.POVERTY_PROPERTY_PERCENTILE] : null,
isDisadvagtaged: properties[constants.IS_GTE_90_BELOW_100_POVERTY_AND_LOW_HIGH_SCHOOL_EDU] ?
properties[constants.IS_GTE_90_BELOW_100_POVERTY_AND_LOW_HIGH_SCHOOL_EDU] : null,
};
// const highSchool:indicatorInfo = {
// label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.HIGH_SCL),
// description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.HIGH_SKL),
// value: properties[constants.HIGH_SCHOOL_PROPERTY_PERCENTILE] ?
// properties[constants.HIGH_SCHOOL_PROPERTY_PERCENTILE] : null,
// isDisadvagtaged: properties[constants.IS_GTE_90_BELOW_100_POVERTY_AND_LOW_HIGH_SCHOOL_EDU] ?
// properties[constants.IS_GTE_90_BELOW_100_POVERTY_AND_LOW_HIGH_SCHOOL_EDU] : null,
// };
const indicators = [areaMedianIncome, eduInfo, poverty];
const additionalIndicators = [
asthma, diabetes, dieselPartMatter, energyBurden, femaRisk, heartDisease,
houseBurden, leadPaint, lifeExpect, pm25, trafficVolume, wasteWater,
// Aggregate indicators based on categories
const categories = [
{
id: 'climate-change',
titleText: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CATEGORY.CLIMATE),
indicators: [expAgLoss, expBldLoss, expPopLoss, lowInc],
isDisadvagtaged: properties[constants.IS_CLIMATE_FACTOR_DISADVANTAGED_L] ?
properties[constants.IS_CLIMATE_FACTOR_DISADVANTAGED_L] : null,
},
{
id: 'clean-energy',
titleText: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CATEGORY.CLEAN_ENERGY),
indicators: [energyBurden, pm25, lowInc],
isDisadvagtaged: properties[constants.IS_ENERGY_FACTOR_DISADVANTAGED_L] ?
properties[constants.IS_ENERGY_FACTOR_DISADVANTAGED_L] : null,
},
{
id: 'clean-transport',
titleText: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CATEGORY.CLEAN_TRANSPORT),
indicators: [dieselPartMatter, trafficVolume, lowInc],
isDisadvagtaged: properties[constants.IS_TRANSPORT_FACTOR_DISADVANTAGED_L] ?
properties[constants.IS_TRANSPORT_FACTOR_DISADVANTAGED_L] : null,
},
{
id: 'sustain-house',
titleText: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CATEGORY.SUSTAIN_HOUSE),
indicators: [houseBurden, leadPaint, lowInc],
isDisadvagtaged: properties[constants.IS_HOUSING_FACTOR_DISADVANTAGED_L] ?
properties[constants.IS_HOUSING_FACTOR_DISADVANTAGED_L] : null,
},
{
id: 'leg-pollute',
titleText: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CATEGORY.LEG_POLLUTE),
indicators: [proxHaz, proxNPL, proxRMP, lowInc],
isDisadvagtaged: properties[constants.IS_POLLUTION_FACTOR_DISADVANTAGED_L] ?
properties[constants.IS_POLLUTION_FACTOR_DISADVANTAGED_L] : null,
},
{
id: 'clean-water',
titleText: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CATEGORY.CLEAN_WATER),
indicators: [wasteWater, lowInc],
isDisadvagtaged: properties[constants.IS_WATER_FACTOR_DISADVANTAGED_L] ?
properties[constants.IS_WATER_FACTOR_DISADVANTAGED_L] : null,
},
{
id: 'health-burdens',
titleText: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CATEGORY.HEALTH_BURDEN),
indicators: [asthma, diabetes, heartDisease, lifeExpect, lowInc],
isDisadvagtaged: properties[constants.IS_HEALTH_FACTOR_DISADVANTAGED_L] ?
properties[constants.IS_HEALTH_FACTOR_DISADVANTAGED_L] : null,
},
{
id: 'work-dev',
titleText: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CATEGORY.WORK_DEV),
indicators: [lowMedInc, lingIso, unemploy, poverty],
isDisadvagtaged: properties[constants.IS_WORKFORCE_FACTOR_DISADVANTAGED_L] ?
properties[constants.IS_WORKFORCE_FACTOR_DISADVANTAGED_L] : null,
},
];
// Create the AccoridionItems by mapping over the categories array. In this array we define the
// various indicators for a specific category. This is an array which then maps over the <Indicator />
// component to render the actual Indicator
const categoryItems = categories.map((category) => ({
id: category.id,
title: <Category name={category.titleText} isDisadvantaged={category.isDisadvagtaged}/>,
content: (
<>
{category.indicators.map((indicator:any, index:number) => {
return <Indicator key={`ind${index}`} indicator={indicator}/>;
})}
</>
),
expanded: false,
}));
return (
<aside className={styles.areaDetailContainer} data-cy={'aside'}>
{/* Methodology version */}
<div className={styles.versionInfo}>
{EXPLORE_COPY.SIDE_PANEL_VERION.TITLE}
</div>
{/* Census Info */}
<ul className={styles.censusRow}>
<li>
<span className={styles.censusLabel}>
@ -192,139 +354,27 @@ const AreaDetail = ({properties}:IAreaDetailProps) => {
<span className={styles.censusText}>{` ${population.toLocaleString()}`}</span>
</li>
</ul>
{/* Disadvantaged? */}
<div className={styles.categorization}>
<div className={styles.isInFocus}>
{EXPLORE_COPY.COMMUNITY.IS_FOCUS}
</div>
<div className={styles.communityOfFocus}>
{isCommunityFocus ?
<>
<div className={styles.communityOfFocusCircle} />
<h3>{EXPLORE_COPY.COMMUNITY.OF_FOCUS}</h3>
<DisadvantageDot isDisadvantaged={isCommunityFocus}/>
</> :
<h3>{EXPLORE_COPY.COMMUNITY.NOT_OF_FOCUS}</h3>
}
</div>
<p className={"secondary"}>version {METHODOLOGY_COPY.VERSION_NUMBER}</p>
</div>
<div className={styles.divider}>
<h6>
{intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.INDICATOR_COLUMN_HEADER)}
</h6>
<h6>
{intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.PERCENTILE_COLUMN_HEADER)}
</h6>
{/* eslint-disable-next-line max-len */}
{/* <a className={styles.feedbackLink} href={sidePanelFeedbackHref}>{EXPLORE_COPY.COMMUNITY.SEND_FEEDBACK}</a> */}
</div>
<>
{
indicators.map((indicator:any, index:number) => {
return <li key={`ind${index}`} className={styles.indicatorBoxMain} data-cy={'indicatorBox'}>
<div className={styles.indicatorRow}>
<h4 className={styles.indicatorName}>{indicator.label}</h4>
<div className={styles.indicatorValue}>
{readablePercentile(indicator.value)}
<sup className={styles.indicatorSuperscript}><span>
{getSuperscriptOrdinal(readablePercentile(indicator.value))}
</span></sup>
</div>
</div>
<p className={'secondary j40-indicator'}>
{indicator.description}
</p>
</li>;
})
}
</>
<>
{
additionalIndicators.map((indicator:any, index:number) => {
return <li
key={`ind${index}`}
className={styles.indicatorBoxAdditional}
data-cy={'indicatorBox'}>
<div className={styles.indicatorRow}>
<h4 className={styles.indicatorName}>{indicator.label}</h4>
<div className={styles.indicatorValue}>
{readablePercentile(indicator.value)}
<sup className={styles.indicatorSuperscript}><span>
{getSuperscriptOrdinal(readablePercentile(indicator.value))}
</span></sup>
</div>
</div>
<p className={'secondary j40-indicator'}>
{indicator.description}
</p>
</li>;
})
}
</>
{/* Temporarily remove Accordions and may place back in later, removed unused
className prop as as styles are based on the id of the Accordion Item */}
{/* <Accordion
multiselectable={true}
items={
[
{
id: 'prioritization-indicators',
title: 'Indicators',
content: (
<>
{
indicators.map((indicator:any, index:number) => {
return <li key={`ind${index}`} className={styles.indicatorBoxMain} data-cy={'indicatorBox'}>
<div className={styles.indicatorRow}>
<h4 className={styles.indicatorName}>{indicator.label}</h4>
<div className={styles.indicatorValue}>
{readablePercentile(indicator.value)}
<sup className={styles.indicatorSuperscript}><span>
{getSuperscriptOrdinal(readablePercentile(indicator.value))}
</span></sup>
</div>
</div>
<p className={'secondary j40-indicator'}>
{indicator.description}
</p>
</li>;
})
}
</>
),
expanded: true,
},
{
id: 'additional-indicators',
title: 'Additional indicators (not used in prioritization)',
content: (
(
<>
{
additionalIndicators.map((indicator:any, index:number) => {
return <li
key={`ind${index}`}
className={styles.indicatorBoxAdditional}
data-cy={'indicatorBox'}>
<div className={styles.indicatorRow}>
<h4 className={styles.indicatorName}>{indicator.label}</h4>
<div className={styles.indicatorValue}>
{readablePercentile(indicator.value)}
<sup className={styles.indicatorSuperscript}><span>
{getSuperscriptOrdinal(readablePercentile(indicator.value))}
</span></sup>
</div>
</div>
<p className={'secondary j40-indicator'}>
{indicator.description}
</p>
</li>;
})
}
</>
)
),
expanded: true,
},
]
}/> */}
{/* All category accordions in this component */}
<Accordion multiselectable={true} items={categoryItems}/>
</aside>
);

View file

@ -1,6 +1,6 @@
import * as React from 'react';
import {render} from '@testing-library/react';
import AreaDetail, {readablePercentile} from '..';
import AreaDetail from '..';
import {LocalizedComponent} from '../../../test/testHelpers';
import * as constants from '../../../data/constants';
@ -29,9 +29,3 @@ describe('rendering of the AreaDetail', () => {
});
});
describe('tests the readablePercentile function', () => {
expect(readablePercentile(.98)).toEqual(98);
expect(readablePercentile(.07)).toEqual(7);
expect(readablePercentile(.123)).toEqual(12);
expect(readablePercentile(.789)).toEqual(79);
});

View file

@ -1,7 +1,7 @@
import React from 'react';
import {Grid} from '@trussworks/react-uswds';
import IndicatorCategory from '../CategoryCard';
import CategoryCard from '../CategoryCard';
import J40MainGridContainer from '../J40MainGridContainer';
import * as METHODOLOGY_COPY from '../../data/copy/methodology';
@ -33,7 +33,7 @@ const Categories = () => {
<J40MainGridContainer className={styles.categoriesContainer}>
{
categories.map((category, index) => <IndicatorCategory key={index} categoryInfo={category} />)
categories.map((category, index) => <CategoryCard key={index} categoryInfo={category} />)
}
</J40MainGridContainer>
</>

View file

@ -0,0 +1,6 @@
@use '../../styles/design-system.scss' as *;
.categoryContainer {
display: flex;
justify-content: space-between;
}

View file

@ -0,0 +1,13 @@
declare namespace CategoryNamespace {
export interface ICategoryScss {
categoryContainer: string;
disadvantageDot: string;
}
}
declare const CategoryScssModule: CategoryNamespace.ICategoryScss & {
/** WARNING: Only available when `css-loader` is used without `style-loader` or `mini-css-extract-plugin` */
locals: CategoryNamespace.ICategoryScss;
};
export = CategoryScssModule;

View file

@ -0,0 +1,28 @@
import * as React from 'react';
import {render} from '@testing-library/react';
import {LocalizedComponent} from '../../test/testHelpers';
import Category from './Category';
describe('rendering of the Category disadvantaged', () => {
const {asFragment} = render(
<LocalizedComponent>
<Category name={'test name'} isDisadvantaged={true}/>
</LocalizedComponent>,
);
it('checks if component renders', () => {
expect(asFragment()).toMatchSnapshot();
});
});
describe('rendering of the Category non-disadvantaged', () => {
const {asFragment} = render(
<LocalizedComponent>
<Category name={'test name'} isDisadvantaged={false}/>
</LocalizedComponent>,
);
it('checks if component renders', () => {
expect(asFragment()).toMatchSnapshot();
});
});

View file

@ -0,0 +1,22 @@
import React from 'react';
import DisadvantageDot from '../DisadvantageDot';
import * as styles from './Category.module.scss';
interface ICategory {
name: string;
isDisadvantaged: boolean;
}
const Category = ({name, isDisadvantaged}:ICategory) => {
return (
<div className={styles.categoryContainer}>
<div>
{name}
</div>
<DisadvantageDot isDisadvantaged={isDisadvantaged}/>
</div>
);
};
export default Category;

View file

@ -0,0 +1,14 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`rendering of the Category disadvantaged checks if component renders 1`] = `
<DocumentFragment>
<div>
<div>
test name
</div>
<div />
</div>
</DocumentFragment>
`;
exports[`rendering of the Category non-disadvantaged checks if component renders 1`] = `<DocumentFragment />`;

View file

@ -0,0 +1,3 @@
import Category from './Category';
export default Category;

View file

@ -10,7 +10,7 @@ interface ICategoryInterface {
THEN: JSX.Element
}
}
const IndicatorCategory = ({categoryInfo}: ICategoryInterface) => {
const CategoryCard = ({categoryInfo}: ICategoryInterface) => {
return (
<div className={styles.categoryCard}>
<h3>
@ -29,4 +29,4 @@ const IndicatorCategory = ({categoryInfo}: ICategoryInterface) => {
);
};
export default IndicatorCategory;
export default CategoryCard;

View file

@ -0,0 +1,19 @@
@use '../../styles/design-system.scss' as *;
.disadvantagedDotSmall {
@include u-circle('105');
@include u-margin-left(1);
align-self: center;
@include u-bg('blue-warm-70v');
}
.disadvantagedDotBig {
@include u-circle(4);
margin: 2.3rem 1.5rem 2rem 0;
opacity: .6;
//Maintain aspect ratio as screen width decreases
flex: 1 0 2rem;
@include u-bg('blue-warm-70v');
}

View file

@ -0,0 +1,14 @@
declare namespace DisadvantagedDotNamespace {
export interface IDisadvantagedDot {
disadvantagedDotBig: string;
disadvantagedDotSmall: string;
}
}
declare const DisadvantagedDotModule: DisadvantagedDotNamespace.IDisadvantagedDot & {
/** WARNING: Only available when `css-loader` is used without `style-loader` or `mini-css-extract-plugin` */
locals: DisadvantagedDotNamespace.IDisadvantagedDot;
};
export = DisadvantagedDotModule;

View file

@ -0,0 +1,16 @@
import * as React from 'react';
import {render} from '@testing-library/react';
import {LocalizedComponent} from '../../test/testHelpers';
import DisadvantageDot from './DisadvantageDot';
describe('rendering of the DisadvantageDot disadvantaged', () => {
const {asFragment} = render(
<LocalizedComponent>
<DisadvantageDot isDisadvantaged={true}/>
</LocalizedComponent>,
);
it('checks if component renders', () => {
expect(asFragment()).toMatchSnapshot();
});
});

View file

@ -0,0 +1,23 @@
import React from 'react';
import * as styles from './DisadvantageDot.module.scss';
interface IDisadvantageDot {
isDisadvantaged?: boolean;
isBig?: boolean;
}
const DisadvantageDot = ({isDisadvantaged = false, isBig}:IDisadvantageDot) => {
let computedClass = '';
if (isBig) {
computedClass = styles.disadvantagedDotBig;
} else {
computedClass = isDisadvantaged ? styles.disadvantagedDotSmall : '';
}
return (
<div className={computedClass} />
);
};
export default DisadvantageDot;

View file

@ -0,0 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`rendering of the DisadvantageDot disadvantaged checks if component renders 1`] = `
<DocumentFragment>
<div />
</DocumentFragment>
`;

View file

@ -0,0 +1,3 @@
import DisadvantageDot from './DisadvantageDot';
export default DisadvantageDot;

View file

@ -0,0 +1,59 @@
@use '../../styles/design-system.scss' as *;
@import "../utils.scss";
@mixin indicator {
display: flex;
flex-direction: column;
@include u-padding-bottom(3);
&:last-child {
border-bottom: none;
@include u-padding-bottom(0);
}
.indicatorRow {
display: flex;
@media screen and (max-width: $mobileBreakpoint) {
flex: 1 0 40%;
align-self: inherit;
padding-left: 3rem;
padding-top: 1rem;
}
.indicatorName {
flex: 0 1 77%;
display: flex;
flex-direction: column;
@include typeset('sans', '2xs', 2);
@include u-text('bold');
.indicatorDesc {
@include typeset('sans', '3xs', 2);
@include u-text('normal');
max-width: 12rem;
@include u-margin-top(0);
@media screen and (max-width: 1024px) {
max-width: 80%;
}
}
}
.indicatorValue {
margin-left: 2.2rem;
.indicatorSuperscript {
top: -0.2em
}
}
}
}
//Indicator box styles
.indicatorBoxMain {
@include indicator;
}
.disadvantagedIndicator {
@include indicator;
@include u-text('blue-warm-70v');
}

View file

@ -0,0 +1,19 @@
declare namespace IndicatorNamespace {
export interface IIndicatorScss {
indicatorBoxMain:string;
indicatorBoxAdditional:string;
indicatorRow:string;
indicatorName:string;
indicatorValue:string;
indicatorSuperscript:string;
indicatorDesc:string;
disadvantagedIndicator:string;
}
}
declare const IndicatorScssModule: IndicatorNamespace.IIndicatorScss & {
/** WARNING: Only available when `css-loader` is used without `style-loader` or `mini-css-extract-plugin` */
locals: IndicatorNamespace.IIndicatorScss;
};
export = IndicatorScssModule;

View file

@ -0,0 +1,30 @@
import * as React from 'react';
import {render} from '@testing-library/react';
import {LocalizedComponent} from '../../test/testHelpers';
import Indicator, {readablePercentile} from './Indicator';
import {indicatorInfo} from '../AreaDetail';
const highSchool:indicatorInfo = {
label: 'some label',
description: 'some description',
value: 97,
};
describe('rendering of the Indicator', () => {
const {asFragment} = render(
<LocalizedComponent>
<Indicator indicator={highSchool}/>
</LocalizedComponent>,
);
it('checks if component renders', () => {
expect(asFragment()).toMatchSnapshot();
});
});
describe('tests the readablePercentile function', () => {
expect(readablePercentile(.98)).toEqual(98);
expect(readablePercentile(.07)).toEqual(7);
expect(readablePercentile(.123)).toEqual(12);
expect(readablePercentile(.789)).toEqual(79);
});

View file

@ -0,0 +1,55 @@
import React from 'react';
import {indicatorInfo} from '../AreaDetail';
import * as styles from './Indicator.module.scss';
interface IIndicator {
indicator: indicatorInfo,
}
export const readablePercentile = (percentile: number | null) => {
return percentile ? Math.round(percentile * 100) : 'N/A';
};
// Todo: Add internationalization to superscript ticket #582
export const getSuperscriptOrdinal = (percentile: number | string) => {
if (typeof percentile === 'number') {
const englishOrdinalRules = new Intl.PluralRules('en', {
type: 'ordinal',
});
const suffixes = {
zero: 'th',
one: 'st',
two: 'nd',
few: 'rd',
many: 'th',
other: 'th',
};
return suffixes[englishOrdinalRules.select(percentile)];
}
};
const Indicator = ({indicator}:IIndicator) => {
return (
<li
className={indicator.isDisadvagtaged ? styles.disadvantagedIndicator : styles.indicatorBoxMain}
data-cy={'indicatorBox'}>
<div className={styles.indicatorRow}>
<div className={styles.indicatorName}>
{indicator.label}
<div className={styles.indicatorDesc}>
{indicator.description}
</div>
</div>
<div className={styles.indicatorValue}>
{readablePercentile(indicator.value)}
<sup className={styles.indicatorSuperscript}><span>
{getSuperscriptOrdinal(readablePercentile(indicator.value))}
</span></sup>
</div>
</div>
</li>
);
};
export default Indicator;

View file

@ -0,0 +1,26 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`rendering of the Indicator checks if component renders 1`] = `
<DocumentFragment>
<li
data-cy="indicatorBox"
>
<div>
<div>
some label
<div>
some description
</div>
</div>
<div>
9700
<sup>
<span>
th
</span>
</sup>
</div>
</div>
</li>
</DocumentFragment>
`;

View file

@ -0,0 +1,3 @@
import Indicator from './Indicator';
export default Indicator;

View file

@ -3,13 +3,14 @@ import {useIntl} from 'gatsby-plugin-intl';
import * as styles from './mapLegend.module.scss';
import * as EXPLORE_COPY from '../../data/copy/explore';
import DisadvantageDot from '../DisadvantageDot';
const MapLegend = () => {
const intl = useIntl();
return (
<div className={styles.legendContainer}>
<div className={styles.colorSwatch} />
<div>
<DisadvantageDot isBig={true} />
<div className={styles.legendTextBox}>
<div className={'j40-h4'}>
{intl.formatMessage(EXPLORE_COPY.LEGEND.PRIORITY_LABEL)}
</div>

View file

@ -1,26 +1,17 @@
@import "../utils.scss";
$min-color: #fafaf8;
$med-color: rgba(26, 68, 128, 0.2);
$max-color: rgba(26, 68, 128, 0.6);
$alertInfoColor: #e7f6f8;
.legendContainer {
display: flex;
margin: 1rem 0 1rem 2.5rem;
border: 1px solid #DFE1E2;
padding: .5rem 1.5rem 1rem 1.5rem;
margin: 1rem 0 1rem 2.5rem;
padding: 0 1.5rem 1rem 1.5rem;
.legendTextBox {
// Set maximum width for text area so that blue dot
// doesn't lose aspect ratio
flex-basis: 88%;
}
@media screen and (max-width: 640px) {
margin: 1rem 0 0;
}
}
.colorSwatch {
flex: 1 0 2rem;
box-sizing: border-box;
height: 2rem;
margin: 2rem 1.5rem 2rem 0;
border-radius: 50%;
background-color: $max-color;
}

View file

@ -1,7 +1,7 @@
declare namespace HowYouCanHelpModuleScssNamespace {
export interface IHowYouCanHelpModuleScss {
legendContainer: string;
colorSwatch: string;
legendTextBox: string;
}
}