FormidableLabs / spectacle

A React-based library for creating sleek presentations using JSX syntax that gives you the ability to live demo your code.
https://commerce.nearform.com/open-source/spectacle/
MIT License
9.74k stars 691 forks source link

Custom Slides Ignored; Stepper Ignores Steps #871

Open forrest-akin opened 4 years ago

forrest-akin commented 4 years ago

react : 6.13.1 spectacle : 6.0.1

I'm trying Spectacle for the first time and ran into this issue Various Issues w/ Imported Slides #678, which mentions it should be resolved by the Slide rewrite. I believe the rewrite has since been released, but the issue is not resolved so I'd like to reopen. Specifically, Slides are discarded if they are not inlined children of Deck. The suggested workaround to wrap Slide contents in React.Fragment allows the Slide to render, but causes nested Steppers to ignore their steps and immediately proceed to the next Slide.

Please see this CodeSandbox I've prepared demonstrating the issues I've mentioned.

ryan-roemer commented 4 years ago

@kale-stew This might be a related thing to #870 in that both Appear and Stepper are similarly written, and used here: https://github.com/FormidableLabs/spectacle/blob/88e635bae3a00eda9fd35bc77acb9d7ffe5a7b74/src/components/deck/index.js#L143-L144

forrest-akin commented 4 years ago

My workaround in the meantime is to map a list of slide metadata into Slide children of Deck

const Presentation =
    ( { theme , template , slides } ) => (
        <Deck theme={ theme } template={ template }>
            { slides.map(
                ( { heading , code , steps } ) => (
                    <Slide transitionEffect="slide">
                        <Heading> { heading } </Heading>
                        <Stepper defaultValue={ [] } values={ steps }>
                            { ( [ start , end , size ] ) => (
                                <CodePane highlightStart={ start } highlightEnd={ end } fontSize={ size }>
                                    { code }
                                </CodePane> ) }
                        </Stepper>
                    </Slide> ) ) }
        </Deck> )
kale-stew commented 4 years ago

Documenting my findings after digging into this a little deeper:

  1. If the slide is an imported Slide, we get an empty prototype obj. The Slide name is accessible, but its props are not.
  2. If the slide is an imported fragment, we get undefined. Fragment-wrapped Slides aren't making it into the Deck whatsoever.
  3. If the slide is inline, children come back as proper children for individual Spectacle elements (expected behavior). ✅

I'm thinking our problem is going to be buried a bit deeper in the DeckContext or elsewhere. Something about imported slides just doesn't mesh well with our methods of searching children.

m11m commented 4 years ago

Stepper also seems to not work when it is the only child in a slide like:

<Slide>
  <Stepper values={[1, 2, 3]}>{(value, step) => <div>{step}</div>}</Stepper>
</Slide>

It calls the function only once with value = undefined and step = -1.

It starts working when I put a sibling either before or after Stepper though. ¯_(ツ)_/¯

mikebarkmin commented 4 years ago

@m11m I can confirm this behavior.

matt-d-rat commented 4 years ago

Stepper also seems to not work when it is the only child in a slide like:

<Slide>
  <Stepper values={[1, 2, 3]}>{(value, step) => <div>{step}</div>}</Stepper>
</Slide>

It calls the function only once with value = undefined and step = -1.

It starts working when I put a sibling either before or after Stepper though. ¯(ツ)

I can also confirm this behaviour. It appears that if you put any element or even a React.Fragment as a sibling, the Stepper component is then somehow happy and works as expected. Weird.