Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/heavy-impalas-stare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'spectacle': patch
---

prevent theme.backdropStyle styles for background from being overridden
7 changes: 7 additions & 0 deletions docs/themes.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ Common CSS properties are divided into theme keys, which you can override in you
| `shadows` | `box-shadow`, `text-shadow` |
| `zIndices` | `z-index` |

Additionally, there are keys for assorted overrides for the presentation:

| Theme Key | Type | Description |
| ---------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `backdropStyle` | `React.CSSProperties` | Set styles for the backdrop (the edge-to-edge area behind the slides) similar to React `style` props, e.g., `{ backgroundColor: '#FFF' }`. Defaults to `{ position: 'fixed', top: 0, left: 0, width: '100vw', height: '100vh' }` |
| `Backdrop` | `React.ElementType` | Replace the default backdrop component (which appears behind the slides) with a completely custom component or tag name, e.g., `'main'` or `MyCustomComponent`. Defaults to `'div'`. |

## Deck Templates

A template in Spectacle is a fixed overlay of components that are presented on every slide. They are similar to masters in Keynote or PowerPoint. It’s a function prop that has a single optional config object containing the current slide and total slide count and returns a React Node.
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@
"start:js": "concurrently --raw pnpm:build:spectacle:esm:watch pnpm:build:spectacle:types:watch \"pnpm run --filter ./examples/js start\"",
"start:md": "concurrently --raw pnpm:build:spectacle:esm:watch pnpm:build:spectacle:types:watch \"pnpm run --filter ./examples/md start\"",
"start:ts": "concurrently --raw pnpm:build:spectacle:esm:watch pnpm:build:spectacle:types:watch \"pnpm run --filter ./examples/typescript start\"",
"start:one-page": "concurrently --raw pnpm:build:spectacle:dev:watch pnpm:build:spectacle:dev:watch",
"start:examples": "concurrently --raw pnpm:build:spectacle:esm:watch pnpm:build:spectacle:dev:watch pnpm:build:spectacle:dev:watch \"pnpm run --parallel --filter \\\"./examples/*\\\" start\"",
"start:one-page": "concurrently --raw pnpm:build:spectacle:dev:watch pnpm:build:spectacle:types:watch",
"start:examples": "concurrently --raw pnpm:build:spectacle:esm:watch pnpm:build:spectacle:dev:watch pnpm:build:spectacle:types:watch \"pnpm run --parallel --filter \\\"./examples/*\\\" start\"",
"start:create-spectacle": "pnpm run --filter ./packages/create-spectacle build --watch",
"clean:build": "rimraf \"{packages,examples}/*/{es,lib,dist}\" packages/create-spectacle/bin",
"clean:cache": "wireit",
Expand Down
37 changes: 37 additions & 0 deletions packages/spectacle/src/components/deck/deck.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import Deck from './index';
import Slide from '../slide/slide';
import { render } from '@testing-library/react';
import { CSSObject } from 'styled-components';

describe('<Deck />', () => {
it('should allow for backdrop color overrides from theme prop', () => {
const deckWithStyle = (
backdropStyle: CSSObject,
Backdrop?: React.ElementType
) => (
<Deck className="backdrop" theme={{ backdropStyle, Backdrop }}>
<Slide>Hi</Slide>
</Deck>
);
let { container, rerender } = render(deckWithStyle({ padding: 16 }));

expect(container.querySelector('.backdrop')).toHaveStyle({
backgroundColor: 'black'
});

rerender(deckWithStyle({ backgroundColor: 'blue' }));
expect(container.querySelector('.backdrop')).toHaveStyle({
backgroundColor: 'blue'
});

rerender(deckWithStyle({ background: 'red' }));
expect(container.querySelector('.backdrop')).toHaveStyle({
backgroundColor: 'red'
});

rerender(deckWithStyle({}, 'section'));
expect(container.querySelector('.backdrop')).not.toHaveStyle({
backgroundColor: 'black'
});
});
});
34 changes: 20 additions & 14 deletions packages/spectacle/src/components/deck/deck.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -400,21 +400,16 @@ export const DeckInternal = forwardRef<DeckRef, DeckInternalProps>(
//
// Yes, this is slightly awkward, but IMO adding an additional `<div>` element
// would be even more awkward.
let useFallbackBackdropStyle = true;
const backdropStyle = themeProvidedBackdropStyle;
let BackdropComponent = 'div' as ElementType;
if (userProvidedBackdropStyle) {
Object.assign(backdropStyle, userProvidedBackdropStyle);
if (backdropStyle['background'] || backdropStyle['backgroundColor']) {
useFallbackBackdropStyle = false;
}
}
if (UserProvidedBackdropComponent) {
BackdropComponent = UserProvidedBackdropComponent;
useFallbackBackdropStyle = false;
}
const backdropStyle = {
...themeProvidedBackdropStyle,
...userProvidedBackdropStyle
};
const BackdropComponent = UserProvidedBackdropComponent || 'div';

if (
useFallbackBackdropStyle &&
!backdropStyle['background'] &&
!backdropStyle['backgroundColor'] &&
!UserProvidedBackdropComponent &&
!suppressBackdropFallback &&
!themeSuppressBackdropFallback
) {
Expand Down Expand Up @@ -535,6 +530,11 @@ type MarkdownThemeOverrides = {
type BackdropOverrides = {
Backdrop?: ElementType;
backdropStyle?: CSSObject;
/**
* @deprecated set a value to one of the `Backdrop`,
* `backdropStyle.background`, or `backdropStyle.backgroundColor` properties
* inside the `theme` prop object instead
*/
suppressBackdropFallback?: boolean;
};

Expand All @@ -556,6 +556,11 @@ export type DeckProps = {
printScale?: number;
overviewScale?: number;
transition?: SlideTransition;
/**
* @deprecated set a value to one of the `Backdrop`,
* `backdropStyle.background`, or `backdropStyle.backgroundColor` properties
* inside the `theme` prop object instead
*/
suppressBackdropFallback?: boolean;
backgroundImage?: string;
};
Expand All @@ -573,6 +578,7 @@ export type DeckInternalProps = DeckProps & {
disableInteractivity?: boolean;
useAnimations?: boolean;
notePortalNode?: HTMLDivElement | null;
/** @deprecated use the backdropStyle property inside the `theme` prop object instead */
backdropStyle?: Partial<CSSStyleDeclaration>;
onActiveStateChange?: (activeView: DeckView) => void;
backgroundImage?: string;
Expand Down
9 changes: 0 additions & 9 deletions packages/spectacle/src/components/markdown/markdown.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,6 @@ import { Heading } from '../typography';
import Slide from '../slide/slide';
import { render } from '@testing-library/react';

jest.mock('../../hooks/use-broadcast-channel', () => {
return {
__esModule: true,
default: function useBroadcastChannel() {
return [() => {}];
}
};
});

const mountInsideDeck = (tree: ReactElement) => {
return render(<Deck>{tree}</Deck>);
};
Expand Down
9 changes: 0 additions & 9 deletions packages/spectacle/src/components/slide-layout.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,6 @@ import Deck from './deck';
import SlideLayout from './slide-layout';
import { Heading, Text } from './typography';

jest.mock('../hooks/use-broadcast-channel', () => {
return {
__esModule: true,
default: function useBroadcastChannel() {
return [() => {}];
}
};
});

const renderInDeck = (tree: ReactElement | JSX.Element) =>
render(<Deck>{tree}</Deck>);

Expand Down
13 changes: 13 additions & 0 deletions packages/spectacle/src/test-utils/test-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,16 @@ window.HTMLElement.prototype.getClientRects = (): any => [
jest.mock('use-resize-observer', () => {
return jest.requireActual('use-resize-observer/polyfilled');
});

jest.mock('broadcast-channel', () => {
const bcExport = jest.requireActual('broadcast-channel');
const ActualBroadcastChannel = bcExport.BroadcastChannel;

// Wrap the BroadcastChannel constructor so it always uses the `simulate`
// mode. This prevents tests from hanging after mounting a Deck.
bcExport.BroadcastChannel = function (name: string) {
return new ActualBroadcastChannel(name, { type: 'simulate' });
};

return bcExport;
});