@shopify/polaris-viz-core
v15.3.2
Published
Core logic for Polaris Viz that is not platform specific
Downloads
268,276
Keywords
Readme
🧠 polaris-viz-core
packages/polaris-viz-core
contains platform agnostic utility functions, hooks, constants, types and UI components.
It gets published as the @shopify/polaris-viz-core
library that is used by both @shopify/polaris-viz
and @shopify/polaris-viz-native
👯♀️ Sharing code between React and React Native
Keeping the bundle size small
To keep the bundle size of the libraries small, @shopify/polaris-viz-core
shouldn't depend on platform specific packages, like @react-native
or @react-spring/web
, directly.
Sharing UI components
To render SVG tags in React Native, we use the react-native-svg
library. @shopify/polaris-viz
doesn't need this package as a dependency though, since its targets are web browsers only. If we added react-native-svg
as a depency of @shopify/polaris-viz-core
we would also increase @shopify/polaris-viz
bundle size for something that only @shopify/polaris-viz-native
needs.
To solve this, we:
- Store all regular SVG tags as React components in the
polaris-viz-context
used byPolarisVizProvider
:
// packages/polaris-viz-core/polaris-viz-context.ts
export const PolarisVizContext = createContext({
components: {
Svg: ({children, ...props}) => createElement('svg', props, children),
Circle: ({children, ...props}) => createElement('circle', props, children),
Ellipse: ({children, ...props}) => createElement('ellipse', props, children),
G: ({children, ...props}) => createElement('g', props, children),
Text: ({children, ...props}) => createElement('text', props, children),
// ... other SVG tags
},
});
- Re-export
PolarisVizProvider
frompolaris-viz-native
overwriting the regular SVG tags, with the equivalent tags fromreact-native-svg
// packages/polaris-viz-native/PolarisVizProvider.tsx
import {PolarisVizProvider as OriginalPolarisVizProvider} from '@shopify/polaris-viz-core';
import {
Svg,
Circle,
// ...
} from 'react-native-svg';
export const NativeComponents = {
Svg,
Circle,
// ...
}
export const PolarisVizProvider = ({themes, children}) => {
return (
<OriginalPolarisVizProvider
themes={themes}
components={NativeComponents}
animated={animated}
>
{children}
</OriginalPolarisVizProvider>
);
};
- When building UI components in
polaris-viz-core
, instead of using<svg>
directly, we get<Svg>
from the context:
// packages/polaris-viz-core/SomeSharedComponent.tsx
export function SomeSharedComponent() {
const {
components: {Svg, Rect},
} = usePolarisVizContext();
return (
<Svg>
<Rect />
</Svg>
)
}
With these changes in place,
- in
polaris-viz
:<Svg>
and<Rect>
will fetch thesvg
andrect
tags from the default values ofpolaris-viz-context
and render correctly in web browsers - in
polaris-viz-native
:<Svg>
and<Rect>
will fetch theSvg
andRect
tags from thereact-native-svg
library that were used to overwrite the default tags in thePolarisVizProvider
, thus rendering correctly in React Native
To summarize:
We use react-spring to handle animations. This library also has platform specific exports to keep bundle size small: @react-spring/web
and @react-spring/native
To animate components in core, we fetch the platform specific animated
function from the PolarisVizContext
, similarly to how we get the correct SVG tags.
// packages/polaris-viz-core/SomeSharedComponent.tsx
import { useSpring } from "@react-spring/core"
export function SomeSharedComponent() {
const {
components: {Svg, Circle},
animated,
} = usePolarisVizContext();
const {animatedRadius} = useSpring({
from: {
animatedRadius: 0,
},
to: {
animatedRadius: 100,
},
});
const AnimatedCircle = animated(Circle);
return (
<Svg>
<AnimatedCircle radius={animatedRadius} />
</Svg>
)
}