Skip to content
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

Make all container components take containerRef; consolidate tests #172

Merged
merged 1 commit into from
Aug 13, 2021

Conversation

lyzadanger
Copy link
Contributor

Per some verbal discussion today, there is a props API naturally shaping up with some of the container components. There's an immediate need for a ref on the Scrollbox container (for Table), so I went ahead and added the containerRef prop to all container components. Tests are consolidated here, as well, to DRY out common container tests.

@codecov
Copy link

codecov bot commented Aug 11, 2021

Codecov Report

Merging #172 (65c9079) into main (42b72f6) will not change coverage.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff            @@
##              main      #172   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           12        13    +1     
  Lines          152       158    +6     
  Branches        53        55    +2     
=========================================
+ Hits           152       158    +6     
Impacted Files Coverage Δ
src/components/containers.js 100.00% <100.00%> (ø)
src/util/typing.js 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 42b72f6...65c9079. Read the comment docs.

Copy link
Member

@robertknight robertknight left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left some comments after an initial look through. The main feedback I had was a suggestion regarding the refElement helper name and a query about the use cases we have for the containerRef prop.

*/
export function refElement(arg) {
return /** @type {import('preact').Ref<any>} */ (arg);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This explanation is clear although I think the term "downcast" probably best describes what we're doing with the input. I took a shot at creating a generic version of this that has the proper types:

/**
 * @template T
 * @typedef {import('preact').Ref<T>} Ref
 */

/**
 * Helper for downcasting a ref to a more specific type, where that is safe
 * to do.
 *
 * This is mainly useful to cast a generic `Ref<HTMLElement>` to a more specific
 * element type (eg. `Ref<HTMLDivElement>`) for use with the `ref` prop of a JSX element.
 * Since Preact only writes to the `ref` prop, such a cast is safe.
 *
 * @template T
 * @template {T} U
 * @param {Ref<T>|undefined} ref
 * @return {Ref<U>|undefined}
 */
export function downcastRef(ref) {
  return /** @type {Ref<U>|undefined} */ (ref);
}

The above works in place of the current refElement calls, if you adjust the name. The type variables T and U could also be given more descriptive names like Base and Derived.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This explanation is clear although I think the term "downcast" probably best describes what we're doing with the input.

Heh, this is why I specifically asked for vocabulary when we chatted about this. I'll use your suggestions here.

/**
* @typedef {import('preact').ComponentChildren} Children
*
* @typedef ContainerProps
* @prop {Children} children
* @prop {string} [classes] - Additional CSS classes to apply
* @prop {import('preact').Ref<HTMLElement>} [containerRef] - Access to the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are the use cases you have in mind for containerRef?

Copy link
Contributor Author

@lyzadanger lyzadanger Aug 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Immediate use case: https://github.com/hypothesis/frontend-shared/pull/174/files#diff-39adc517b1457f125e1e729d1039b7ce6a3a4c39317a18af693ff418d5cf6073R153

In general, because these are centralized, common components, I want to give authors as much flexibility as possible when using them, and to have a predictable API across them.

>
{children}
</div>
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An observation - this Actions class is now almost a completely generic version of the <div> in the other components.

@lyzadanger
Copy link
Contributor Author

@robertknight Have at! I've integrated your version.

Copy link
Member

@robertknight robertknight left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

const containerRef = createRef();
createComponent(Component, { containerRef });

assert.isTrue(containerRef.current instanceof Node);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert.instanceOf(object, constructor) will give a better error if this check fails.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, that is a nice assertion to use, thanks.

@lyzadanger lyzadanger merged commit 08a09bb into main Aug 13, 2021
@lyzadanger lyzadanger deleted the container-refs branch August 13, 2021 15:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants