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

design review: timer #1458

Merged
merged 9 commits into from
Jan 24, 2025
Merged

design review: timer #1458

merged 9 commits into from
Jan 24, 2025

Conversation

cpvalente
Copy link
Owner

@cpvalente cpvalente commented Jan 18, 2025

Starting the design review with the timer and associated components. This is divided in two parts

Style and code tweaks

  • Simplify getting params
  • Ensure timer colour can be overridden in all phases
  • Style timer type none
  • Clock seconds is substring
  • handle longer titles
  • mobile views
  • what should be displayed when nothing is playing
  • what should be displayed when waiting to start (roll mode)
  • what should be displayed when loaded but not started

Behaviour and structure changes

  • Timer type overrides per view
  • Minimal and Clock are subviews

Copy link
Contributor

coderabbitai bot commented Jan 18, 2025

Important

Review skipped

Auto reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This pull request involves a comprehensive restructuring of the timer-related components and utilities across multiple files in the client application. The changes include relocating the Timer component from the features/viewers/timer directory to a new views/timer directory, updating import paths, modifying styling approaches, and introducing new utility functions and options management for timer displays. The modifications aim to improve the organization, flexibility, and maintainability of the timer functionality.

Changes

File Change Summary
apps/client/src/AppRouter.tsx Updated import path for TimerView from ./features/viewers/timer/Timer to ./views/timer/Timer
apps/client/src/common/components/multi-part-progress-bar/* Modified progress bar styling and added new overtime-related class
apps/client/src/common/components/title-card/* Updated font sizing variables and made title optional
apps/client/src/features/viewers/common/superscript-time/* Added new subscript styling and time parsing function
apps/client/src/features/viewers/common/viewUtils.ts Enhanced getTimerByType function with optional timer type override
apps/client/src/theme/_viewerDefs.scss Introduced new sizing variables and updated timer value size
apps/client/src/views/timer/* Completely restructured timer component, added new utility functions, options management, and animations

Possibly related PRs

Suggested Labels

priority


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@cpvalente cpvalente force-pushed the timer-review branch 3 times, most recently from 3c91d00 to 1d5d063 Compare January 21, 2025 20:18
@cpvalente
Copy link
Owner Author

@coderabbitai full review

Copy link
Contributor

coderabbitai bot commented Jan 24, 2025

✅ Actions performed

Full review triggered.

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

🧹 Nitpick comments (14)
apps/client/src/views/timer/timer.animations.ts (1)

5-18: Consider honoring reduced motion preferences.
A 1-second transition duration may be too lengthy for some users, and you could improve accessibility by conditionally reducing or disabling animations when prefers-reduced-motion is enabled at the OS level.

apps/client/src/common/components/multi-part-progress-bar/MultiPartProgressBar.tsx (1)

17-17: New optional property hideOvertime is clear.
Document it in the prop definition or component usage notes to help others understand its behavior.

apps/client/src/views/timer/timer.utils.ts (5)

18-20: Consider trimming whitespace-only messages.

getShowMessage only checks for an empty string but not whitespace. If whitespace-only messages are to be hidden, consider trimming the text before evaluation.


25-27: Check for any additional playback states.

getIsPlaying returns true for Play or Roll. If other playback states exist (like pause, or a newly introduced custom state), ensure each is accounted for or intentionally excluded.


46-48: Naming could be more explicit.

getShowClock returning false for TimerType.Clock can be confusing at a glance. Consider a more self-descriptive function name, like shouldHideClockForType.


95-109: Additional conditions for showing modifiers could be consolidated.

The logic for showEndMessage, showFinished, showWarning, and showDanger is straightforward, but you might unify common conditions, reduce repetition, or incorporate them in a single object with typed states.


149-189: Potential to extract sub-functions for clarity.

getCardData manages multiple conditions for current and next events. To improve readability, consider splitting out the “stop” scenario, “active” scenario, and “pending” scenario into smaller helper functions.

apps/client/src/views/timer/Timer.tsx (3)

41-52: Validate prop defaults and usage.

The TimerProps interface is quite extensive. For better maintainability, consider providing default values (or internal fallbacks) for props such as customFields and viewSettings if they can sometimes be undefined. This ensures the component doesn’t break in edge cases.


74-74: Address the TODO regarding size issues.

The TODO comment indicates a known issue with displaying minutes. Consider prioritizing a fix or fallback approach to avoid rendering inconsistencies in strict layouts.


90-99: Ensure data completeness for card display.

When using mainSource and secondarySource to determine card data, check that you handle scenarios in which eventNow or eventNext fields are missing or incomplete. Consider adding a safeguard to avoid rendering partial or null states.

apps/client/src/common/components/multi-part-progress-bar/MultiPartProgressBar.scss (1)

3-3: Use caution with fixed height progress bars.

Changing $progress-bar-size to 1.5rem may affect vertical spacing in some layouts. Ensure it doesn’t overlap other elements on smaller screens or constrained containers.

apps/client/src/theme/_viewerDefs.scss (1)

38-38: Check new clamp range for $timer-value-size.

Switching from 2rem, 3.5vw, 3.5rem to 32px, 3.5vw, 50px tightens the minimum and maximum sizes. Verify that 32px isn’t overly large on small displays or too small on higher-end screens for your typical user base.

apps/server/src/user/styles/override.css (1)

50-54: Consider using semantic naming for studio variables.

The studio-specific variables could be more semantically named to better reflect their purpose.

Consider renaming:

--- studio-active: #101010;
+++ studio-active-background: #101010;
--- studio-idle: #cfcfcf;
+++ studio-idle-background: #cfcfcf;
apps/client/src/views/timer/Timer.scss (1)

124-128: Consider using CSS custom properties for phase colors.

The phase-based color system could be more maintainable using CSS custom properties.

-      &[data-phase="warning"] {
-        color: var(--timer-warning-color-override, var(--phase-color));
-      }
-      &[data-phase="danger"] {
-        color: var(--timer-danger-color-override, var(--phase-color));
-      }
+      @each $phase in (warning, danger) {
+        &[data-phase="#{$phase}"] {
+          color: var(--timer-#{$phase}-color-override, var(--phase-color));
+        }
+      }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 30e290c and 1292d54.

📒 Files selected for processing (20)
  • apps/client/src/AppRouter.tsx (1 hunks)
  • apps/client/src/common/components/multi-part-progress-bar/MultiPartProgressBar.scss (2 hunks)
  • apps/client/src/common/components/multi-part-progress-bar/MultiPartProgressBar.tsx (4 hunks)
  • apps/client/src/common/components/title-card/TitleCard.scss (3 hunks)
  • apps/client/src/common/components/title-card/TitleCard.tsx (1 hunks)
  • apps/client/src/features/operator/status-bar/StatusBar.module.scss (1 hunks)
  • apps/client/src/features/viewers/common/superscript-time/SuperscriptTime.scss (1 hunks)
  • apps/client/src/features/viewers/common/superscript-time/SuperscriptTime.tsx (1 hunks)
  • apps/client/src/features/viewers/common/viewUtils.ts (2 hunks)
  • apps/client/src/features/viewers/timer/Timer.tsx (0 hunks)
  • apps/client/src/features/viewers/timer/timer.options.ts (0 hunks)
  • apps/client/src/theme/_viewerDefs.scss (2 hunks)
  • apps/client/src/views/cuesheet/cuesheet.options.ts (1 hunks)
  • apps/client/src/views/timer/Timer.scss (9 hunks)
  • apps/client/src/views/timer/Timer.tsx (1 hunks)
  • apps/client/src/views/timer/timer.animations.ts (1 hunks)
  • apps/client/src/views/timer/timer.options.ts (1 hunks)
  • apps/client/src/views/timer/timer.utils.ts (1 hunks)
  • apps/server/src/user/styles/override.css (1 hunks)
  • packages/utils/src/validate-events/validateEvent.test.ts (1 hunks)
💤 Files with no reviewable changes (2)
  • apps/client/src/features/viewers/timer/timer.options.ts
  • apps/client/src/features/viewers/timer/Timer.tsx
🔇 Additional comments (43)
apps/client/src/features/operator/status-bar/StatusBar.module.scss (1)

Line range hint 108-111: Verify progress bar height consistency and improve documentation.

  1. The height of 1rem here differs from the 1.5rem in MultiPartProgressBar.scss. Please verify if this difference is intentional.
  2. The CSS custom property --progress-bar-br would benefit from documentation explaining its purpose.

Consider renaming the class to be more semantic, e.g.:

-.progressOverride {
+.progress-bar--compact {
   height: 1rem;
   --progress-bar-br: 0;
 }
apps/client/src/features/viewers/common/superscript-time/SuperscriptTime.tsx (5)

12-13: Good documentation practice.

The comment succinctly indicates the intention behind separating seconds from the main time string, which increases maintainability and clarity.


14-20: Edge-case handling suggestion.

While the function correctly handles the standard 8-character input (e.g., "HH:MM:SS"), consider whether you need stricter validation or formatting for unusual cases (e.g., "12:0:9", user typos, or partial times). Currently, inputs that are not exactly 8 characters simply return the original string. If these are truly out-of-scope, adding a comment clarifying expectations would help future maintainers.


22-25: Effective examples in documentation.

Showing an example for typical HH:MM behavior and an example including seconds helps users quickly grasp the purpose of the subscript formatting. Great job proactively clarifying usage!


32-32: Validate split usage for advanced formats.

Splitting by space to separate a period-like segment (e.g., "AM", or "PM") is straightforward but may have edge cases if users pass more than one space or unexpected text. If multiple tokens are possible, consider adopting a more robust approach (e.g., RegEx) or ensuring usage strictly follows your format requirements.


36-37: Sensible conditional rendering of seconds.

Displaying the subscript element only when seconds exist keeps the markup clean and avoids empty spans. This approach is both readable and efficient.

apps/client/src/features/viewers/common/superscript-time/SuperscriptTime.scss (1)

5-8: Consistent styling approach.

Defining .subscript as a separate class with a suitable font size aligns well with the existing .period class. This fosters consistent, modular styling.

apps/client/src/views/timer/timer.animations.ts (3)

1-1: Import from 'framer-motion' is appropriate.
No issues here.


3-3: Ensure the relative import path for TitleCard is valid.
Double-check that this path correctly reflects the file structure to avoid runtime errors.


20-20: Exporting a motion-wrapped TitleCard is a neat approach.
This pattern cleanly separates animation specifics from the original component.

apps/client/src/common/components/title-card/TitleCard.tsx (1)

8-8: Be mindful of null/undefined titles.
Making the title optional is fine, but ensure the UI gracefully handles an empty or missing title. Consider a fallback to avoid empty text elements.

packages/utils/src/validate-events/validateEvent.test.ts (1)

30-33: Appreciate the added test for null timer types.
This strengthens the function’s coverage. You might also consider tests for undefined or other unexpected input types.

apps/client/src/common/components/multi-part-progress-bar/MultiPartProgressBar.tsx (5)

4-4: Using cx is a good practice for conditional classNames.
Ensures maintainable and clean code, no issues here.


32-32: Consistent destructuring of hideOvertime.
This maintains clarity in reading the function signature.


40-41: Logic for detecting overtime is straightforward.
Implementing isOvertime as now < 0 is concise.


45-50: Neat usage of cx for dynamic class handling.
The array-based approach keeps the className logic succinct.


61-62: Conditionally masking danger color for overtime is a smart move.
Cleanly differentiates normal danger mode from overtime mode.

apps/client/src/views/cuesheet/cuesheet.options.ts (1)

79-79: Ensure no external dependencies rely on this function export removal.

By removing the export keyword from getOptionsFromParams, you've effectively made it private to this module. Verify that no other modules rely on this function externally. If so, they will break after this change.

apps/client/src/features/viewers/common/viewUtils.ts (4)

10-14: Validate all callers for updated function signature.

Adding the optional parameter timerTypeOverride changes the function signature. Please ensure all call sites are updated accordingly to avoid runtime errors.


19-20: Fallback logic is sound.

Using the nullish coalescing operator here properly respects overrides while preserving the original timer type when not provided. Nicely done.


28-28: Consistency check for viewTimerType in switch statement.

Switching on viewTimerType is straightforward and more explicit. This improves readability by clearly distinguishing between the override scenario and the default scenario.


40-41: Simplified default clause.

Falling back to null for unrecognized timer types is a clean approach to handle unexpected input.

apps/client/src/views/timer/timer.options.ts (4)

16-21: Confirm omission of None timer type.

You excluded TimerType.None from timerDisplayOptions. If this omission is intentional (e.g., you never want to explicitly set a "none" override), it’s fine; otherwise, consider adding it to ensure consistency of user-selectable options.


23-95: General approach for building timer options is well-structured.

The code effectively composes an array of ViewOption objects by combining preset configurations with custom fields. This pattern is clean and maintainable, providing an extensible basis for future timer settings.


110-132: Successful adaptation of search param parsing.

This function mirrors the structure of your cuesheet param parsing, ensuring consistency for timer-specific options. Just confirm that all property names align with their definitions in TimerOptions.


134-141: useTimerOptions usage highlights a good reactive pattern.

Wrapping the param parsing with useMemo ensures the computation is optimized. This approach is efficient for large-scale or repetitive re-renders.

apps/client/src/views/timer/timer.utils.ts (4)

32-34: Straightforward time calculation.

getTotalTime simply sums duration and addedTime, handling null with defaults. This is concise and reliable.


39-41: Progress bar visibility logic is clear.

Skipping the progress bar for None and Clock maintains alignment with typical user expectations for these timer types.


114-118: Color override hierarchy.

You handle priority for warning and danger states well in getTimerColour. If no color is provided, consider a fallback to ensure the timer remains visible.


123-144: Validate mismatched external sources.

getSecondaryDisplay handles 'aux' or 'external' sources. If a developer sets secondarySource to 'aux' but the message is actually using an 'external' text, ensure the code or documentation clarifies the precedence logic.

apps/client/src/views/timer/Timer.tsx (2)

79-89: Verify logic around timer modifiers.

The evaluation of modifiers (warning, danger, end message) is helpful for controlling visual states. However, if time.timerType or time.phase becomes undefined, this could lead to unexpected states. Ensure that calling code or hooks provide valid data and add fallback checks if needed.


191-225: Check animation resource usage.

Two separate <AnimatePresence> blocks are used for showing “Now” and “Next” events. While this is valid, consider consolidating them or verifying that each block doesn’t unintentionally re-render elements in quick succession, potentially impacting performance.

apps/client/src/common/components/title-card/TitleCard.scss (4)

3-5: Confirm default size behavior.

$title-primary-size and $title-secondary-size use clamp with minimums of 1.5rem and 1rem respectively. For smaller devices or unique layouts, verify these sizes aren’t too large or overlapping.


21-21: Good substitution for responsive sizing.

Switching to $title-primary-size in .title-card__title is an improvement for maintainability and readability of text across various screen sizes.


27-27: Align secondary text styling.

Using $title-secondary-size ensures consistency with the primary title. This helps preserve a coherent hierarchy in the title card design.


36-36: Maintain consistent label styling.

Adopting $timer-label-size for .title-card__label provides uniformity across components, especially when used in tandem with timer-based layouts.

apps/client/src/common/components/multi-part-progress-bar/MultiPartProgressBar.scss (1)

56-58: Approved: Overtime color logic.

Your new .multiprogress-bar__bg-danger--overtime class effectively differentiates overtime from regular danger states. This clarifies the UI for edge cases where the timer has exceeded its intended range.

apps/client/src/theme/_viewerDefs.scss (1)

24-28: Validate new view-element sizing variables.

The newly introduced $view-element-gap, $view-outer-padding, and $view-card-padding define padding using a combination of min(), clamp(), and fixed values. Ensure these values display properly across an array of screen resolutions, including very small or unusually large devices.

apps/server/src/user/styles/override.css (1)

25-27: LGTM! Timer color overrides enhance customization.

The new timer color override variables for warning, danger, and overtime states provide better customization options for different timer phases.

apps/client/src/views/timer/Timer.scss (3)

14-18: LGTM! Improved layout structure.

The switch from grid to flexbox with standardized spacing variables improves maintainability and responsiveness.


201-202: LGTM! Responsive logo positioning.

The use of min() function for logo positioning ensures proper scaling across different viewport sizes.


138-145: Verify the impact of line-height changes.

The line height changes and new spacing values might affect text rendering.

✅ Verification successful

Line height change is safe and localized

The line-height change to 1em in Timer.scss only affects the Timer component's secondary text display. This is a standard value that ensures consistent text rendering and proper vertical alignment. Other components using "secondary" classes have their own independent styling modules and are not affected by this change.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for components using the secondary class
rg -A 5 "className.*secondary" --glob "**/*.{tsx,jsx}"

Length of output: 3566


Script:

#!/bin/bash
# Search for all SCSS/CSS files with line-height or secondary class definitions
rg -A 3 "line-height|\.secondary" --glob "**/*.{scss,css}"

Length of output: 13109

apps/client/src/AppRouter.tsx (1)

25-25: Verify the new Timer component import path.

Ensure that all references to the Timer component have been updated consistently across the codebase.

✅ Verification successful

Timer component import path is correctly updated

The new import path './views/timer/Timer' in AppRouter.tsx is correct and consistent with the actual file location. No outdated references were found in the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining references to the old timer path
rg -l "features/viewers/timer/Timer" --glob "**/*.{tsx,ts,jsx,js}"

Length of output: 66


Script:

#!/bin/bash
# Check if the new Timer component exists
fd Timer.tsx -t f

# Search for any Timer-related imports
rg "import.*Timer" --glob "**/*.{tsx,ts,jsx,js}" -l

# Search for files containing "timer" case-insensitive
fd -i timer -t f -e tsx -e ts -e jsx -e js

Length of output: 5838

@cpvalente cpvalente merged commit d58335d into master Jan 24, 2025
4 checks passed
@cpvalente cpvalente deleted the timer-review branch January 24, 2025 12:13
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.

1 participant