Skip to content

Commit

Permalink
fix(app,components): apply drop shadow filter to labware highlight (#…
Browse files Browse the repository at this point in the history
…16117)

we've been using a gaussian blur filter to the SVG labware outline to
achieve a box-shadow-like effect to highlight labware. the drop shadow
filter does a closer approximation to box shadow. multiple drop shadow
filters do even better to approximate the spread specified in designs.

closes RQA-3019
  • Loading branch information
brenthagen authored Aug 26, 2024
1 parent 0da0f4d commit eb857f4
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ export function SetupLabwareMap({
topLabwareDefinition != null &&
topLabwareId != null &&
hoverLabwareId === topLabwareId,
highlightShadowLabware:
topLabwareDefinition != null &&
topLabwareId != null &&
hoverLabwareId === topLabwareId,
stacked: topLabwareDefinition != null && topLabwareId != null,
moduleChildren: (
// open modal
Expand Down Expand Up @@ -148,6 +152,7 @@ export function SetupLabwareMap({
topLabwareId,
topLabwareDisplayName,
highlight: isLabwareInStack && hoverLabwareId === topLabwareId,
highlightShadow: isLabwareInStack && hoverLabwareId === topLabwareId,
labwareChildren: (
<g
cursor={isLabwareInStack ? 'pointer' : ''}
Expand Down
3 changes: 3 additions & 0 deletions app/src/organisms/ProtocolSetupLabware/LabwareMapView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ export function LabwareMapView(props: LabwareMapViewProps): JSX.Element {
}
: undefined,
highlightLabware: true,
highlightShadowLabware:
topLabwareDefinition != null && topLabwareId != null,
moduleChildren: null,
stacked: topLabwareDefinition != null && topLabwareId != null,
}
Expand Down Expand Up @@ -99,6 +101,7 @@ export function LabwareMapView(props: LabwareMapViewProps): JSX.Element {
},
labwareChildren: null,
highlight: true,
highlightShadow: isLabwareInStack,
stacked: isLabwareInStack,
}
}
Expand Down
6 changes: 6 additions & 0 deletions components/src/hardware-sim/BaseDeck/BaseDeck.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export interface LabwareOnDeck {
labwareChildren?: React.ReactNode
onLabwareClick?: () => void
highlight?: boolean
highlightShadow?: boolean
stacked?: boolean
}

Expand All @@ -70,6 +71,7 @@ export interface ModuleOnDeck {
moduleChildren?: React.ReactNode
onLabwareClick?: () => void
highlightLabware?: boolean
highlightShadowLabware?: boolean
stacked?: boolean
}
interface BaseDeckProps {
Expand Down Expand Up @@ -250,6 +252,7 @@ export function BaseDeck(props: BaseDeckProps): JSX.Element {
moduleChildren,
onLabwareClick,
highlightLabware,
highlightShadowLabware,
}) => {
const slotPosition = getPositionFromSlotId(
moduleLocation.slotName,
Expand Down Expand Up @@ -277,6 +280,7 @@ export function BaseDeck(props: BaseDeckProps): JSX.Element {
'left' && moduleModel === HEATERSHAKER_MODULE_V1
}
highlight={highlightLabware}
highlightShadow={highlightShadowLabware}
/>
) : null}
{moduleChildren}
Expand All @@ -294,6 +298,7 @@ export function BaseDeck(props: BaseDeckProps): JSX.Element {
missingTips,
onLabwareClick,
highlight,
highlightShadow,
}) => {
if (
labwareLocation === 'offDeck' ||
Expand Down Expand Up @@ -322,6 +327,7 @@ export function BaseDeck(props: BaseDeckProps): JSX.Element {
wellFill={wellFill ?? undefined}
missingTips={missingTips}
highlight={highlight}
highlightShadow={highlightShadow}
/>
{labwareChildren}
</g>
Expand Down
22 changes: 21 additions & 1 deletion components/src/hardware-sim/Labware/LabwareAdapter/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,18 @@ export interface LabwareAdapterProps {
labwareLoadName: LabwareAdapterLoadName
definition?: LabwareDefinition2
highlight?: boolean
highlightShadow?: boolean
}

export const LabwareAdapter = (
props: LabwareAdapterProps
): JSX.Element | null => {
const { labwareLoadName, definition, highlight = false } = props
const {
labwareLoadName,
definition,
highlight = false,
highlightShadow,
} = props
const highlightOutline =
highlight && definition != null ? (
<LabwareOutline
Expand All @@ -39,10 +45,24 @@ export const LabwareAdapter = (
fill={COLORS.transparent}
/>
) : null
const highlightShadowOutline =
highlight && definition != null ? (
<LabwareOutline
definition={definition}
highlight={highlight}
highlightShadow={highlightShadow}
fill={COLORS.transparent}
/>
) : null
const SVGElement = LABWARE_ADAPTER_LOADNAME_PATHS[labwareLoadName]

return (
<g>
{/**
* render an initial shadow outline first in the DOM so that the SVG highlight shadow
* does not layer over the inside of the SVG labware adapter
*/}
{highlightShadowOutline}
<SVGElement />
{highlightOutline}
</g>
Expand Down
4 changes: 4 additions & 0 deletions components/src/hardware-sim/Labware/LabwareRender.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ export interface LabwareRenderProps {
labwareStroke?: CSSProperties['stroke']
/** adds thicker blue border with blur to labware */
highlight?: boolean
/** adds a drop shadow to the highlight border */
highlightShadow?: boolean
/** Optional callback, called with WellMouseEvent args onMouseEnter */
onMouseEnterWell?: (e: WellMouseEvent) => unknown
/** Optional callback, called with WellMouseEvent args onMouseLeave */
Expand Down Expand Up @@ -90,6 +92,7 @@ export const LabwareRender = (props: LabwareRenderProps): JSX.Element => {
labwareLoadName={labwareLoadName as LabwareAdapterLoadName}
definition={definition}
highlight={props.highlight}
highlightShadow={props.highlightShadow}
/>
</g>
</g>
Expand All @@ -107,6 +110,7 @@ export const LabwareRender = (props: LabwareRenderProps): JSX.Element => {
onMouseLeaveWell={props.onMouseLeaveWell}
onLabwareClick={props.onLabwareClick}
highlight={props.highlight}
highlightShadow={props.highlightShadow}
/>
{props.wellStroke != null ? (
<StrokedWells
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export interface LabwareOutlineProps {
isTiprack?: boolean
/** adds thicker blue border with blur to labware, defaults to false */
highlight?: boolean
/** adds a drop shadow to the highlight border */
highlightShadow?: boolean
/** [legacy] override the border color */
stroke?: CSSProperties['stroke']
fill?: CSSProperties['fill']
Expand All @@ -31,6 +33,7 @@ export function LabwareOutline(props: LabwareOutlineProps): JSX.Element {
height = SLOT_RENDER_HEIGHT,
isTiprack = false,
highlight = false,
highlightShadow = false,
stroke,
fill,
showRadius = true,
Expand All @@ -52,31 +55,41 @@ export function LabwareOutline(props: LabwareOutlineProps): JSX.Element {
<>
<defs>
<filter id="feOffset" filterUnits="objectBoundingBox">
<feGaussianBlur stdDeviation="6" />
{/* *
* TODO(bh, 2024-08-23): layer drop shadow filters to mimic CSS box shadow - may need to evaluate performance
* https://stackoverflow.com/questions/22486039/css3-filter-drop-shadow-spread-property-alternatives
* */}
<feDropShadow
dx="0"
dy="0"
stdDeviation="3"
floodColor={COLORS.blue50}
/>
<feDropShadow
dx="0"
dy="0"
stdDeviation="1.75"
floodColor={COLORS.blue50}
/>
<feDropShadow
dx="0"
dy="0"
stdDeviation="1"
floodColor={COLORS.blue50}
/>
</filter>
</defs>
{/* TODO(bh, 2024-07-22): adjust gaussian blur for stacks */}
<LabwareBorder
borderThickness={1.5 * OUTLINE_THICKNESS_MM}
borderThickness={2.2 * OUTLINE_THICKNESS_MM}
xDimension={dimensions.xDimension}
yDimension={dimensions.yDimension}
filter="url(#feOffset)"
stroke="#74B0FF"
filter={highlightShadow ? 'url(#feOffset)' : ''}
stroke={COLORS.blue50}
rx="8"
ry="8"
showRadius={showRadius}
fill={backgroundFill}
/>
<LabwareBorder
borderThickness={2.2 * OUTLINE_THICKNESS_MM}
xDimension={dimensions.xDimension}
yDimension={dimensions.yDimension}
stroke={COLORS.blue50}
fill={backgroundFill}
rx="4"
ry="4"
showRadius={showRadius}
/>
</>
) : (
<LabwareBorder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export interface StaticLabwareProps {
definition: LabwareDefinition2
/** Add thicker blurred blue border to labware, defaults to false */
highlight?: boolean
/** adds a drop shadow to the highlight border */
highlightShadow?: boolean
/** Optional callback to be executed when entire labware element is clicked */
onLabwareClick?: () => void
/** Optional callback to be executed when mouse enters a well element */
Expand Down Expand Up @@ -55,6 +57,7 @@ export function StaticLabwareComponent(props: StaticLabwareProps): JSX.Element {
const {
definition,
highlight,
highlightShadow,
onLabwareClick,
onMouseEnterWell,
onMouseLeaveWell,
Expand All @@ -69,6 +72,7 @@ export function StaticLabwareComponent(props: StaticLabwareProps): JSX.Element {
<LabwareOutline
definition={definition}
highlight={highlight}
highlightShadow={highlightShadow}
fill={fill}
showRadius={showRadius}
/>
Expand Down
5 changes: 5 additions & 0 deletions components/src/hardware-sim/ProtocolDeck/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ export function ProtocolDeck(props: ProtocolDeckProps): JSX.Element | null {
</LabwareInfo>
) : null,
highlightLabware: handleLabwareClick != null,
highlightShadowLabware:
handleLabwareClick != null &&
topLabwareDefinition != null &&
topLabwareId != null,
onLabwareClick:
handleLabwareClick != null &&
topLabwareDefinition != null &&
Expand Down Expand Up @@ -140,6 +144,7 @@ export function ProtocolDeck(props: ProtocolDeckProps): JSX.Element | null {
</LabwareInfo>
) : null,
highlight: handleLabwareClick != null,
highlightShadow: handleLabwareClick != null && isLabwareInStack,
onLabwareClick:
handleLabwareClick != null
? () => {
Expand Down

0 comments on commit eb857f4

Please sign in to comment.