Skip to content

refactor(media-query): migrate MediaQuery from Flow to TypeScript - #4735

Merged
mergify[bot] merged 1 commit into
box:masterfrom
bonchevskyi:refactor/flow-to-ts-media-query
Aug 6, 2026
Merged

refactor(media-query): migrate MediaQuery from Flow to TypeScript#4735
mergify[bot] merged 1 commit into
box:masterfrom
bonchevskyi:refactor/flow-to-ts-media-query

Conversation

@bonchevskyi

@bonchevskyi bonchevskyi commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Convert MediaQuery utilities to TypeScript

This PR converts src/components/media-query from JavaScript with Flow to TypeScript.

Changes

  • Converted media-query hooks, HOC, constants, and types to TypeScript
  • Converted object type definitions to exported interfaces
  • Converted stories and tests to TypeScript
  • Created .js.flow files for backward compatibility
  • Re-exported public utilities and types from index.ts
  • Added media-query exports to src/components/index.ts

Testing

  • Ran tests for src/components/media-query; all 3 pass
  • yarn lint:ts, ESLint, and Flow checks pass
  • Storybook production build completed successfully

Summary by CodeRabbit

  • New Features

    • Added media-query utilities for detecting viewport size, touch capability, pointer precision, hover support, and window dimensions.
    • Added a hook for accessing responsive media information.
    • Added a higher-order component that supplies media-query data to wrapped components.
    • Exposed media-query utilities and related types through the components API.
    • Media queries can be configured using query strings or feature settings.
  • Tests

    • Updated media-query tests and stories with stronger TypeScript typing.

@bonchevskyi
bonchevskyi requested a review from a team as a code owner July 31, 2026 15:03
@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

The PR adds typed media-query constants, types, a useMediaQuery hook, a withMediaQuery HOC, public exports, and TypeScript updates for tests and stories.

Changes

Media query support

Layer / File(s) Summary
Media query contracts and constants
src/components/media-query/constants.*, src/components/media-query/types.*
Adds responsive size, hover, and pointer constants. Defines media-query feature types and the normalized MediaShape result.
Media query hook and HOC
src/components/media-query/useMediaQuery.*, src/components/media-query/withMediaQuery.*
Adds media-query evaluation, device capability detection, viewport classification, normalized hook output, and media-property injection through the HOC.
Public exports and typed usage
src/components/index.ts, src/components/media-query/index.*, src/components/media-query/__tests__/*, src/components/media-query/stories/*
Exports the media-query module and updates tests and stories to use TypeScript types and component references.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant useMediaQuery
  participant react-responsive
  participant Window
  participant withMediaQuery
  participant WrappedComponent
  useMediaQuery->>react-responsive: Evaluate formatted media queries
  react-responsive->>Window: Read viewport dimensions
  Window-->>react-responsive: Return width and height
  react-responsive-->>useMediaQuery: Return query matches
  useMediaQuery-->>withMediaQuery: Return MediaShape
  withMediaQuery-->>WrappedComponent: Pass media properties
Loading

Possibly related PRs

  • box/box-ui-elements#4743: Both PRs migrate a component module from Flow to TypeScript and add typed entry-point exports.

Suggested reviewers: tjiang-box, vitali-usik

Poem

A rabbit types queries with care,
And maps every screen size and pair.
The hook finds the view,
The HOC passes it through,
While exports and tests align there.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the migration of MediaQuery from Flow to TypeScript.
Description check ✅ Passed The description summarizes the migration, lists the main changes, and documents testing results.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/media-query/types.js.flow`:
- Around line 3-6: Update the MediaPointerType and MediaHoverType aliases to use
valid Flow syntax: define them as string-literal unions matching the
POINTER_TYPE and HOVER_TYPE values, or use typeof property queries for those
constants. Keep the existing exported names and supported values unchanged.

In `@src/components/media-query/types.ts`:
- Around line 6-19: Remove the string index signatures from the MediaFeatures
and MediaShape interfaces so their contracts reject arbitrary keys. Preserve the
explicitly declared media feature properties and their existing types, ensuring
invalid feature objects cannot pass through toQuery.

In `@src/components/media-query/useMediaQuery.ts`:
- Around line 24-26: Move the window access out of the render path by
establishing a separate subscription effect that listens for window resize
events instead of calling getViewDimensions during render. Wrap the window
access in an SSR-safe guard that provides fallback dimensions when window is
unavailable, and set up an event listener on the resize event to update viewport
dimensions whenever the window size changes rather than only when media query
conditions are evaluated.

In `@src/components/media-query/withMediaQuery.tsx`:
- Around line 5-12: Update the withMediaQuery function in
src/components/media-query/withMediaQuery.tsx lines 5-12 to preserve the wrapped
component's original prop contract by changing the return type from
React.ComponentType<Record<string, unknown>> to a generic that reflects
Omit<Props, keyof MediaShape>, and filter the injected media props from the
original props before spreading them into WrappedComponent using an explicit set
of known media property keys instead of relying on MediaShape's index signature.
Apply the equivalent changes to
src/components/media-query/withMediaQuery.js.flow lines 7-23 to maintain the
Flow type contract in parallel. Add a type test that includes a required
non-media prop on the wrapped component to verify callers must provide it after
wrapping.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b36e9b1e-5c57-42a6-ad40-927b21fbc7ee

📥 Commits

Reviewing files that changed from the base of the PR and between 336205d and 87a16fb.

📒 Files selected for processing (14)
  • src/components/index.ts
  • src/components/media-query/__tests__/useMediaQuery.test.tsx
  • src/components/media-query/__tests__/withMediaQuery.test.tsx
  • src/components/media-query/constants.js.flow
  • src/components/media-query/constants.ts
  • src/components/media-query/index.js.flow
  • src/components/media-query/index.ts
  • src/components/media-query/stories/MediaQuery.stories.tsx
  • src/components/media-query/types.js.flow
  • src/components/media-query/types.ts
  • src/components/media-query/useMediaQuery.js.flow
  • src/components/media-query/useMediaQuery.ts
  • src/components/media-query/withMediaQuery.js.flow
  • src/components/media-query/withMediaQuery.tsx

Comment thread src/components/media-query/types.ts Outdated
Comment thread src/components/media-query/useMediaQuery.ts
Comment thread src/components/media-query/withMediaQuery.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/media-query/types.js.flow`:
- Around line 3-6: Update the MediaPointerType and MediaHoverType aliases to use
valid Flow syntax: define them as string-literal unions matching the
POINTER_TYPE and HOVER_TYPE values, or use typeof property queries for those
constants. Keep the existing exported names and supported values unchanged.

In `@src/components/media-query/types.ts`:
- Around line 6-19: Remove the string index signatures from the MediaFeatures
and MediaShape interfaces so their contracts reject arbitrary keys. Preserve the
explicitly declared media feature properties and their existing types, ensuring
invalid feature objects cannot pass through toQuery.

In `@src/components/media-query/useMediaQuery.ts`:
- Around line 24-26: Move the window access out of the render path by
establishing a separate subscription effect that listens for window resize
events instead of calling getViewDimensions during render. Wrap the window
access in an SSR-safe guard that provides fallback dimensions when window is
unavailable, and set up an event listener on the resize event to update viewport
dimensions whenever the window size changes rather than only when media query
conditions are evaluated.

In `@src/components/media-query/withMediaQuery.tsx`:
- Around line 5-12: Update the withMediaQuery function in
src/components/media-query/withMediaQuery.tsx lines 5-12 to preserve the wrapped
component's original prop contract by changing the return type from
React.ComponentType<Record<string, unknown>> to a generic that reflects
Omit<Props, keyof MediaShape>, and filter the injected media props from the
original props before spreading them into WrappedComponent using an explicit set
of known media property keys instead of relying on MediaShape's index signature.
Apply the equivalent changes to
src/components/media-query/withMediaQuery.js.flow lines 7-23 to maintain the
Flow type contract in parallel. Add a type test that includes a required
non-media prop on the wrapped component to verify callers must provide it after
wrapping.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b36e9b1e-5c57-42a6-ad40-927b21fbc7ee

📥 Commits

Reviewing files that changed from the base of the PR and between 336205d and 87a16fb.

📒 Files selected for processing (14)
  • src/components/index.ts
  • src/components/media-query/__tests__/useMediaQuery.test.tsx
  • src/components/media-query/__tests__/withMediaQuery.test.tsx
  • src/components/media-query/constants.js.flow
  • src/components/media-query/constants.ts
  • src/components/media-query/index.js.flow
  • src/components/media-query/index.ts
  • src/components/media-query/stories/MediaQuery.stories.tsx
  • src/components/media-query/types.js.flow
  • src/components/media-query/types.ts
  • src/components/media-query/useMediaQuery.js.flow
  • src/components/media-query/useMediaQuery.ts
  • src/components/media-query/withMediaQuery.js.flow
  • src/components/media-query/withMediaQuery.tsx
🛑 Comments failed to post (1)
src/components/media-query/types.js.flow (1)

3-6: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 2 \
  'MediaPointerType|MediaHoverType|POINTER_TYPE\.none|HOVER_TYPE\.none|typeof .*\[' \
  src/components/media-query --glob '*.js.flow'

fd -a '^package\.json$' . -E node_modules -x jq -r \
  '.scripts // {} | to_entries[] | select(.key | test("flow"; "i")) | "\(.key): \(.value)"' {}

Repository: box/box-ui-elements

Length of output: 3608


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Files:\n'
git ls-files 'src/components/media-query/*'

printf '\nRelevant source:\n'
for f in src/components/media-query/types.js.flow src/components/media-query/*.js.flow package.json; do
  if [ -f "$f" ]; then
    echo "--- $f"
    sed -n '1,80p' "$f"
  fi
done

printf '\nFind flow/config references:\n'
rg -n '"flow"|"flow-bin"|flow' package.json .flowconfig jsconfig.json .vimrc 2>/dev/null || true

printf '\nCheck for external flow executable/version hints:\n'
(command -v flow && flow --version 2>/dev/null) || true
npm list flow-bin 2>/dev/null || true

Repository: box/box-ui-elements

Length of output: 13025


🌐 Web query:

Flow type syntax type alias object literal property union imported const property string literal union

💡 Result:

In Flow, you can combine type aliases, object literals, union types, and property types to model complex data structures, such as disjoint unions, which are often used for state management or event handling [1][2][3]. Type Alias and Object Literal A type alias provides a reusable name for a type [4]. You can define an object literal type using the syntax { key: Type } [5][6]. For example: type User = { id: number, name: string }; String Literal Unions Literal types restrict a value to specific constants [7]. Combining them with unions allows you to define a finite set of allowed values, such as specific string tags [7][8]. type ActionType = 'LOGIN' | 'LOGOUT'; Disjoint Object Unions A disjoint object union is a union of object types that share a common "discriminant" property with distinct literal values [1]. This allows Flow to narrow (refine) the type based on the value of that property [1][2]. type UserAction = | { type: 'LOGIN', userId: number } | { type: 'LOGOUT', userId: number }; Using Imported Const Properties To derive a union of string literals from a collection of constants (e.g., imported from another module), you can use the typeof operator [4][9]. If you have a constant object, you can extract the union of its property types [10]. // config.js export const ACTIONS = { LOGIN: 'LOGIN', LOGOUT: 'LOGOUT' }; // types.js import { ACTIONS } from './config'; type ActionValues = $Values; // 'LOGIN' | 'LOGOUT' Key Syntax Considerations 1. Exact Objects: By default, Flow object types are exact (they reject extra properties) [5][6]. To allow extra properties, use the inexact syntax: { property: string,... } [5][6]. 2. Const Expressions: Use as const to preserve narrow literal types in objects or arrays, preventing them from widening to their base primitive types [7][9]. 3. Refinements: When using disjoint unions, ensure the discriminant property has a concrete literal type so Flow can successfully refine the type within control flow statements like if or switch [1][2].

Citations:


Use a valid Flow type alias.

POINTER_TYPE.none and HOVER_TYPE.none are value expressions, so the aliases on lines 5-6 are not valid Flow type syntax. Type MediaPointerType/MediaHoverType as string-literal unions or use a typeof property query in the alias.

Proposed fix
-import { POINTER_TYPE, HOVER_TYPE } from './constants';
-
-export type MediaPointerType = POINTER_TYPE.none | POINTER_TYPE.coarse | POINTER_TYPE.fine;
-export type MediaHoverType = HOVER_TYPE.none | HOVER_TYPE.hover;
+export type MediaPointerType = 'none' | 'coarse' | 'fine';
+export type MediaHoverType = 'none' | 'hover';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

export type MediaPointerType = 'none' | 'coarse' | 'fine';
export type MediaHoverType = 'none' | 'hover';
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/media-query/types.js.flow` around lines 3 - 6, Update the
MediaPointerType and MediaHoverType aliases to use valid Flow syntax: define
them as string-literal unions matching the POINTER_TYPE and HOVER_TYPE values,
or use typeof property queries for those constants. Keep the existing exported
names and supported values unchanged.

Comment thread src/components/media-query/useMediaQuery.ts
Comment thread src/components/media-query/withMediaQuery.tsx
vitali-usik
vitali-usik previously approved these changes Aug 4, 2026
@bonchevskyi
bonchevskyi force-pushed the refactor/flow-to-ts-media-query branch from 87a16fb to e85e6f9 Compare August 4, 2026 11:11

@jpan-box jpan-box left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@bonchevskyi
bonchevskyi requested a review from jpan-box August 5, 2026 09:33
@bonchevskyi
bonchevskyi force-pushed the refactor/flow-to-ts-media-query branch 2 times, most recently from 25092e3 to e8290ec Compare August 5, 2026 13:24
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@bonchevskyi
bonchevskyi force-pushed the refactor/flow-to-ts-media-query branch from e8290ec to 4879bfa Compare August 5, 2026 13:36
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@bonchevskyi
bonchevskyi force-pushed the refactor/flow-to-ts-media-query branch from 4879bfa to 93a1208 Compare August 5, 2026 13:58
@bonchevskyi
bonchevskyi force-pushed the refactor/flow-to-ts-media-query branch from 93a1208 to f62724d Compare August 6, 2026 08:38
@mergify mergify Bot added the queued label Aug 6, 2026
@mergify

mergify Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Merge Queue Status

  • Entered queue2026-08-06 09:22 UTC · Rule: Automatic strict merge · triggered by rule Automatic merge queue
  • Checks skipped · PR is already up-to-date
  • Merged2026-08-06 09:22 UTC · at f62724df94a71a732c3f27217eadf7b6a3a53c47 · squash

This pull request spent 21 seconds in the queue, including 3 seconds running CI.

Required conditions to merge
  • github-review-approved [🛡 GitHub branch protection]
  • any of [🛡 GitHub branch protection]:
    • check-success = Summary
    • check-neutral = Summary
    • check-skipped = Summary
  • any of [🛡 GitHub branch protection]:
    • check-success = lint_test_build
    • check-neutral = lint_test_build
    • check-skipped = lint_test_build
  • any of [🛡 GitHub branch protection]:
    • check-success = license/cla
    • check-neutral = license/cla
    • check-skipped = license/cla
  • any of [🛡 GitHub branch protection]:
    • check-success = lint_pull_request
    • check-neutral = lint_pull_request
    • check-skipped = lint_pull_request

@mergify
mergify Bot merged commit 5aef4b0 into box:master Aug 6, 2026
9 of 10 checks passed
@mergify mergify Bot removed the queued label Aug 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants