-
Notifications
You must be signed in to change notification settings - Fork 45
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
feat: bunch of bug fixes, style impros, arrangement impros, refactors #1774
Conversation
WalkthroughThe changes in this pull request involve updates to various components across the application, focusing on enhancing user experience and styling. Key modifications include simplifying fallback messages in routing, introducing new styled components, and refining layout structures. Additionally, utility functions for number formatting have been added, and several components have undergone structural changes to improve clarity and consistency in presentation. Changes
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
✅ Deploy Preview for kleros-v2-university ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
❌ Deploy Preview for kleros-v2-testnet-devtools failed. Why did it fail? →
|
✅ Deploy Preview for kleros-v2-testnet ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
✅ Deploy Preview for kleros-v2-neo ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
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.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (19)
web/src/components/Field.tsx (2)
Line range hint
71-106
: Consider these architectural improvements
- The boolean props (
isOverview
,isJurorBalance
,displayAsList
) could be consolidated into avariant
prop using a discriminated union:type FieldVariant = 'default' | 'overview' | 'jurorBalance' | 'list'; interface IField { variant?: FieldVariant; // ... other props }
- The click handler's purpose should be documented, as
stopPropagation()
usage isn't immediately obvious:<StyledInternalLink to={link} + // Prevent click events from bubbling up to parent containers + // This is necessary when the Field is used within clickable containers onClick={(event) => { event.stopPropagation(); }} >These changes would improve maintainability and make the component's behavior more explicit.
Line range hint
93-106
: Enhance accessibility attributesConsider adding these accessibility improvements:
- Add
aria-label
to the icon for screen readers- Ensure proper color contrast for the link text (especially with the new font-weight)
Example implementation:
<FieldContainer isList={displayAsList} {...{ isOverview, isJurorBalance, width, className }}> - <Icon /> + <Icon aria-label={`${name} icon`} /> {(!displayAsList || isOverview || isJurorBalance) && <label>{name}:</label>}web/src/components/DisputePreview/Policies.tsx (1)
66-83
: Consider refactoring for improved maintainabilityThe conditional rendering logic could be simplified and the URL construction could be extracted to reduce repetition.
Consider this refactor:
export const Policies: React.FC<IPolicies> = ({ disputePolicyURI, courtId, attachment }) => { + const renderPolicyLink = ( + to: string, + Icon: typeof StyledPolicyIcon | typeof StyledPaperclipIcon, + label: string + ) => ( + <StyledInternalLink to={to}> + <Icon /> + {label} + </StyledInternalLink> + ); return ( <Container> <StyledP>Policy documents:</StyledP> - {!isUndefined(attachment) && !isUndefined(attachment.uri) ? ( - <StyledInternalLink to={`attachment/?url=${getIpfsUrl(attachment.uri)}`}> - <StyledPaperclipIcon /> - {attachment.label ?? "Attachment"} - </StyledInternalLink> - ) : null} + {attachment?.uri && renderPolicyLink( + `attachment/?url=${getIpfsUrl(attachment.uri)}`, + StyledPaperclipIcon, + attachment.label ?? "Attachment" + )} - {isUndefined(disputePolicyURI) ? null : ( - <StyledInternalLink to={`policy/attachment/?url=${getIpfsUrl(disputePolicyURI)}`}> - <StyledPolicyIcon /> - Dispute Policy - </StyledInternalLink> - )} + {disputePolicyURI && renderPolicyLink( + `policy/attachment/?url=${getIpfsUrl(disputePolicyURI)}`, + StyledPolicyIcon, + "Dispute Policy" + )} - {isUndefined(courtId) ? null : ( - <StyledInternalLink to={`/courts/${courtId}/policy?section=description`}> - <StyledPolicyIcon /> - Court Policy - </StyledInternalLink> - )} + {courtId && renderPolicyLink( + `/courts/${courtId}/policy?section=description`, + StyledPolicyIcon, + "Court Policy" + )} </Container> ); };web/src/components/LightButton.tsx (1)
16-16
: Consider extracting theme colors to constantsThe fill color logic could be more maintainable by extracting the theme colors and opacity values into named constants.
+ const DESKTOP_FILL = (theme) => `${theme.white}BF`; + const DESKTOP_HOVER_FILL = (theme) => theme.white; + const MOBILE_FILL = (theme) => theme.secondaryText; + const MOBILE_HOVER_FILL = (theme) => theme.primaryText; .button-svg { - fill: ${({ theme, isMobileNavbar }) => (isMobileNavbar ? theme.secondaryText : `${theme.white}BF`)} !important; + fill: ${({ theme, isMobileNavbar }) => (isMobileNavbar ? MOBILE_FILL(theme) : DESKTOP_FILL(theme))} !important; } &:hover { .button-svg { - fill: ${({ theme, isMobileNavbar }) => (isMobileNavbar ? theme.primaryText : `${theme.white}`)} !important; + fill: ${({ theme, isMobileNavbar }) => (isMobileNavbar ? MOBILE_HOVER_FILL(theme) : DESKTOP_HOVER_FILL(theme))} !important; } }Also applies to: 21-21
web/src/layout/Header/navbar/Explore.tsx (1)
38-38
: Consider extracting style conditions to styled-components helper functionsThe conditional styling logic could be more maintainable by using styled-components helper functions.
+ const getFontWeight = ({ isActive, isMobileNavbar }) => + isMobileNavbar && isActive ? "600" : "normal"; + const getHoverColor = ({ theme, isMobileNavbar }) => + isMobileNavbar ? theme.primaryText : theme.white; - font-weight: ${({ isActive, isMobileNavbar }) => (isMobileNavbar && isActive ? "600" : "normal")}; + font-weight: ${getFontWeight}; &:hover { - color: ${({ theme, isMobileNavbar }) => (isMobileNavbar ? theme.primaryText : theme.white)} !important; + color: ${getHoverColor} !important; }Also applies to: 43-43
web/src/layout/Header/navbar/index.tsx (2)
Line range hint
26-36
: Consider using CSS variables for transitions.The styled components use hardcoded values for transitions. Consider moving these to CSS variables for better maintainability.
const Wrapper = styled.div<{ isOpen: boolean }>` visibility: ${({ isOpen }) => (isOpen ? "visible" : "hidden")}; position: absolute; top: 100%; left: 0; width: 100vw; height: 100vh; z-index: 1; + transition: visibility var(--transition-speed) ease; `;
Line range hint
135-142
: Consider using a dedicated modal/dialog component.The popup handling logic could benefit from using a dedicated modal component that handles overlay, accessibility, and keyboard interactions.
Consider using a modal component from your UI library or implementing one that:
- Handles keyboard events (Esc to close)
- Manages focus trap
- Provides proper ARIA attributes
- Handles click outside behavior consistently
web/src/utils/beautifyStatNumber.ts (1)
24-45
: Consider enhancing input validation and error handlingThe implementation is functional but could be more robust. Consider these improvements:
export function unbeautifyStatNumber(value: string): number { const multiplierMap: Record<string, number> = { B: 1e9, M: 1e6, K: 1e3, }; - const match = value.match(/^([\d,\.]+)([BMK]?)$/); + const match = value.match(/^(-?[\d,]+\.?\d*?)([BMK]?)$/); if (!match) { - throw new Error("Invalid formatted number string"); + throw new Error( + "Invalid formatted number string. Expected format: optional negative sign, digits with optional commas and decimal point, optional suffix (K/M/B)" + ); } const [, numericPart, unit] = match; + if (numericPart.split(".").length > 2) { + throw new Error("Invalid number format: multiple decimal points found"); + } const numericValue = parseFloat(numericPart.replace(/,/g, "")); if (unit && multiplierMap[unit]) { return numericValue * multiplierMap[unit]; } return numericValue; }The improvements include:
- Support for negative numbers
- More precise decimal number validation
- More descriptive error messages
- Prevention of multiple decimal points
web/src/pages/Courts/CourtDetails/Stats.tsx (1)
265-271
: Consider extracting common USD conversion logicThe getSubtext implementations contain similar patterns for USD conversion.
Consider extracting the common logic:
const calculateUSDValue = (pnkAmount: number, coinPrice?: number) => { if (!pnkAmount) return "N/A"; return formatUSD(unbeautifyStatNumber(beautifyStatNumber(pnkAmount, true)) * (coinPrice ?? 0)); };Then use it in the getSubtext methods:
getSubtext: (data, coinPrice) => { const treeExpectedRewardPerPnk = data?.treeExpectedRewardPerPnk; const ethPriceUSD = pricesData ? pricesData[CoinIds.ETH]?.price : undefined; if (!ethPriceUSD || !treeExpectedRewardPerPnk) return "N/A"; const pnkNeeded = treeExpectedRewardPerPnk * ethPriceUSD; return calculateUSDValue(pnkNeeded, coinPrice); }Also applies to: 288-293
web/src/components/Verdict/Answer.tsx (1)
18-22
: Consider semantic HTML implicationsUsing
h4
for description text might not be semantically correct. Consider usingp
orspan
with appropriate styling instead, as this content appears to be descriptive rather than a heading.-const AnswerDescription = styled.h4` +const AnswerDescription = styled.p` margin: 0; font-size: 15px; color: ${({ theme }) => theme.primaryText}; `;web/src/components/DisputeView/DisputeInfo/DisputeInfoList.tsx (2)
Line range hint
38-43
: Consider improving the truncateText utilityThe truncation function could be enhanced in several ways:
- Handle null/undefined input gracefully
- Make the ellipsis character configurable
- Consider word boundaries to avoid cutting words in the middle
-const truncateText = (text: string, limit: number) => { +const truncateText = (text: string | undefined | null, limit: number, ellipsis = '...') => { + if (!text) return ''; if (text && text.length > limit) { - return text.substring(0, limit) + "..."; + const truncated = text.substring(0, limit).trim(); + return truncated + ellipsis; } return text; };
Line range hint
51-57
: Consider selective truncation based on field typeThe current implementation truncates all field values to 20 characters. Consider:
- Making the truncation limit configurable per field
- Excluding certain field types (numbers, dates) from truncation
-value={truncateText(item.value, 20)} +value={item.skipTruncate ? item.value : truncateText(item.value, item.truncateLimit ?? 20)}web/src/components/CasesDisplay/index.tsx (1)
27-29
: Consider using responsiveSize for font-sizeThe font-size is hardcoded to 16px. Consider using the responsiveSize utility for consistent responsive behavior across the application.
const StyledLabel = styled.label` - font-size: 16px; + font-size: ${responsiveSize(14, 16)}; `;web/src/components/DisputeView/DisputeInfo/index.tsx (1)
Line range hint
98-98
: Remove unused dependency from useMemoThe
isOverview
dependency is no longer used in the fieldItems calculation but is still included in the dependencies array. This could cause unnecessary re-renders.], - [category, court, courtId, date, displayAsList, isOverview, period, rewards, round] + [category, court, courtId, date, displayAsList, period, rewards, round] );web/src/app.tsx (1)
98-98
: Consider using a styled error page componentWhile the message is now more professional, consider creating a dedicated styled component for the 404 page to:
- Maintain consistent styling with the rest of the application
- Provide better user experience with potential navigation options
- Keep the error message accessible and visually appealing
Example implementation:
const NotFound = styled.div` display: flex; flex-direction: column; align-items: center; justify-content: center; padding: ${responsiveSize(24, 32)}; h1 { margin-bottom: ${responsiveSize(16, 24)}; } `; // Usage <Route path="*" element={ <NotFound> <h1>Page not found</h1> <StyledArrowLink to="/">Return to home</StyledArrowLink> </NotFound> } />web/src/pages/Courts/CourtDetails/Description.tsx (1)
84-93
: LGTM! Consider extracting the fallback path logic.The conditional rendering with fallback navigation is a good improvement for handling missing policy summaries. However, the fallback path
filteredTabs.length > 0 ? filteredTabs[0].path : ""
is duplicated in both routes.Consider extracting the fallback path logic to improve maintainability:
+ const defaultPath = filteredTabs.length > 0 ? filteredTabs[0].path : ""; <Routes> <Route path="purpose" element={formatMarkdown(policy?.description)} /> <Route path="skills" element={<p>{policy?.requiredSkills}</p>} /> <Route path="policy" element={ policy?.summary ? ( formatMarkdown(policy?.summary) ) : ( - <Navigate to={filteredTabs.length > 0 ? filteredTabs[0].path : ""} replace /> + <Navigate to={defaultPath} replace /> ) } /> - <Route path="*" element={<Navigate to={filteredTabs.length > 0 ? filteredTabs[0].path : ""} replace />} /> + <Route path="*" element={<Navigate to={defaultPath} replace />} /> </Routes>web/src/pages/Courts/CourtDetails/StakePanel/Simulator/index.tsx (3)
Line range hint
122-156
: Consider memoizing complex data transformations.While the hooks usage is correct, consider memoizing the following transformations to prevent unnecessary recalculations:
- jurorStakeData finding
- stake calculations
+ const jurorStakeData = useMemo( + () => stakeData?.jurorTokensPerCourts?.find(({ court }) => court.id === id), + [stakeData, id] + ); + const { jurorCurrentEffectiveStake, jurorCurrentSpecificStake } = useMemo( + () => ({ + jurorCurrentEffectiveStake: address && jurorStakeData ? Number(formatEther(jurorStakeData.effectiveStake)) : 0, + jurorCurrentSpecificStake: address && jurorStakeData ? Number(formatEther(jurorStakeData.staked)) : 0, + }), + [address, jurorStakeData] + );
Line range hint
157-167
: Enhance type safety in calculations.The calculations are correct, but consider using TypeScript's nullish coalescing operator and type guards to improve type safety and readability:
- const { votes: totalVotes, rewards: totalRewards } = totals; + const { votes: totalVotes = 0, rewards: totalRewards = 0 } = totals ?? {}; const courtFutureEffectiveStake = !isUndefined(courtCurrentEffectiveStake) ? Math.max(isStaking ? courtCurrentEffectiveStake + amountToStake : courtCurrentEffectiveStake - amountToStake, 0) : undefined; - const futureTreeVotesPerPnk = - !isUndefined(courtFutureEffectiveStake) && !isUndefined(totalVotes) - ? totalVotes / courtFutureEffectiveStake - : undefined; + const futureTreeVotesPerPnk = courtFutureEffectiveStake + ? totalVotes / courtFutureEffectiveStake + : undefined;
Case-related calculations have been partially removed, but some references remain
The code still contains case-related references that should be addressed:
currentTreeDisputesPerPnk
is still being used in the component- There's a
cases
calculation in thetotals
object that depends oncurrentTreeDisputesPerPnk
- The
cases
value is calculated but never used in the component's UI🔗 Analysis chain
Line range hint
157-167
: Verify complete removal of case-related calculations.The AI summary mentions removal of case-related calculations. Let's verify that all references have been properly removed.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for any remaining case-related references in the codebase rg -i "case" --type ts --type tsx "web/src/pages/Courts/CourtDetails/StakePanel" # Search for any imports or uses of removed case-related functions rg "TreeDisputesPerPnk|totalCases|currentExpectedCases|futureExpectedCases" --type ts --type tsx "web/src/pages/Courts"Length of output: 254
Script:
#!/bin/bash # Search for any remaining case-related references in the codebase, without file type restrictions rg -i "case" "web/src/pages/Courts/CourtDetails/StakePanel" # Search for any imports or uses of removed case-related functions rg "TreeDisputesPerPnk|totalCases|currentExpectedCases|futureExpectedCases" "web/src/pages/Courts" # Additional search to find any case-related calculations in the specific file cat "web/src/pages/Courts/CourtDetails/StakePanel/Simulator/index.tsx"Length of output: 10428
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (22)
web/src/app.tsx
(1 hunks)web/src/components/CasesDisplay/index.tsx
(2 hunks)web/src/components/DisputePreview/Policies.tsx
(2 hunks)web/src/components/DisputeView/DisputeInfo/DisputeInfoCard.tsx
(2 hunks)web/src/components/DisputeView/DisputeInfo/DisputeInfoList.tsx
(1 hunks)web/src/components/DisputeView/DisputeInfo/index.tsx
(1 hunks)web/src/components/Field.tsx
(1 hunks)web/src/components/LightButton.tsx
(3 hunks)web/src/components/Verdict/Answer.tsx
(2 hunks)web/src/components/Verdict/FinalDecision.tsx
(2 hunks)web/src/components/Verdict/VerdictBanner.tsx
(1 hunks)web/src/layout/Header/navbar/Explore.tsx
(4 hunks)web/src/layout/Header/navbar/Menu/index.tsx
(3 hunks)web/src/layout/Header/navbar/index.tsx
(2 hunks)web/src/pages/Cases/CaseDetails/Overview/index.tsx
(1 hunks)web/src/pages/Courts/CourtDetails/Description.tsx
(1 hunks)web/src/pages/Courts/CourtDetails/StakePanel/Simulator/index.tsx
(4 hunks)web/src/pages/Courts/CourtDetails/StakePanel/index.tsx
(2 hunks)web/src/pages/Courts/CourtDetails/Stats.tsx
(6 hunks)web/src/pages/Courts/CourtDetails/index.tsx
(3 hunks)web/src/styles/themes.ts
(2 hunks)web/src/utils/beautifyStatNumber.ts
(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- web/src/pages/Cases/CaseDetails/Overview/index.tsx
🧰 Additional context used
📓 Learnings (1)
web/src/components/DisputeView/DisputeInfo/DisputeInfoList.tsx (1)
Learnt from: nikhilverma360
PR: kleros/kleros-v2#1632
File: web/src/components/DisputeView/DisputeInfo/DisputeInfoList.tsx:37-42
Timestamp: 2024-11-12T04:49:43.234Z
Learning: `useMemo` is used in `DisputeInfoList` to optimize the rendering of `FieldItems` based on changes in `fieldItems`, ensuring that the mapping and truncation operation are only performed when necessary.
🔇 Additional comments (22)
web/src/components/Field.tsx (1)
51-53
: LGTM: Styling changes are well-implemented
The addition of font-weight styling for anchor elements is properly scoped and consistent with the component's existing styling patterns.
web/src/components/DisputePreview/Policies.tsx (2)
14-19
: Well-structured styling improvements!
The new flex layout with responsive gap and simplified margins creates a more maintainable and responsive design. The use of flex-wrap
ensures good mobile compatibility.
Also applies to: 26-26
64-84
: Clean and semantic implementation!
The component structure is well-organized with consistent conditional rendering and proper null checks.
web/src/components/LightButton.tsx (1)
7-7
: LGTM! Clean implementation of mobile navigation support
The addition of the isMobileNavbar
prop and its implementation is clean and consistent. The changes properly handle both mobile and desktop contexts.
Also applies to: 43-43, 46-47
web/src/layout/Header/navbar/Menu/index.tsx (1)
51-53
: LGTM! Clean interface composition and prop handling
The addition of the IMenu
interface and its integration with existing interfaces is well-structured. The prop passing to LightButton
is implemented cleanly.
Also applies to: 55-55, 84-84
web/src/layout/Header/navbar/Explore.tsx (1)
32-32
: LGTM! Well-structured mobile navigation enhancements
The implementation of mobile-specific styling through the isMobileNavbar
prop is clean and consistent. The interface definition and prop handling are well-structured.
Also applies to: 62-64, 66-66, 78-78
web/src/styles/themes.ts (1)
7-7
: Verify if this color addition is necessary.
The addition of black: "#000000"
might be redundant if:
- The base component library themes (
componentsLightTheme
/componentsDarkTheme
) already include this color - The color is only used in limited places where an existing color property could be used instead
Also applies to: 56-56
✅ Verification successful
The black
color property is necessary and correctly used
The verification shows that:
- The
theme.black
color itself isn't directly used, but its derivativeblackLowOpacity
(which uses the same hex value with opacity) is used in multiple components:- Header/navbar
- Overlay component
- DesktopHeader
The color serves as a base for the blackLowOpacity
variable (#00000080
), making it a foundational color that should be explicitly defined in the theme rather than relying on potential inherited values from the component library.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check if the black color is already defined in the component library
# and where the new black color is being used
# Search for black color usage in the codebase
rg -B 2 -A 2 'theme\.black'
# Search for potential hardcoded #000000 values that could be replaced
rg -B 2 -A 2 '#000000'
Length of output: 3853
web/src/pages/Courts/CourtDetails/Stats.tsx (2)
238-250
: LGTM! Well-structured stat component with clear user guidance
The implementation includes a helpful tooltip and proper number formatting.
339-346
: Verify null safety in the mapping function
The code assumes coinIds[coinId!]
will always be valid.
Consider adding a type guard:
-const coinPrice = !isUndefined(pricesData) ? pricesData[coinIds[coinId!]]?.price : undefined;
+const coinPrice = !isUndefined(pricesData) && coinId !== undefined ? pricesData[coinIds[coinId]]?.price : undefined;
✅ Verification successful
The non-null assertion is safe to use here
The code inspection reveals that coinId
is always defined in the timeframedStats
array with specific numeric values (0 or 1). All entries in the array have an explicit coinId
property set, making the non-null assertion operator (!
) safe to use in this context. The interface shows coinId
as optional (coinId?: number
), but the actual implementation always provides it.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check if coinId is always defined in timeframedStats
ast-grep --pattern 'const timeframedStats: ITimeframedStat[] = [
$$$
{
$$$
coinId: $_,
$$$
}
$$$
]'
Length of output: 121
Script:
#!/bin/bash
# Let's try to find the timeframedStats definition with a simpler pattern
rg "timeframedStats.*=" -A 20
Length of output: 3335
Script:
#!/bin/bash
# Let's also check the interface definition
rg "interface ITimeframedStat"
Length of output: 180
Script:
#!/bin/bash
# Check for any usage of coinId in the file
rg "coinId" "web/src/pages/Courts/CourtDetails/Stats.tsx"
Length of output: 742
web/src/components/Verdict/Answer.tsx (1)
6-12
: LGTM! Clean and responsive layout implementation
The Container component implements a flexible and responsive layout with proper spacing. The implementation handles both answer present and absent cases well.
Also applies to: 32-37
web/src/components/Verdict/VerdictBanner.tsx (1)
10-10
: Verify the fixed margin impact across screen sizes
The change from a responsive margin (16-24px) to a fixed 8px might affect the visual hierarchy and spacing on larger screens. Consider if this reduction in margin is intentional and test across different viewport sizes.
web/src/components/DisputeView/DisputeInfo/DisputeInfoCard.tsx (2)
56-56
: LGTM! Clean props interface update
The removal of court-related props simplifies the component interface while maintaining type safety.
Line range hint 56-65
: Verify the impact of removed court functionality
The removal of court-related functionality might affect features depending on this information. Let's verify there are no remaining references to the removed props.
web/src/components/DisputeView/DisputeInfo/DisputeInfoList.tsx (1)
33-36
: LGTM: StyledField implementation
The styled component implementation follows best practices by extending the Field component and providing flexible styling options.
web/src/components/DisputeView/DisputeInfo/index.tsx (1)
79-79
: LGTM: Simplified court display logic
The simplified condition for displaying court information improves code readability while maintaining the same functionality.
web/src/components/Verdict/FinalDecision.tsx (2)
33-35
: LGTM: Improved responsive layout
The changes to JuryContainer
enhance the component's responsive behavior by:
- Using row layout with wrap support for better space utilization
- Properly aligning items in the center
51-51
: LGTM: Consistent spacing using responsiveSize
Good use of responsiveSize
utility for dynamic margin scaling between 16px and 24px based on viewport size.
web/src/pages/Courts/CourtDetails/StakePanel/index.tsx (1)
16-16
: LGTM! Verify SimulatorPopup to Simulator rename impact.
The component rename from SimulatorPopup to Simulator is implemented correctly here.
Let's verify no remaining references to SimulatorPopup exist:
Also applies to: 102-102
✅ Verification successful
Component rename from SimulatorPopup to Simulator is complete
The verification confirms that the rename was done correctly and completely:
- All references now use "Simulator" instead of "SimulatorPopup"
- The component is properly defined in
StakePanel/Simulator/index.tsx
- No lingering references to "SimulatorPopup" exist in the codebase
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for any remaining references to SimulatorPopup
# Test: Search for SimulatorPopup. Expect: No results as component was renamed.
rg -i "simulatorpopup"
Length of output: 22
Script:
#!/bin/bash
# Let's try a more thorough search for any references to SimulatorPopup
# 1. Search for files containing "simulator" to understand the scope
fd -t f -e tsx -e ts -e js -e jsx | xargs rg -i "simulator"
# 2. Check git history for the rename to ensure completeness
git log -p --all -S "SimulatorPopup" --since="1 month ago"
# 3. Look for any potential component definitions
ast-grep --pattern 'const SimulatorPopup = $_'
Length of output: 2184
web/src/pages/Courts/CourtDetails/index.tsx (2)
41-41
: LGTM! Style improvements enhance visual hierarchy.
The increased margin-bottom for CourtHeader and reduced gap in CourtInfo create better visual spacing and hierarchy.
Also applies to: 49-49
90-90
: Verify the breadcrumb visibility logic change.
The new breadcrumb visibility logic (items.length > 1 && items[0]?.value !== 1
) appears to hide navigation for the top-level court. While this makes sense, we should ensure this doesn't affect user navigation expectations.
Let's verify the court hierarchy structure:
Also applies to: 104-104
✅ Verification successful
Let me gather more specific information about the court hierarchy and breadcrumb implementation.
Let me check the complete breadcrumb implementation and court path logic to understand the navigation flow better.
Let me check the court path utility implementation to understand how the hierarchy is constructed.
Based on the code analysis, I can now provide a final response about the breadcrumb visibility logic.
The breadcrumb visibility logic is correctly implemented and safe to use
The implementation shows that:
- The breadcrumb is hidden only when there's a single item (no hierarchy) or when viewing the root court (id=1)
- The
getCourtsPath
utility correctly builds the court hierarchy path by recursively traversing the court tree - The breadcrumb items are properly constructed from the court path, preserving the navigation structure
This change maintains proper navigation while avoiding redundant breadcrumbs for top-level views, which is a good UX practice.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check court hierarchy implementation
# Test: Search for court hierarchy related code to understand the structure
ast-grep --pattern 'interface $interface {
$$$
id: $type
$$$
}'
# Also check for any court-related tests
rg -l "court.*test"
Length of output: 1994
Script:
#!/bin/bash
# Check the court details component and breadcrumb implementation
rg -A 5 "items\s*=\s*\[\]" web/src/pages/Courts/CourtDetails/
# Look for court hierarchy related code
ast-grep --pattern 'const $var = useParams<{ courtId: string }>();'
# Check for any court navigation related components
rg -l "Breadcrumb|breadcrumb"
Length of output: 603
Script:
#!/bin/bash
# Get the complete context of breadcrumb implementation
rg -B 10 -A 10 "const items = \[\]" web/src/pages/Courts/CourtDetails/index.tsx
# Check for courtPath implementation
ast-grep --pattern 'const courtPath = $$$'
# Look for any court navigation related hooks or utils
rg -l "useCourt|useCourtPath|getCourtPath"
Length of output: 1496
Script:
#!/bin/bash
# Find and check the getCourtsPath implementation
rg -A 20 "getCourtsPath"
# Check the court tree hook implementation
rg -A 10 "useCourtTree" web/src/hooks/queries/useCourtTree.ts
# Look for any breadcrumb navigation components
rg -A 5 "Breadcrumb" web/src/components/
Length of output: 3896
web/src/pages/Courts/CourtDetails/StakePanel/Simulator/index.tsx (2)
117-120
: LGTM! Interface rename and definition are appropriate.
The interface rename from ISimulatorPopup
to ISimulator
better reflects the component's purpose, and the props are well-typed.
Line range hint 213-269
: Well-structured rendering logic with good UX considerations.
The simulator items implementation is clean with:
- Clear tooltips for complex concepts
- Appropriate loading states
- Good handling of edge cases (zero amount)
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.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (1)
web/src/components/DisputePreview/DisputeContext.tsx (1)
74-74
: Consider enhancing accessibility for content sectionsWhile the implementation is functionally correct, consider adding ARIA attributes to improve accessibility:
- Add
aria-label
to the markdown sections to describe their purpose- Ensure error messages are properly announced to screen readers
Example implementation:
- <ReactMarkdown>{disputeDetails?.question}</ReactMarkdown> + <div aria-label="Dispute Question"> + <ReactMarkdown>{disputeDetails?.question}</ReactMarkdown> + </div> - <ReactMarkdown>{disputeDetails?.description}</ReactMarkdown> + <div aria-label="Dispute Description"> + <ReactMarkdown>{disputeDetails?.description}</ReactMarkdown> + </div> - <AnswersHeader>Voting Options</AnswersHeader> + <AnswersHeader aria-label="Available voting options">Voting Options</AnswersHeader>Also applies to: 77-78, 87-87
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (1)
web/src/components/DisputePreview/DisputeContext.tsx
(4 hunks)
🔇 Additional comments (2)
web/src/components/DisputePreview/DisputeContext.tsx (2)
30-31
: LGTM: Styling adjustment for consistent spacing
The margin adjustment helps maintain consistent spacing in the component.
45-47
: LGTM: Clean styled component implementation
The new AnswersHeader
styled component follows the established pattern of zero margins and uses semantic HTML (h3).
Code Climate has analyzed commit 6e5113c and detected 10 issues on this pull request. Here's the issue category breakdown:
View more on Code Climate. |
Quality Gate passedIssues Measures |
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.
lgtm
PR-Codex overview
This PR focuses on enhancing the UI components and functionality of the courts and disputes sections in the application. It includes styling adjustments, refactoring components, and improving user feedback.
Detailed summary
gap
values in various styled components.SimulatorPopup
toSimulator
with adjustments in props and calculations.black
color to the theme.AnswerDisplay
component with better layout and styling.unbeautifyStatNumber
function for number formatting.Stats
component to include subtext with dynamic values.Policies
component layout for better presentation.Summary by CodeRabbit
Release Notes
New Features
black
color property to both light and dark themes.Improvements
Bug Fixes
Style
Chores