@codecademy/gamut
72.5.172.5.2-alpha.319fdb.0
dist/Card/styles.js~
dist/Card/styles.jsModified+59−55
Index: package/dist/Card/styles.js
===================================================================
--- package/dist/Card/styles.js
+++ package/dist/Card/styles.js
@@ -1,8 +1,28 @@
import { theme, timingValues, variant } from '@codecademy/gamut-styles';
+import { useTheme } from '@emotion/react';
+
+/**
+ * The theme's elevation scale is flattened to dashcase tokens (`rest-shadow`,
+ * `hoverMirrored-transform`, ...), so per-state groups don't exist on the
+ * theme at runtime. This regroups one state's tokens into a spreadable style
+ * object, mapping the `shadow` token onto the `boxShadow` property
+ * framer-motion animates.
+ */
+const getElevationStyles = (elevation, state) => ({
+ boxShadow: elevation[`${state}-shadow`],
+ transform: elevation[`${state}-transform`]
+});
const SHADOW_OFFSET = 8;
const SHADOW_OFFSET_INITIAL = 6;
-const TRANSFORM_OFFSET = 4;
+const REST_TRANSITION = {
+ duration: timingValues.fast / 1000,
+ ease: 'easeOut'
+};
+const HOVER_TRANSITION = {
+ duration: timingValues.fast / 1000,
+ ease: 'easeIn'
+};
export const cardVariants = variant({
defaultVariant: 'default',
base: {
color: 'text'
@@ -55,59 +75,43 @@
ease: 'easeIn'
}
}
};
-export const hoverShadowLeft = borderRadius => ({
- initial: {
- boxShadow: `0px 0px 0 ${theme.colors['shadow-primary']}`,
- borderRadius,
- transition: {
- duration: timingValues.fast / 1000,
- ease: 'easeOut'
+
+/**
+ * Motion variants for a Card's hover elevation, read from the active theme's
+ * `elevation` scale so each theme controls its own shadow and lift.
+ * `patternRight` cards cast their shadow on the opposite side, so they use the
+ * `hoverMirrored` tokens.
+ */
+export const useCardElevation = (shadow, borderRadius) => {
+ const {
+ elevation
+ } = useTheme();
+ const hoverState = shadow === 'patternRight' ? 'hoverMirrored' : 'hover';
+ return {
+ initial: {
+ ...getElevationStyles(elevation, 'rest'),
+ borderRadius,
+ transition: REST_TRANSITION
+ },
+ // outline variants keep their bespoke two-layer shadow but share the
+ // elevation scale's transforms
+ initialOutline: {
+ ...getElevationStyles(elevation, 'rest'),
+ boxShadow: `-${SHADOW_OFFSET_INITIAL}px ${SHADOW_OFFSET_INITIAL}px 0 0px ${theme.colors['background-current']}, -${SHADOW_OFFSET_INITIAL}px ${SHADOW_OFFSET_INITIAL}px 0 1px ${theme.colors['border-primary']}`,
+ borderRadius,
+ transition: REST_TRANSITION
+ },
+ animate: {
+ ...getElevationStyles(elevation, hoverState),
+ borderRadius,
+ transition: HOVER_TRANSITION
+ },
+ animateOutline: {
+ ...getElevationStyles(elevation, 'hover'),
+ boxShadow: `-${SHADOW_OFFSET}px ${SHADOW_OFFSET}px 0 0px ${theme.colors['shadow-primary']}, -${SHADOW_OFFSET}px ${SHADOW_OFFSET}px 0 1px ${theme.colors['shadow-primary']}`,
+ borderRadius,
+ transition: HOVER_TRANSITION
}
- },
- initialOutline: {
- boxShadow: `-${SHADOW_OFFSET_INITIAL}px ${SHADOW_OFFSET_INITIAL}px 0 0px ${theme.colors['background-current']}, -${SHADOW_OFFSET_INITIAL}px ${SHADOW_OFFSET_INITIAL}px 0 1px ${theme.colors['border-primary']}`,
- borderRadius,
- transition: {
- duration: timingValues.fast / 1000,
- ease: 'easeOut'
- }
- },
- animate: {
- transform: `translate(${TRANSFORM_OFFSET}px, -${TRANSFORM_OFFSET}px)`,
- boxShadow: `-${SHADOW_OFFSET}px ${SHADOW_OFFSET}px 0 ${theme.colors['shadow-primary']}`,
- borderRadius,
- transition: {
- duration: timingValues.fast / 1000,
- ease: 'easeIn'
- }
- },
- animateOutline: {
- transform: `translate(${TRANSFORM_OFFSET}px, -${TRANSFORM_OFFSET}px)`,
- boxShadow: `-${SHADOW_OFFSET}px ${SHADOW_OFFSET}px 0 0px ${theme.colors['shadow-primary']}, -${SHADOW_OFFSET}px ${SHADOW_OFFSET}px 0 1px ${theme.colors['shadow-primary']}`,
- borderRadius,
- transition: {
- duration: timingValues.fast / 1000,
- ease: 'easeIn'
- }
- }
-});
-export const hoverShadowRight = borderRadius => ({
- initial: {
- boxShadow: `0px 0px 0 ${theme.colors['shadow-primary']}`,
- borderRadius,
- transition: {
- duration: timingValues.fast / 1000,
- ease: 'easeOut'
- }
- },
- animate: {
- transform: `translate(-${TRANSFORM_OFFSET}px, -${TRANSFORM_OFFSET}px)`,
- boxShadow: `${SHADOW_OFFSET}px ${SHADOW_OFFSET}px 0 ${theme.colors['shadow-primary']}`,
- borderRadius,
- transition: {
- duration: timingValues.fast / 1000,
- ease: 'easeIn'
- }
- }
-});
\ No newline at end of file
+ };
+};
\ No newline at end of file