export const showcaseListStyles = style({display: 'flex',flexFlow: 'row nowrap',gap: theme.grid.xxl,});
Source: CSS
List Styles
Nothing fancy, rendering a list of things
Showcase Image
Styles for the image itself
export const showcaseImageStyles = style({blockSize: '100cqh',inlineSize: '100cqw',objectFit: 'cover',objectPosition: 'center center',});
Constants
Through these variables we will be controlling the showcase items themselves,The position variables are required for functioning, the rest are for you to play around with.
// Control the size of the itemsexport const imageSize = createVar();// Expose cursor position from JSexport const xPosition = createVar();export const yPosition = createVar();// Control the effects intensityexport const shadowIntensity = createVar();export const transformIntensity = createVar();export const perspective = createVar();
Variables
We'll be using these to break down the calculations for explanations
// Primitives for the calculationsconst xOffset = createVar();const yOffset = createVar();// Transform calculationsconst transformX = createVar();const transformY = createVar();const transform = createVar();// Box Shadow Calculationsconst shadowXOffset = createVar();const shadowYOffset = createVar();const shadowXSlope = createVar();const shadowYSlope = createVar();const shadowSlope = createVar();const shadowSpread = createVar();const shadowColorOpacity = createVar();const shadowColor = createVar();const shadowBlur = createVar();const shadow = createVar();
Showcase Effects
We'll have two wrappers to create the effect we want.,One of them will handle scaling while the other will handle transforms and box shadows,The calculations will be present down below
export const showcaseWrapperStyles = recipe({// Common Stylesbase: {display: 'flex',flexFlow: 'column nowrap',alignItems: 'center',justifyContent: 'center',cursor: 'pointer',},// Base styles for each variant of wrapper (well, for the outer wrapper)variants: {which: {outer: {transition: 'transform 0.2s ease-out',containerType: 'size',inlineSize: `calc(${imageSize} * 1px)`,aspectRatio: '11/15',},inner: {},},active: {true: {},},},compoundVariants: [// Outer wrapper will pop out when active{variants: {which: 'outer',active: true,},style: {transform: 'scale(1.2)',position: 'relative',},},// Inner wrapper will transform and render a box shadow when active{variants: {which: 'inner',active: true,},style: {transform,boxShadow: shadow,background: shadowColor,},},],});
Calculations
globalStyle(showcaseWrapperStyles.classNames.variants.which.outer, {vars: {// Calculate offset ([-1, 1]) for each axis// with respects to the center of the item[xOffset]: `calc(${xPosition} - 0.5)`,[yOffset]: `calc(${yPosition} - 0.5)`,// Slightly rotate the item based on our offsets// and factor in perspective// We want to tilt the item in the opposite direction// as that of our cursos with respects to the center of the item[transformY]: `calc(${xOffset} * ${transformIntensity} * 1deg)`,[transformX]: `calc(${yOffset} * ${transformIntensity} * -1deg)`,[transform]: [`perspective(calc(${perspective} * 1px))`,`rotateY(${transformY})`,`rotateX(${transformX})`,].join(' '),// Calculate X and Y offsets for the shadow based on our offsets// and the size of the item[shadowXOffset]: `calc(${xOffset} * 100cqw * -1 * ${shadowIntensity})`,[shadowYOffset]: `calc(${yOffset} * 100cqh * -1 * ${shadowIntensity})`,// Calculate the slope of the transform// (the most we're tilting the item on each axis)[shadowXSlope]: `abs(${xOffset})`,[shadowYSlope]: `abs(${yOffset})`,[shadowSlope]: `max(max(${shadowXSlope}, ${shadowYSlope}), 0)`,// Calculate the blur based on the slope[shadowBlur]: `calc(max(${shadowSlope}, 0.4) * 50px)`,// Calculate the spread based on the slope[shadowSpread]: `calc(max(${shadowSlope}, 0.1) * 20px)`,// Calculate the color based on the slope[shadowColorOpacity]: `calc(max(0, min(1 - ${shadowSlope})) - 0.3)`,[shadowColor]: `hsla(from black h s l / ${shadowColorOpacity})`,// Combine our calculations into a box-shadow specification[shadow]: [shadowXOffset,shadowYOffset,shadowBlur,shadowSpread,shadowColor,].join(' '),},});export type ShowcaseWrapperStylesProps = RecipeVariants<typeof showcaseWrapperStyles>;