diff --git a/README.md b/README.md index 41121aa..9500b67 100644 --- a/README.md +++ b/README.md @@ -131,6 +131,7 @@ export default Example; - `useDevicePixelRatio`: _(optional)_ If `true`, the hook will scale the resolution of the animation based the [devicePixelRatio](https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio). Defaults to `true`. NOTE: Requires the `setContainerRef` ref callback to be passed to a element wrapping a canvas element. If you use the `RiveComponent`, then this will happen automatically. - `fitCanvasToArtboardHeight`: _(optional)_ If `true`, then the canvas will resize based on the height of the artboard. Defaults to `false`. - `useOffscreenRenderer`: _(optional)_ If `true`, the Rive instance will share (or create if one does not exist) an offscreen `WebGL` context. This allows you to display multiple Rive animations on one screen to work around some browser limitations regarding multiple concurrent WebGL contexts. If `false`, each Rive instance will have its own dedicated `WebGL` context, and you may need to be cautious of the browser limitations just mentioned. Defaults to `true`. +- `canvasProps`: _(optional)_ An object of props to pass to the underlying `` element created in the `RiveComponent` returned from this hook. You can also set `canvasProps` directly on the returned `RiveComponent` as well if you prefer. Currently by default, spreading any HTML props on the `RiveComponent` goes to the ``'s container `
` element, however, in a next major version, this may be restructured such that by default, spread props go onto the `canvas` element itself. ### useStateMachineInput Hook diff --git a/src/components/Rive.tsx b/src/components/Rive.tsx index bf0065b..6975265 100644 --- a/src/components/Rive.tsx +++ b/src/components/Rive.tsx @@ -6,28 +6,34 @@ export type RiveProps = { src: string; artboard?: string; animations?: string | string[]; + stateMachines?: string | string[]; layout?: Layout; useOffscreenRenderer?: boolean; + canvasProps?: ComponentProps<'canvas'>; }; const Rive = ({ src, artboard, animations, + stateMachines, layout, useOffscreenRenderer = true, + canvasProps = {}, ...rest }: RiveProps & ComponentProps<'div'>) => { const params = { src, artboard, animations, + stateMachines, layout, autoplay: true, }; const options = { useOffscreenRenderer, + canvasProps, }; const { RiveComponent } = useRive(params, options); diff --git a/src/hooks/useRive.tsx b/src/hooks/useRive.tsx index 2e94f7d..5b88440 100644 --- a/src/hooks/useRive.tsx +++ b/src/hooks/useRive.tsx @@ -18,11 +18,13 @@ import { useWindowSize } from '../utils'; type RiveComponentProps = { setContainerRef: RefCallback; setCanvasRef: RefCallback; + canvasProps?: ComponentProps<'canvas'>, }; function RiveComponent({ setContainerRef, setCanvasRef, + canvasProps = {}, ...rest }: RiveComponentProps & ComponentProps<'div'>) { const containerStyle = { @@ -36,7 +38,7 @@ function RiveComponent({ style={'className' in rest ? undefined : containerStyle} {...rest} > - +
); } @@ -45,6 +47,7 @@ const defaultOptions = { useDevicePixelRatio: true, fitCanvasToArtboardHeight: false, useOffscreenRenderer: true, + canvasProps: {}, }; /** @@ -240,6 +243,7 @@ export default function useRive( ); diff --git a/src/types.ts b/src/types.ts index 931e0af..b460e18 100644 --- a/src/types.ts +++ b/src/types.ts @@ -7,6 +7,7 @@ export type UseRiveOptions = { useDevicePixelRatio: boolean; fitCanvasToArtboardHeight: boolean; useOffscreenRenderer: boolean; + canvasProps: ComponentProps<'canvas'>; }; export type Dimensions = { diff --git a/test/useRive.test.tsx b/test/useRive.test.tsx index 4526c98..96cd52a 100644 --- a/test/useRive.test.tsx +++ b/test/useRive.test.tsx @@ -1,4 +1,6 @@ +import React from 'react'; import { mocked } from 'jest-mock'; +import {render} from '@testing-library/react'; import { renderHook, act } from '@testing-library/react-hooks'; import useRive from '../src/hooks/useRive'; @@ -308,4 +310,24 @@ describe('useRive', () => { expect(stopMock).toBeCalledWith(['light']); expect(playMock).toBeCalledWith('dark'); }); + + it('passes canvasProps down to the canvas element', () => { + const params = { + src: 'file-src', + animations: 'light', + }; + + const options = { + canvasProps: { + 'data-testid': 'foo', + 'aria-label': 'test label', + }, + }; + + const { result } = renderHook(() => useRive(params, options)); + + const ResultComponent = result.current.RiveComponent; + const {getByTestId} = render(); + expect(getByTestId('foo')).toHaveAttribute('aria-label', 'test label'); + }); });