Skip to content

Conversation

@pzanella
Copy link
Contributor

Reorganized the hang-ui source folder structure.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 13, 2026

Walkthrough

The hang-ui package was reorganized from a flat file layout to a modular directory structure. Root-level entry files for publish, watch, and stats were replaced by directory index.tsx entry points. Components, hooks, contexts, and styles were moved into dedicated subdirectories and import paths across the codebase were updated. README and build config were adjusted to match the new layout.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: reorganizing the hang-ui folder structure through refactoring, which aligns with the changeset's comprehensive restructuring of imports, exports, and module organization.
Description check ✅ Passed The description is directly related to the changeset, explaining the reorganization of the hang-ui source folder structure, which matches the comprehensive refactoring shown across all modified files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7a079b6 and 985f7eb.

📒 Files selected for processing (1)
  • js/hang-ui/README.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • js/hang-ui/README.md
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Check

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 and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In @js/hang-ui/README.md:
- Around line 40-48: The snippet for <hang-publish-ui> uses hard tabs for
indentation while the earlier <hang-watch-ui> example uses spaces; update the
snippet so all indentation is spaces (matching the style used in
<hang-watch-ui>), replacing each leading tab with the repository's configured
number of spaces (e.g., 2 or 4) so the entire block (<hang-publish-ui>,
<hang-publish>, and <video> lines) uses consistent space indentation.
- Around line 58-66: Update the README text to remove the React reference and
use Solid-specific wording: find and replace the string "Custom React/Solid
hooks" with "Custom Solid hooks" in the README entries under the publish and
watch sections (look for the lines describing the hooks directories and the
exact phrase "Custom React/Solid hooks" to update).
- Around line 54-87: The fenced ASCII tree in README.md is missing a language
specifier; update the opening fence from ``` to ```text (or ```plaintext) for
the directory tree block so the ASCII directory structure renders correctly;
locate the block starting with the src/ tree (the triple-backtick fenced code
block) and change its opening fence to include the specifier.
🧹 Nitpick comments (1)
js/hang-ui/src/publish/index.tsx (1)

5-5: Consider removing the explicit .tsx extension for consistency.

Other imports in this PR don't include file extensions (e.g., "./context", "../hooks/use-watch-ui"). For consistency, consider using "./element" instead.

Suggested change
-import { PublishUI } from "./element.tsx";
+import { PublishUI } from "./element";
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 189f6f6 and 7a079b6.

⛔ Files ignored due to path filters (20)
  • js/hang-ui/src/shared/components/icon/arrow-down.svg is excluded by !**/*.svg
  • js/hang-ui/src/shared/components/icon/arrow-up.svg is excluded by !**/*.svg
  • js/hang-ui/src/shared/components/icon/audio.svg is excluded by !**/*.svg
  • js/hang-ui/src/shared/components/icon/ban.svg is excluded by !**/*.svg
  • js/hang-ui/src/shared/components/icon/buffer.svg is excluded by !**/*.svg
  • js/hang-ui/src/shared/components/icon/camera.svg is excluded by !**/*.svg
  • js/hang-ui/src/shared/components/icon/file.svg is excluded by !**/*.svg
  • js/hang-ui/src/shared/components/icon/fullscreen-enter.svg is excluded by !**/*.svg
  • js/hang-ui/src/shared/components/icon/fullscreen-exit.svg is excluded by !**/*.svg
  • js/hang-ui/src/shared/components/icon/microphone.svg is excluded by !**/*.svg
  • js/hang-ui/src/shared/components/icon/mute.svg is excluded by !**/*.svg
  • js/hang-ui/src/shared/components/icon/network.svg is excluded by !**/*.svg
  • js/hang-ui/src/shared/components/icon/pause.svg is excluded by !**/*.svg
  • js/hang-ui/src/shared/components/icon/play.svg is excluded by !**/*.svg
  • js/hang-ui/src/shared/components/icon/screen.svg is excluded by !**/*.svg
  • js/hang-ui/src/shared/components/icon/stats.svg is excluded by !**/*.svg
  • js/hang-ui/src/shared/components/icon/video.svg is excluded by !**/*.svg
  • js/hang-ui/src/shared/components/icon/volume-high.svg is excluded by !**/*.svg
  • js/hang-ui/src/shared/components/icon/volume-low.svg is excluded by !**/*.svg
  • js/hang-ui/src/shared/components/icon/volume-medium.svg is excluded by !**/*.svg
📒 Files selected for processing (59)
  • js/hang-ui/README.md
  • js/hang-ui/package.json
  • js/hang-ui/src/publish/components/CameraSourceButton.tsx
  • js/hang-ui/src/publish/components/FileSourceButton.tsx
  • js/hang-ui/src/publish/components/MediaSourceSelector.tsx
  • js/hang-ui/src/publish/components/MicrophoneSourceButton.tsx
  • js/hang-ui/src/publish/components/NothingSourceButton.tsx
  • js/hang-ui/src/publish/components/PublishControls.tsx
  • js/hang-ui/src/publish/components/PublishStatusIndicator.tsx
  • js/hang-ui/src/publish/components/ScreenSourceButton.tsx
  • js/hang-ui/src/publish/context.tsx
  • js/hang-ui/src/publish/element.tsx
  • js/hang-ui/src/publish/hooks/use-publish-ui.ts
  • js/hang-ui/src/publish/index.tsx
  • js/hang-ui/src/publish/styles/index.css
  • js/hang-ui/src/shared/components/button/button.css
  • js/hang-ui/src/shared/components/button/button.tsx
  • js/hang-ui/src/shared/components/icon/icon.tsx
  • js/hang-ui/src/shared/flex.css
  • js/hang-ui/src/shared/variables.css
  • js/hang-ui/src/stats.tsx
  • js/hang-ui/src/stats/README.md
  • js/hang-ui/src/stats/__tests__/Stats.test.tsx
  • js/hang-ui/src/stats/__tests__/components/StatsItem.test.tsx
  • js/hang-ui/src/stats/__tests__/components/StatsPanel.test.tsx
  • js/hang-ui/src/stats/__tests__/providers/audio.test.ts
  • js/hang-ui/src/stats/__tests__/providers/base.test.ts
  • js/hang-ui/src/stats/__tests__/providers/buffer.test.ts
  • js/hang-ui/src/stats/__tests__/providers/network.test.ts
  • js/hang-ui/src/stats/__tests__/providers/registry.test.ts
  • js/hang-ui/src/stats/__tests__/providers/video.test.ts
  • js/hang-ui/src/stats/__tests__/utils.ts
  • js/hang-ui/src/stats/components/StatsItem.tsx
  • js/hang-ui/src/stats/components/StatsPanel.tsx
  • js/hang-ui/src/stats/index.tsx
  • js/hang-ui/src/stats/providers/audio.ts
  • js/hang-ui/src/stats/providers/base.ts
  • js/hang-ui/src/stats/providers/buffer.ts
  • js/hang-ui/src/stats/providers/index.ts
  • js/hang-ui/src/stats/providers/network.ts
  • js/hang-ui/src/stats/providers/registry.ts
  • js/hang-ui/src/stats/providers/video.ts
  • js/hang-ui/src/stats/styles/index.css
  • js/hang-ui/src/stats/types.ts
  • js/hang-ui/src/watch/components/BufferingIndicator.tsx
  • js/hang-ui/src/watch/components/FullscreenButton.tsx
  • js/hang-ui/src/watch/components/LatencySlider.tsx
  • js/hang-ui/src/watch/components/PlayPauseButton.tsx
  • js/hang-ui/src/watch/components/QualitySelector.tsx
  • js/hang-ui/src/watch/components/StatsButton.tsx
  • js/hang-ui/src/watch/components/VolumeSlider.tsx
  • js/hang-ui/src/watch/components/WatchControls.tsx
  • js/hang-ui/src/watch/components/WatchStatusIndicator.tsx
  • js/hang-ui/src/watch/context.tsx
  • js/hang-ui/src/watch/element.tsx
  • js/hang-ui/src/watch/hooks/use-watch-ui.ts
  • js/hang-ui/src/watch/index.tsx
  • js/hang-ui/src/watch/styles/index.css
  • js/hang-ui/vite.config.ts
💤 Files with no reviewable changes (1)
  • js/hang-ui/src/stats.tsx
🧰 Additional context used
📓 Path-based instructions (1)
js/**/*.{ts,tsx,js,jsx,json}

📄 CodeRabbit inference engine (CLAUDE.md)

Use bun for all TypeScript/JavaScript package management and script execution (not npm, yarn, or pnpm)

Files:

  • js/hang-ui/src/stats/components/StatsPanel.tsx
  • js/hang-ui/src/publish/hooks/use-publish-ui.ts
  • js/hang-ui/src/watch/components/QualitySelector.tsx
  • js/hang-ui/src/publish/components/MicrophoneSourceButton.tsx
  • js/hang-ui/src/watch/components/PlayPauseButton.tsx
  • js/hang-ui/src/watch/components/LatencySlider.tsx
  • js/hang-ui/src/publish/components/ScreenSourceButton.tsx
  • js/hang-ui/src/publish/components/PublishStatusIndicator.tsx
  • js/hang-ui/src/watch/element.tsx
  • js/hang-ui/package.json
  • js/hang-ui/src/publish/components/MediaSourceSelector.tsx
  • js/hang-ui/src/watch/hooks/use-watch-ui.ts
  • js/hang-ui/src/watch/index.tsx
  • js/hang-ui/src/publish/components/CameraSourceButton.tsx
  • js/hang-ui/src/stats/__tests__/components/StatsItem.test.tsx
  • js/hang-ui/src/watch/components/VolumeSlider.tsx
  • js/hang-ui/src/publish/components/FileSourceButton.tsx
  • js/hang-ui/src/watch/components/WatchStatusIndicator.tsx
  • js/hang-ui/src/publish/element.tsx
  • js/hang-ui/src/watch/components/FullscreenButton.tsx
  • js/hang-ui/src/watch/components/BufferingIndicator.tsx
  • js/hang-ui/src/watch/components/StatsButton.tsx
  • js/hang-ui/src/publish/index.tsx
  • js/hang-ui/src/publish/components/NothingSourceButton.tsx
  • js/hang-ui/vite.config.ts
🧠 Learnings (1)
📚 Learning: 2026-01-11T03:47:52.766Z
Learnt from: CR
Repo: moq-dev/moq PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T03:47:52.766Z
Learning: Applies to js/**/*.{ts,tsx,js,jsx,json} : Use `bun` for all TypeScript/JavaScript package management and script execution (not npm, yarn, or pnpm)

Applied to files:

  • js/hang-ui/package.json
  • js/hang-ui/vite.config.ts
🪛 markdownlint-cli2 (0.18.1)
js/hang-ui/README.md

41-41: Hard tabs
Column: 1

(MD010, no-hard-tabs)


42-42: Hard tabs
Column: 1

(MD010, no-hard-tabs)


43-43: Hard tabs
Column: 1

(MD010, no-hard-tabs)


44-44: Hard tabs
Column: 1

(MD010, no-hard-tabs)


45-45: Hard tabs
Column: 1

(MD010, no-hard-tabs)


46-46: Hard tabs
Column: 1

(MD010, no-hard-tabs)


47-47: Hard tabs
Column: 1

(MD010, no-hard-tabs)


54-54: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Check
🔇 Additional comments (26)
js/hang-ui/src/watch/components/WatchStatusIndicator.tsx (1)

1-20: LGTM!

The import path update correctly reflects the new modular structure. The path ../hooks/use-watch-ui properly resolves from watch/components/ to watch/hooks/use-watch-ui.ts.

js/hang-ui/src/watch/hooks/use-watch-ui.ts (1)

1-12: LGTM!

The import path update to ../context correctly points to the consolidated context module. The hook implementation properly validates context availability with a descriptive error message.

js/hang-ui/src/watch/components/LatencySlider.tsx (1)

1-33: LGTM!

The import path update is consistent with other watch components using the same ../hooks/use-watch-ui pattern.

js/hang-ui/src/watch/components/VolumeSlider.tsx (1)

1-42: LGTM!

All import path updates are correct:

  • Shared components (Button, Icon) now use the deeper ../../shared/components/... structure
  • Hook import is consistent with other watch components
js/hang-ui/src/stats/components/StatsPanel.tsx (1)

1-53: LGTM!

The Icon import path update to ../../shared/components/icon/icon is consistent with the same pattern used in watch components (e.g., VolumeSlider.tsx), maintaining uniformity across the codebase.

js/hang-ui/src/stats/__tests__/components/StatsItem.test.tsx (1)

4-4: LGTM!

The import path update correctly reflects the new modular structure where the Icon component has been moved to shared/components/icon/icon.

js/hang-ui/src/watch/components/FullscreenButton.tsx (1)

2-4: LGTM!

The import path updates correctly reflect the new modular structure:

  • Button and Icon components moved under shared/components/
  • Hook relocated to watch/hooks/
js/hang-ui/src/watch/components/BufferingIndicator.tsx (1)

2-2: LGTM!

The import path correctly points to the new hook location under watch/hooks/.

js/hang-ui/src/publish/styles/index.css (1)

1-3: LGTM!

The CSS import paths correctly reflect the reorganized structure:

  • Shared CSS files remain at shared/ level
  • Button CSS moved to componentized location under shared/components/button/
js/hang-ui/src/watch/index.tsx (1)

4-4: LGTM!

The import path update correctly reflects the flattened module structure, moving the main UI component to element.tsx at the module root level.

js/hang-ui/src/publish/hooks/use-publish-ui.ts (1)

1-12: LGTM!

The import path update correctly references the new ../context location from the hooks directory. The hook implementation remains unchanged and follows best practices with proper null-check error handling.

js/hang-ui/src/publish/components/PublishStatusIndicator.tsx (1)

1-20: LGTM!

The import path update correctly references ../hooks/use-publish-ui from the components directory. The component logic is clean and unchanged.

js/hang-ui/src/publish/components/MicrophoneSourceButton.tsx (1)

1-44: LGTM!

The import path updates are consistent with the new folder structure:

  • Button and Icon components correctly reference the shared components directory
  • The hook import follows the same pattern as other publish components

Component logic remains unchanged.

js/hang-ui/src/publish/components/NothingSourceButton.tsx (1)

1-24: LGTM!

Import paths are consistent with the pattern established in other publish components. The component logic is unchanged and straightforward.

js/hang-ui/src/watch/components/StatsButton.tsx (1)

1-20: LGTM!

Import paths follow the same consistent pattern used in the publish module:

  • Shared components referenced via ../../shared/components/
  • Module-specific hooks referenced via ../hooks/

The component logic is clean and unchanged.

js/hang-ui/src/watch/components/QualitySelector.tsx (1)

1-5: LGTM!

The import path update correctly reflects the new directory structure. The relative path ../hooks/use-watch-ui properly navigates from the components/ directory to the hooks/ directory.

js/hang-ui/src/watch/components/PlayPauseButton.tsx (1)

1-4: LGTM!

Import paths are correctly updated to reflect the new directory structure:

  • Shared components properly referenced via ../../shared/components/
  • Hook correctly referenced via ../hooks/
js/hang-ui/src/publish/element.tsx (1)

1-4: LGTM!

Import paths correctly updated to the new modular structure with components/, context/, and styles/ subdirectories.

js/hang-ui/src/watch/element.tsx (1)

1-9: LGTM!

Import paths correctly updated to the new modular structure. The organization into components/, context/, and styles/ subdirectories is consistent with the publish/ module refactoring.

js/hang-ui/src/publish/components/CameraSourceButton.tsx (1)

1-5: LGTM!

The updated import paths correctly reflect the new folder structure:

  • Shared components accessed via ../../shared/components/
  • Hook accessed via ../hooks/
  • Co-located MediaSourceSelector correctly kept as relative ./
js/hang-ui/src/watch/styles/index.css (1)

1-4: LGTM!

The CSS import paths are correctly adjusted for the new folder structure. Path calculations are accurate:

  • ../../shared/ for shared CSS files
  • ../../shared/components/button/ for component-specific styles
  • ../../stats/styles/ for cross-module style imports
js/hang-ui/src/publish/components/FileSourceButton.tsx (1)

1-4: LGTM!

Import paths are consistent with the pattern established in CameraSourceButton.tsx and align with the folder restructuring.

js/hang-ui/src/publish/components/MediaSourceSelector.tsx (1)

1-3: LGTM!

Import paths for Button and Icon are consistent with the other publish components.

js/hang-ui/src/publish/components/ScreenSourceButton.tsx (1)

1-3: LGTM!

Import paths follow the consistent pattern established across all publish components in this PR. The folder restructuring maintains uniform import conventions.

js/hang-ui/package.json (1)

8-17: LGTM! Exports and sideEffects paths are consistent.

The export mappings and sideEffects entries are correctly updated to point to the new index.tsx entry points within each module directory. The structure is consistent across all three modules (publish, watch, stats).

js/hang-ui/vite.config.ts (1)

9-13: LGTM! Entry points align with package.json exports.

The library entry points correctly resolve to the new index.tsx files within each module directory, maintaining consistency with the exports field in package.json.

Copy link
Collaborator

@jdreetz jdreetz left a comment

Choose a reason for hiding this comment

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

Looks great! One question: why is Stats outside of the Watch UI?

- **BufferingIndicator**: Visual feedback during buffering
- **StatsButton**: Toggle statistics panel

#### **stats/**
Copy link
Collaborator

Choose a reason for hiding this comment

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

Stats is only used by the Watch UI, right? Why isn't it a component of watch?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hey @jdreetz! Thank you for your feedback! The Stats component is currently used only by the Watch UI. I was thinking we could also use it for real-time stats in the Publish UI later. Do you think it makes sense to move it to the shared folder? If not, no worries, I can just keep it under the Watch UI. Let me know. Thanks!

Copy link
Collaborator

Choose a reason for hiding this comment

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

If you think we'd use it elsewhere, then yea, I'd move it to shared components.

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