-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enhance transition components #996
Conversation
Codecov Report
@@ Coverage Diff @@
## main #996 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 53 53
Lines 700 702 +2
Branches 238 240 +2
=========================================
+ Hits 700 702 +2
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
f80216d
to
26942cb
Compare
@@ -31,6 +31,6 @@ export type IconComponent = FunctionComponent<JSX.SVGAttributes<SVGSVGElement>>; | |||
* animate the mounting and unmounting of a child component. | |||
*/ | |||
export type TransitionComponent = FunctionComponent<{ | |||
visible: boolean; | |||
direction?: 'in' | 'out'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this mean that all TransitionComponent
s have to support both an in
and an out
transition? Is this an OK assumption to make?
@@ -194,7 +194,7 @@ export default function UsingComponentsPage() { | |||
<Library.Code | |||
size="sm" | |||
content={`type TransitionComponentProps = { | |||
visible: boolean; | |||
direction?: 'in' | 'out'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we document that default is in
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -196,7 +196,7 @@ const Dialog = function Dialog({ | |||
|
|||
return ( | |||
<Wrapper | |||
visible={transitionComponentVisible} | |||
direction={transitionComponentVisible ? 'in' : 'out'} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm curious: this Wrapper
may be a reference to a TransitionComponent
functional component or it might be a Fragment
. Do Fragment
s happily take any props without grumbling? Presumably typechecking would bark if not...I just haven't thought about it before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I thought the same at first, but not only it does not complain when type-checking, but the IDE properly autocompletes valid props, and complains if you set something not valid for TransitionComponent
.
So I guess the type of Fragment
is defined in a way that it accepts anything, knowing it will be actually "lost".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool. Let's get the tests and plop templates sorted out now!
> = ({ children, visible, onTransitionEnd, _transitionStatus }) => { | ||
const [isVisible, setIsVisible] = useState(visible); | ||
const toggleSlider = () => setIsVisible(prev => !prev); | ||
> = ({ children, direction, onTransitionEnd, _transitionStatus }) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This typing is a little hard to read (the multi-line wrapping). Is it possible to construct the type elsewhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, this is now redundant, and _transitionStatus
can be completely discarded in favor of direction
. It was needed when visible
was used, but not anymore.
This can be simplified as const Slider_: TransitionComponent = ...
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok no, my mistake. Doing that has other side effects.
I will extract the type in multiple definitions for better readability.
<Library.Example title="direction"> | ||
This prop tells if the Slider is currently expanded (<code>in</code> | ||
) or collapsed (<code>out</code>). It is <code>in</code> by default. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A task for me, especially now that we have reliable routing and fragment navigation, is to create a better centralized documentation for common component props. That is, this documentation probably shouldn't be necessary specifically for Slider
, instead, we should be able to reuse or link to generalized documentation for this prop.
While creating the
plop
files forTransitionComponent
s, we realized there was a design mistake on their properties. Thevisible
one should be optional, and default totrue
.However, this presented another problem, based on how we have decided to use boolean optional props. We want them to have a default value which allows to set them with no value in order to overwrite it.
If
visible
defaults totrue
, we would not be able to follow that rule, because it would have to be set as<Component visible={false} />
in order to overwrite it.Because of this, we considered replacing the prop with something else. The first logical option was
hidden
, which could default tofalse
and be overwritten with just<Component hidden />
, but while implementing it, it didn't feel right, and most of the logic started withconst visible = !hidden
, to be able to continue dealing withvisible
as a concept.After some discussions, we have moved away from a flag, and I have finally introduced an optional
direction
prop, which can have valuesin
andout
, with a default value ofin
.The benefits of this approach are:
onTransitionEnd
, making it easier to handle internally, and to reason about.hidden
).It has one main consideration, though:
Technically speaking, it is a breaking change.
In
client
, where we are usingDialog
and providing a local component astransitionComponent
, that local component will no longer fulfill the proper API.However, there's already a draft PR which replaces that component by the equivalent one on this library, which has been adapted as part of this PR, so the migration should be easy.