Skip to content

Frontend milestone #52

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

Merged
merged 128 commits into from
Nov 7, 2024
Merged

Frontend milestone #52

merged 128 commits into from
Nov 7, 2024

Conversation

ken-zlai
Copy link
Contributor

@ken-zlai ken-zlai commented Oct 28, 2024

Summary

Lots of changes here. Here is a PR walkthrough video and a summary:

  • Custom chart zoom functionality (click and drag)
  • Sticky header w/ controls shows when you show past the model drift chart section
  • Use geist font throughout app (and monospace version for numbers)
  • Charts should fill full width on resize of window
  • Start to match UI/typography
  • Sidebar w/ charts using local sample data (percentiles, now vs baseline)
  • Date range selector w/ calendar picker

Checklist

  • Added Unit Tests
  • Covered by existing CI
  • Integration tested
  • Documentation update

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a customizable date range selection component.
    • Added new components: DriftSkewToggle, DateRangeSelector, PageHeader, and various calendar-related components.
    • Enhanced navigation with icons for improved user experience.
    • Implemented a reset zoom button for chart interactions.
  • Improvements

    • Updated typography with new font options and sizes.
    • Enhanced chart rendering logic for better data visualization.
    • Improved layout and structure for better usability in observability pages.
  • Bug Fixes

    • Adjusted padding and layout for table and separator components.
    • Fixed issues with date range handling in observability features.
  • Documentation

    • Updated internal documentation to reflect new components and features.

Copy link

coderabbitai bot commented Oct 28, 2024

Walkthrough

The pull request includes numerous changes across various files in the frontend codebase. Key modifications involve updates to the package.json dependencies, the introduction of new components for UI elements like date range selectors and toggle buttons, and enhancements to existing components. Additionally, new types and utility functions are added for better handling of date ranges and feature responses. The Tailwind CSS configuration is updated to include new font families and sizes, improving typography options throughout the application.

Changes

File Path Change Summary
frontend/package.json Added new dependencies (@internationalized/date, bits-ui, svelte-hero-icons, svelte-intersection-observer, svelte-radix); updated svelte version; removed bits-ui and svelte-radix from dependencies.
frontend/src/app.css Added font-face declarations for "Geist" and "Geist Mono".
frontend/src/lib/api/api.ts Updated getModelTimeseries function parameter from id to name; added getFeatureTimeseries function.
frontend/src/lib/components/BreadcrumbNav/BreadcrumbNav.svelte Updated imports and props to allow for customizable class names; modified separator rendering.
frontend/src/lib/components/CollapsibleSection/CollapsibleSection.svelte Restructured props and layout; added new optional header content props.
frontend/src/lib/components/DateRangeSelector/DateRangeSelector.svelte Introduced a new date range selection component.
frontend/src/lib/components/DriftSkewToggle/DriftSkewToggle.svelte Added a new toggle component for 'drift' and 'skew' states.
frontend/src/lib/components/EChart/EChart.svelte Added properties for custom zoom and dimensions; updated chart options.
frontend/src/lib/components/NavigationBar/NavigationBar.svelte Updated icon usage and modified navItems structure.
frontend/src/lib/components/PageHeader/PageHeader.svelte Introduced a new page header component.
frontend/src/lib/components/ResetZoomButton/ResetZoomButton.svelte Added a new button component for resetting zoom.
frontend/src/lib/components/SplitView/SplitView.svelte Updated icon implementation for closing sidebar.
frontend/src/lib/components/ui/calendar/*.svelte Introduced various calendar-related components, including cells, days, grids, and headers.
frontend/src/lib/constants/date-ranges.ts Added new constants and a function for handling date ranges.
frontend/src/lib/types/Model/Model.ts Updated Model type structure and introduced new types for feature responses.
frontend/src/lib/util/date-ranges.ts Added parseDateRangeParams function for handling URL parameters.
frontend/src/routes/+layout.svelte Enhanced navigation items with icons; adjusted layout classes.
frontend/src/routes/models/+page.svelte Added new UI components and modified layout for model display.
frontend/src/routes/models/[slug]/observability/+page.server.ts Simplified date range handling in the load function.
frontend/src/routes/models/[slug]/observability/+page.svelte Enhanced observability features with new state management and UI components.
frontend/tailwind.config.js Updated font families and added new font sizes to the Tailwind configuration.

Possibly related PRs

  • Frontend tests #32: This PR introduces unit tests for the API, which may indirectly relate to the changes in the main PR that involve modifications to dependencies and functionality in the frontend.
  • Frontend 8/14 milestone #45: This PR includes extensive modifications to the +page.svelte component, which may relate to the changes in the main PR regarding the addition of new dependencies and updates to existing components.
  • Frontend update model type #49: This PR updates the Model type and related components, which could be relevant to the changes in the main PR that involve updates to dependencies and potential impacts on type definitions.

Suggested reviewers

  • piyush-zlai
  • nikhil-zlai

Poem

In the garden of code, we hop and play,
New components bloom, brightening the day.
With toggles and charts, our features expand,
A rabbit's delight, in this code-laden land! 🐇✨
Fonts dance in the air, as styles take flight,
Together we build, from morning till night!


🪧 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 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.

@ken-zlai ken-zlai changed the title Frontend 8/18 milestone Frontend milestone Oct 28, 2024
Copy link

@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.

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.

🛑 Comments failed to post (52)
frontend/src/lib/util/event.ts (2)

1-1: ⚠️ Potential issue

Fix spelling error in function name: "Propogation" → "Propagation"

The function name contains a typo that should be corrected for consistency with the standard DOM API.

Apply this diff to fix the spelling:

-export function stopPropogation(event: Event) {
+export function stopPropagation(event: Event) {
📝 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 function stopPropagation(event: Event) {

1-3: 💡 Codebase verification

🛠️ Refactor suggestion

Function has typo and limited usage - consider fixing and inlining

The function stopPropogation (note the typo: "Propogation" instead of "Propagation") is only used in one place in CollapsibleSection.svelte for a click event. Given this:

  1. The function name has a spelling error
  2. It's only used once in a click event context
  3. It's a simple one-line wrapper around the native method

Recommend either:

  • Fix the typo and rename to stopPropagation if keeping the utility
  • Or preferably, remove the utility and use the native event.stopPropagation() directly in CollapsibleSection.svelte
🔗 Analysis chain

Consider improving type safety and function necessity

A few suggestions for improvement:

  1. Consider using more specific event types based on usage context (e.g., MouseEvent, KeyboardEvent, etc.) to provide better type safety.
  2. Since this is a thin wrapper around the native stopPropagation() method, consider whether this utility function adds enough value to justify its existence. If it's only used in a few places, using the native method directly might be clearer.

Example of a more type-safe implementation:

export function stopPropagation<T extends Event>(event: T): void {
  event.stopPropagation();
}

Let's check how this function is being used across the codebase:


Let me search for actual usage of this function in the codebase to better understand its usage context.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usage of stopPropogation to determine if specific event types are commonly used
rg -A 2 "stopPropogation\(" 

Length of output: 198


Script:

#!/bin/bash
# Search for imports and usage of stopPropogation
rg "stopPropogation" -B 2 -A 2

Length of output: 1296

frontend/src/lib/components/ResetZoomButton/ResetZoomButton.svelte (1)

8-11: 🛠️ Refactor suggestion

Enhance accessibility and component composability.

The button implementation could benefit from improved accessibility and more flexible styling options.

Consider these improvements:

-<Button on:click={onClick} variant="outline" class="mr-4">
-	<Icon src={ArrowUturnLeft} micro size="16" class="mr-2" />
+<Button
+	on:click={onClick}
+	variant="outline"
+	aria-label="Reset zoom level to default"
+	class={$$props.class}
+>
+	<Icon
+		src={ArrowUturnLeft}
+		micro
+		size="var(--icon-size, 16px)"
+		class="mr-2"
+	/>
 	Reset Zoom
 </Button>

Changes:

  1. Added descriptive aria-label
  2. Moved margin class to be controlled by parent component
  3. Made icon size configurable via CSS variable
📝 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.

<Button
	on:click={onClick}
	variant="outline"
	aria-label="Reset zoom level to default"
	class={$$props.class}
>
	<Icon
		src={ArrowUturnLeft}
		micro
		size="var(--icon-size, 16px)"
		class="mr-2"
	/>
	Reset Zoom
</Button>
frontend/src/lib/components/ui/calendar/calendar-grid-head.svelte (1)

11-13: 🛠️ Refactor suggestion

Consider adding template type checking.

The component template looks good, but could benefit from TypeScript template checking for better type safety.

Add the svelte:options tag at the top of the file:

+<svelte:options strictEvents />

<script lang="ts">

This will enable stricter type checking in the template, helping catch potential type errors during development.

Committable suggestion was skipped due to low confidence.

frontend/src/lib/components/ui/table/table-cell.svelte (1)

13-13: 💡 Codebase verification

Padding inconsistency found between table-cell and table-head components

The review comment mentioned alignment with table-head.svelte, but the verification reveals an inconsistency:

  • table-cell.svelte uses p-3 (padding on all sides)
  • table-head.svelte uses px-3 (padding only on left/right)

This creates an inconsistent vertical spacing between header and cell content. Consider either:

  • Using p-3 in table-head.svelte to match table-cell.svelte
  • Using px-3 in table-cell.svelte to match table-head.svelte
🔗 Analysis chain

Verify visual consistency with related table components.

The padding increase from p-2 to p-3 aligns with similar changes in table-head.svelte. The implementation looks good.

Let's verify consistent padding across related table components:


The previous result only showed which files contain padding classes, but we need to see the actual values to verify consistency. Let's also check for any other table-related components that might have padding classes but in a different format.


The search results show that only table-cell.svelte has padding classes, but we need to verify table-head.svelte since it was specifically mentioned in the context as having similar changes. We should also check what other table components exist to ensure we're not missing anything.


We need to check all table components to ensure padding consistency since we see that table-head.svelte uses px-3 (horizontal padding) instead of p-3 (all-around padding). Let's verify the padding patterns across all table components to make a complete assessment.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check padding classes in related table components
# Expected: All table components should use p-3 consistently

echo "Checking padding classes in table components..."
rg -l 'p-[2-4].*align-middle' frontend/src/lib/components/ui/table/

Length of output: 229


Script:

#!/bin/bash
# Let's check the actual padding values in all table-related components
echo "Checking all padding-related classes in table components..."
rg -A 2 'p-[2-4].*align-middle|align-middle.*p-[2-4]' frontend/src/lib/components/ui/table/

Length of output: 493


Script:

#!/bin/bash
# Check for any other padding classes in table components
echo "Checking for other padding patterns in table components..."
rg -A 2 'padding|p-\d' frontend/src/lib/components/ui/table/

Length of output: 460


Script:

#!/bin/bash
# Let's check the content of table-head.svelte since it was mentioned in the context
echo "Checking table-head.svelte content..."
cat frontend/src/lib/components/ui/table/table-head.svelte

# Also check for any other table-related components
echo -e "\nListing all table-related components..."
ls -la frontend/src/lib/components/ui/table/

Length of output: 1440


Script:

#!/bin/bash
# Let's check the content of all table components for padding-related classes
echo "Checking content of all table components for padding..."
for file in frontend/src/lib/components/ui/table/table-*.svelte; do
    echo -e "\n=== $file ==="
    cat "$file"
done

Length of output: 4872

frontend/src/lib/components/ui/calendar/calendar-grid.svelte (1)

11-13: 🛠️ Refactor suggestion

Consider adding type-safe slots.

While the implementation is functional, you could improve type safety by defining the expected slot content type.

 <script lang="ts">
 	import { Calendar as CalendarPrimitive } from 'bits-ui';
 	import { cn } from '$lib/utils.js';
 
 	type $$Props = CalendarPrimitive.GridProps;
+	interface $$Slots {
+		default: {};
+	}
 
 	let className: $$Props['class'] = undefined;
 	export { className as class };
 </script>
📝 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.

<script lang="ts">
	import { Calendar as CalendarPrimitive } from 'bits-ui';
	import { cn } from '$lib/utils.js';

	type $$Props = CalendarPrimitive.GridProps;
	interface $$Slots {
		default: {};
	}

	let className: $$Props['class'] = undefined;
	export { className as class };
</script>

<CalendarPrimitive.Grid class={cn('w-full border-collapse space-y-1', className)} {...$$restProps}>
	<slot />
</CalendarPrimitive.Grid>
frontend/src/lib/components/ui/range-calendar/range-calendar-grid-head.svelte (1)

11-13: 🛠️ Refactor suggestion

Consider enhancing accessibility attributes.

While the component works correctly, consider adding ARIA attributes to improve accessibility for screen readers.

-<RangeCalendarPrimitive.GridHead class={cn(className)} {...$$restProps}>
+<RangeCalendarPrimitive.GridHead 
+  class={cn(className)} 
+  role="row"
+  aria-label="Calendar header"
+  {...$$restProps}
+>
📝 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.

<RangeCalendarPrimitive.GridHead 
  class={cn(className)} 
  role="row"
  aria-label="Calendar header"
  {...$$restProps}
>
	<slot />
</RangeCalendarPrimitive.GridHead>
frontend/src/lib/components/ui/calendar/calendar-months.svelte (1)

11-16: 🛠️ Refactor suggestion

Enhance accessibility with ARIA attributes and semantic structure.

Consider adding appropriate ARIA attributes and roles to improve accessibility, especially since this is a calendar-related component.

 <div
+	role="group"
+	aria-label="Calendar months"
 	class={cn('mt-4 flex flex-col space-y-4 sm:flex-row sm:space-x-4 sm:space-y-0', className)}
 	{...$$restProps}
 >
 	<slot />
 </div>
📝 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.

<div
	role="group"
	aria-label="Calendar months"
	class={cn('mt-4 flex flex-col space-y-4 sm:flex-row sm:space-x-4 sm:space-y-0', className)}
	{...$$restProps}
>
	<slot />
</div>
frontend/src/lib/components/ui/calendar/calendar-head-cell.svelte (1)

11-16: 🛠️ Refactor suggestion

Consider using Tailwind's text size utilities.

Instead of hardcoding the text size to [0.8rem], consider using Tailwind's text size utilities (e.g., text-xs) for better consistency with the design system.

 <CalendarPrimitive.HeadCell
-	class={cn('text-muted-foreground w-8 rounded-md text-[0.8rem] font-normal', className)}
+	class={cn('text-muted-foreground w-8 rounded-md text-xs font-normal', className)}
 	{...$$restProps}
 >
 	<slot />
 </CalendarPrimitive.HeadCell>
📝 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.

<CalendarPrimitive.HeadCell
	class={cn('text-muted-foreground w-8 rounded-md text-xs font-normal', className)}
	{...$$restProps}
>
	<slot />
</CalendarPrimitive.HeadCell>
frontend/src/lib/components/ui/range-calendar/range-calendar-header.svelte (1)

13-13: 🛠️ Refactor suggestion

Consider adding type safety for rest props.

The spread operator usage with $$restProps could benefit from type safety to prevent passing invalid props to the underlying component.

Add type checking for rest props:

<script lang="ts">
	import { RangeCalendar as RangeCalendarPrimitive } from 'bits-ui';
	import { cn } from '$lib/utils.js';

	type $$Props = RangeCalendarPrimitive.HeaderProps;
+	// Ensure type safety for rest props
+	interface $$RestProps extends Omit<$$Props, keyof $$Props> {}

	let className: $$Props['class'] = undefined;
	export { className as class };
</script>

Committable suggestion was skipped due to low confidence.

frontend/src/lib/components/ui/range-calendar/range-calendar-head-cell.svelte (1)

5-9: 🛠️ Refactor suggestion

Consider enhancing type safety for the className prop.

While the current implementation works, you could make it more type-safe by explicitly defining the type for className.

Consider this improvement:

-let className: $$Props['class'] = undefined;
+let className: $$Props['class'] | undefined = undefined;

This makes it explicit that the prop can be undefined, improving type safety and code readability.

📝 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.

	type $$Props = RangeCalendarPrimitive.HeadCellProps;

	let className: $$Props['class'] | undefined = undefined;
	export { className as class };
</script>
frontend/src/lib/components/ui/range-calendar/range-calendar-heading.svelte (1)

13-13: 🛠️ Refactor suggestion

Consider extracting the default classes to a constant.

The hardcoded classes could be moved to a constant for better maintainability and reusability.

+const defaultClass = 'text-sm font-medium';
+
 <RangeCalendarPrimitive.Heading
 	let:headingValue
-	class={cn('text-sm font-medium', className)}
+	class={cn(defaultClass, className)}

Committable suggestion was skipped due to low confidence.

frontend/src/lib/components/ui/calendar/calendar-cell.svelte (1)

5-10: 🛠️ Refactor suggestion

Consider adding type constraints for better type safety.

While the current implementation is correct, you could enhance type safety by:

  1. Making the date prop required
  2. Adding JSDoc comments for better documentation

Consider applying these changes:

 type $$Props = CalendarPrimitive.CellProps;

-export let date: $$Props['date'];
+/** The date to be rendered in the cell */
+export let date: $$Props['date'];
+$: if (!date) throw new Error('date is required');
📝 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.

	type $$Props = CalendarPrimitive.CellProps;

	/** The date to be rendered in the cell */
	export let date: $$Props['date'];
	$: if (!date) throw new Error('date is required');
	let className: $$Props['class'] = undefined;
	export { className as class };
</script>
frontend/src/lib/components/PageHeader/PageHeader.svelte (4)

19-22: ⚠️ Potential issue

Use Svelte's event handling syntax

The onclick attribute should use Svelte's event handling syntax on:click.

-<Button variant="outline" onclick={openChronon}>
+<Button variant="outline" on:click={openChronon}>
   <Icon src={BookOpen} micro size="16" class="mr-2" />
   Learn
 </Button>
📝 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.

		<Button variant="outline" on:click={openChronon}>
			<Icon src={BookOpen} micro size="16" class="mr-2" />
			Learn
		</Button>

8-10: 🛠️ Refactor suggestion

Move URL to configuration and improve function name

The hardcoded URL should be moved to a configuration file for better maintainability. Also, the function name could be more descriptive.

-function openChronon() {
-  window.open('https://chronon.ai/', '_blank');
+import { DOCS_URL } from '$lib/config';
+
+function openDocumentation() {
+  window.open(DOCS_URL, '_blank');
}

Committable suggestion was skipped due to low confidence.


13-24: 🛠️ Refactor suggestion

Consider making the component more configurable

The component could benefit from additional customization options:

  1. Icon size could be a prop
  2. Spacing classes (mb-6, gap-4) could be made configurable
  3. The "Learn" text could be made configurable for i18n support

Here's a suggested implementation:

<script lang="ts">
  import type { Snippet } from 'svelte';
  import Button from '$lib/components/ui/button/button.svelte';
  import { Icon, BookOpen } from 'svelte-hero-icons';

  let {
    title,
    children = undefined,
+   iconSize = "16",
+   spacing = "mb-6",
+   gapSize = "gap-4",
+   learnButtonText = "Learn"
  }: {
    title: string;
    children?: Snippet;
+   iconSize?: string;
+   spacing?: string;
+   gapSize?: string;
+   learnButtonText?: string;
  } = $props();
</script>

-<div class="flex justify-between items-center mb-6">
+<div class="flex justify-between items-center {spacing}">
  <h1 class="text-3xl">{title}</h1>
-  <div class="flex items-center gap-4">
+  <div class="flex items-center {gapSize}">
    {#if children}
      {@render children()}
    {/if}
    <Button variant="outline" on:click={openChronon}>
-     <Icon src={BookOpen} micro size="16" class="mr-2" />
+     <Icon src={BookOpen} micro size={iconSize} class="mr-2" />
-     Learn
+     {learnButtonText}
    </Button>
  </div>
</div>
📝 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.

<script lang="ts">
  import type { Snippet } from 'svelte';
  import Button from '$lib/components/ui/button/button.svelte';
  import { Icon, BookOpen } from 'svelte-hero-icons';

  let {
    title,
    children = undefined,
    iconSize = "16",
    spacing = "mb-6",
    gapSize = "gap-4",
    learnButtonText = "Learn"
  }: {
    title: string;
    children?: Snippet;
    iconSize?: string;
    spacing?: string;
    gapSize?: string;
    learnButtonText?: string;
  } = $props();
</script>

<div class="flex justify-between items-center {spacing}">
	<h1 class="text-3xl">{title}</h1>
	<div class="flex items-center {gapSize}">
		{#if children}
			{@render children()}
		{/if}
		<Button variant="outline" on:click={openChronon}>
			<Icon src={BookOpen} micro size={iconSize} class="mr-2" />
			{learnButtonText}
		</Button>
	</div>
</div>

1-24: 💡 Codebase verification

Based on the gathered information, I can now provide the final response:

Add aria-label to Learn button for better accessibility

The PageHeader component is used consistently across the models pages, but the Learn button lacks proper accessibility attributes. To improve accessibility:

  • Add aria-label="Learn more at Chronon" to the Learn button in frontend/src/lib/components/PageHeader/PageHeader.svelte
  • Consider adding a more descriptive tooltip using the native HTML title attribute

The component's usage and implementation are otherwise appropriate, with proper heading hierarchy (h1) and consistent styling patterns.

🔗 Analysis chain

Verify accessibility and component usage

Let's verify the component's implementation and usage across the codebase.


Let me try different commands since the previous ones failed due to unrecognized file type.


Let me check the actual usage of PageHeader in the files to understand the implementation better.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check component usage and potential accessibility issues

# Test 1: Find usage of PageHeader component
echo "Checking PageHeader usage:"
rg -l "PageHeader" --type svelte

# Test 2: Verify if similar header patterns exist
echo -e "\nChecking for similar header patterns:"
rg -A 2 'class="text-3xl"' --type svelte

# Test 3: Check for potential accessibility issues with the button
echo -e "\nChecking for aria-label usage with buttons:"
ast-grep --pattern 'Button variant="outline"'

Length of output: 442


Script:

#!/bin/bash
# Description: Check component usage and potential accessibility issues

# Test 1: Find usage of PageHeader component
echo "Checking PageHeader usage:"
rg -l "PageHeader"

# Test 2: Verify if similar header patterns exist
echo -e "\nChecking for similar header patterns:"
rg -A 2 'text-3xl'

# Test 3: Check for potential accessibility issues with the button
echo -e "\nChecking button implementations:"
rg -A 2 'variant="outline"'

Length of output: 2498


Script:

#!/bin/bash
# Check how PageHeader is being used in the identified files
echo "PageHeader usage in models/+page.svelte:"
rg -A 5 "PageHeader" frontend/src/routes/models/+page.svelte

echo -e "\nPageHeader usage in models/[slug]/observability/+page.svelte:"
rg -A 5 "PageHeader" frontend/src/routes/models/[slug]/observability/+page.svelte

# Check if there are any aria-labels used with the Learn button in other components
echo -e "\nChecking for aria-label usage with Learn buttons:"
rg -B 2 -A 2 '"Learn"'

Length of output: 1620

frontend/src/lib/components/ui/calendar/calendar-prev-button.svelte (1)

14-27: 🛠️ Refactor suggestion

Consider making styling values more configurable.

While the implementation is functional, consider extracting hardcoded values into props for better customization:

  • opacity values (50/100)
  • icon dimensions (h-4 w-4)
  • button dimensions (h-7 w-7)

Here's a suggested refactor to improve customization:

<script lang="ts">
	import { Calendar as CalendarPrimitive } from 'bits-ui';
	import ChevronLeft from 'svelte-radix/ChevronLeft.svelte';
	import { buttonVariants } from '$lib/components/ui/button/index.js';
	import { cn } from '$lib/utils.js';

	type $$Props = CalendarPrimitive.PrevButtonProps & {
+		buttonSize?: string;
+		iconSize?: string;
+		defaultOpacity?: string;
	};
	type $$Events = CalendarPrimitive.PrevButtonEvents;

	let className: $$Props['class'] = undefined;
+	export let buttonSize = 'h-7 w-7';
+	export let iconSize = 'h-4 w-4';
+	export let defaultOpacity = 'opacity-50';
	export { className as class };
</script>

<CalendarPrimitive.PrevButton
	on:click
	class={cn(
		buttonVariants({ variant: 'outline' }),
-		'h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100',
+		`${buttonSize} bg-transparent p-0 ${defaultOpacity} hover:opacity-100`,
		className
	)}
	{...$$restProps}
	let:builder
>
	<slot {builder}>
-		<ChevronLeft class="h-4 w-4" />
+		<ChevronLeft class={iconSize} />
	</slot>
</CalendarPrimitive.PrevButton>
📝 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.

<script lang="ts">
	import { Calendar as CalendarPrimitive } from 'bits-ui';
	import ChevronLeft from 'svelte-radix/ChevronLeft.svelte';
	import { buttonVariants } from '$lib/components/ui/button/index.js';
	import { cn } from '$lib/utils.js';

	type $$Props = CalendarPrimitive.PrevButtonProps & {
		buttonSize?: string;
		iconSize?: string;
		defaultOpacity?: string;
	};
	type $$Events = CalendarPrimitive.PrevButtonEvents;

	let className: $$Props['class'] = undefined;
	export let buttonSize = 'h-7 w-7';
	export let iconSize = 'h-4 w-4';
	export let defaultOpacity = 'opacity-50';
	export { className as class };
</script>

<CalendarPrimitive.PrevButton
	on:click
	class={cn(
		buttonVariants({ variant: 'outline' }),
		`${buttonSize} bg-transparent p-0 ${defaultOpacity} hover:opacity-100`,
		className
	)}
	{...$$restProps}
	let:builder
>
	<slot {builder}>
		<ChevronLeft class={iconSize} />
	</slot>
</CalendarPrimitive.PrevButton>
frontend/src/lib/components/ui/calendar/calendar-next-button.svelte (1)

14-27: 🛠️ Refactor suggestion

Consider improving component flexibility and maintainability.

While the implementation is functional, we could enhance it in several ways:

Consider these improvements:

<script lang="ts">
 import { Calendar as CalendarPrimitive } from 'bits-ui';
 import ChevronRight from 'svelte-radix/ChevronRight.svelte';
 import { buttonVariants } from '$lib/components/ui/button/index.js';
 import { cn } from '$lib/utils.js';

 type $$Props = CalendarPrimitive.NextButtonProps;
 type $$Events = CalendarPrimitive.NextButtonEvents;

+interface ButtonStyles {
+  size?: string;
+  opacity?: number;
+}
+
 let className: $$Props['class'] = undefined;
+export let styles: ButtonStyles = {
+  size: '7',
+  opacity: 50
+};
 export { className as class };
</script>

<CalendarPrimitive.NextButton
 on:click
+{...$$props('click')}
 class={cn(
   buttonVariants({ variant: 'outline' }),
-  'h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100',
+  `h-${styles.size} w-${styles.size} p-0 opacity-${styles.opacity} hover:opacity-100`,
   className
 )}
 {...$$restProps}
 let:builder
>
 <slot {builder}>
-  <ChevronRight class="h-4 w-4" />
+  <ChevronRight class="h-[calc(theme(spacing.4))] w-[calc(theme(spacing.4))]" />
 </slot>
</CalendarPrimitive.NextButton>

This refactor:

  1. Makes size and opacity configurable via props
  2. Uses Tailwind's calc function for more reliable sizing
  3. Forwards all events properly using Svelte's event forwarding syntax

Committable suggestion was skipped due to low confidence.

frontend/src/lib/components/DriftSkewToggle/DriftSkewToggle.svelte (2)

16-33: 🛠️ Refactor suggestion

Enhance accessibility for the toggle group

While the implementation is visually correct, consider improving accessibility by:

  1. Adding ARIA roles and labels
  2. Supporting keyboard navigation
-<div class="flex space-x-2">
+<div
+  class="flex space-x-2"
+  role="radiogroup"
+  aria-label="View selection"
+>
   <Button
     variant={selected === 'drift' ? 'default' : 'outline'}
     size="sm"
     on:click={() => toggle('drift')}
+    role="radio"
+    aria-checked={selected === 'drift'}
   >
     <Icon src={ArrowTrendingUp} micro size="16" class="mr-2" />
     Drift
   </Button>
   <Button
     variant={selected === 'skew' ? 'default' : 'outline'}
     size="sm"
     on:click={() => toggle('skew')}
+    role="radio"
+    aria-checked={selected === 'skew'}
   >
     <Icon src={ArrowsRightLeft} micro size="16" class="mr-2" />
     Skew
   </Button>
 </div>

Also, consider adding keyboard navigation support:

<script lang="ts">
  // ... existing code ...
  
  function handleKeydown(event: KeyboardEvent) {
    if (event.key === 'ArrowRight' || event.key === 'ArrowLeft') {
      event.preventDefault();
      toggle(selected === 'drift' ? 'skew' : 'drift');
    }
  }
</script>

<div
  class="flex space-x-2"
  role="radiogroup"
  aria-label="View selection"
  on:keydown={handleKeydown}
  tabindex="0"
>
  <!-- ... existing buttons ... -->
</div>

5-9: 🛠️ Refactor suggestion

Strengthen type safety for the selected prop

The type annotation allows any string, but the component only accepts 'drift' or 'skew' values. Consider using a union type for better type safety.

 let {
   selected = $bindable('drift')
 }: {
-  selected: string;
+  selected: 'drift' | 'skew';
 } = $props();
📝 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.

	let {
		selected = $bindable('drift')
	}: {
		selected: 'drift' | 'skew';
	} = $props();
frontend/src/lib/components/ui/range-calendar/range-calendar-prev-button.svelte (1)

16-20: 🛠️ Refactor suggestion

Consider making dimensions and opacity configurable.

The button currently uses hardcoded values for:

  • Button dimensions (h-7 w-7)
  • Opacity levels (opacity-50, opacity-100)

Consider making these configurable through props to enhance component reusability across different contexts.

<script lang="ts">
	import { RangeCalendar as RangeCalendarPrimitive } from 'bits-ui';
	import ChevronLeft from 'svelte-radix/ChevronLeft.svelte';
	import { buttonVariants } from '$lib/components/ui/button/index.js';
	import { cn } from '$lib/utils.js';

	type $$Props = RangeCalendarPrimitive.PrevButtonProps & {
+		size?: string;
+		defaultOpacity?: string;
+		hoverOpacity?: string;
	};
	type $$Events = RangeCalendarPrimitive.PrevButtonEvents;

	let className: $$Props['class'] = undefined;
+	export let size = 'h-7 w-7';
+	export let defaultOpacity = 'opacity-50';
+	export let hoverOpacity = 'opacity-100';
	export { className as class };
</script>

<RangeCalendarPrimitive.PrevButton
	on:click
	class={cn(
		buttonVariants({ variant: 'outline' }),
-		'h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100',
+		`${size} bg-transparent p-0 ${defaultOpacity} hover:${hoverOpacity}`,
		className
	)}
	{...$$restProps}
	let:builder
>
📝 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.

	class={cn(
		buttonVariants({ variant: 'outline' }),
		`${size} bg-transparent p-0 ${defaultOpacity} hover:${hoverOpacity}`,
		className
	)}
frontend/src/lib/components/ui/range-calendar/range-calendar-next-button.svelte (1)

14-27: 🛠️ Refactor suggestion

Consider enhancing accessibility and customization options.

The component implementation is clean and follows good practices with event forwarding and slot flexibility. However, consider these improvements:

  1. Add an ARIA label for better accessibility
  2. Consider making the button size configurable
  3. Use CSS variables for opacity values for better theme support

Here's a suggested implementation:

 <RangeCalendarPrimitive.NextButton
 	on:click
+	aria-label="Next month"
 	class={cn(
 		buttonVariants({ variant: 'outline' }),
-		'h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100',
+		'bg-transparent p-0',
+		'[--button-size:1.75rem] h-[var(--button-size)] w-[var(--button-size)]',
+		'[--opacity-default:0.5] [--opacity-hover:1]',
+		'opacity-[var(--opacity-default)] hover:opacity-[var(--opacity-hover)]',
 		className
 	)}
 	{...$$restProps}
 	let:builder
 >
 	<slot {builder}>
 		<ChevronRight class="h-4 w-4" />
 	</slot>
 </RangeCalendarPrimitive.NextButton>
📝 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.

<RangeCalendarPrimitive.NextButton
	on:click
	aria-label="Next month"
	class={cn(
		buttonVariants({ variant: 'outline' }),
		'bg-transparent p-0',
		'[--button-size:1.75rem] h-[var(--button-size)] w-[var(--button-size)]',
		'[--opacity-default:0.5] [--opacity-hover:1]',
		'opacity-[var(--opacity-default)] hover:opacity-[var(--opacity-hover)]',
		className
	)}
	{...$$restProps}
	let:builder
>
	<slot {builder}>
		<ChevronRight class="h-4 w-4" />
	</slot>
</RangeCalendarPrimitive.NextButton>
frontend/src/lib/components/ui/range-calendar/range-calendar-cell.svelte (1)

12-21: 🛠️ Refactor suggestion

Consider extracting complex class string into constants.

The class string contains multiple complex selectors. Consider extracting these into named constants for better maintainability and reusability.

+<script lang="ts">
+  const baseClasses = 'relative p-0 text-center text-sm';
+  const focusClasses = 'focus-within:relative focus-within:z-20';
+  const selectionClasses = [
+    '[&:has([data-selected])]:bg-accent',
+    '[&:has([data-selected][data-outside-month])]:bg-accent/50',
+    'first:[&:has([data-selected])]:rounded-l-md',
+    'last:[&:has([data-selected])]:rounded-r-md',
+    '[&:has([data-selected][data-selection-end])]:rounded-r-md',
+    '[&:has([data-selected][data-selection-start])]:rounded-l-md'
+  ].join(' ');
+</script>

 <RangeCalendarPrimitive.Cell
 	{date}
 	class={cn(
-		'[&:has([data-selected])]:bg-accent [&:has([data-selected][data-outside-month])]:bg-accent/50 relative p-0 text-center text-sm focus-within:relative focus-within:z-20 first:[&:has([data-selected])]:rounded-l-md last:[&:has([data-selected])]:rounded-r-md [&:has([data-selected][data-selection-end])]:rounded-r-md [&:has([data-selected][data-selection-start])]:rounded-l-md',
+		baseClasses,
+		focusClasses,
+		selectionClasses,
 		className
 	)}
 	{...$$restProps}
 >
 	<slot />
 </RangeCalendarPrimitive.Cell>
📝 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.

<script lang="ts">
  const baseClasses = 'relative p-0 text-center text-sm';
  const focusClasses = 'focus-within:relative focus-within:z-20';
  const selectionClasses = [
    '[&:has([data-selected])]:bg-accent',
    '[&:has([data-selected][data-outside-month])]:bg-accent/50',
    'first:[&:has([data-selected])]:rounded-l-md',
    'last:[&:has([data-selected])]:rounded-r-md',
    '[&:has([data-selected][data-selection-end])]:rounded-r-md',
    '[&:has([data-selected][data-selection-start])]:rounded-l-md'
  ].join(' ');
</script>

<RangeCalendarPrimitive.Cell
	{date}
	class={cn(
		baseClasses,
		focusClasses,
		selectionClasses,
		className
	)}
	{...$$restProps}
>
	<slot />
</RangeCalendarPrimitive.Cell>
frontend/src/lib/components/ui/input/index.ts (1)

6-23: 🛠️ Refactor suggestion

Consider making less common events optional.

The type definition is comprehensive and well-organized. However, some events like wheel, paste, mousemove might not be commonly used in all input scenarios.

Consider making less common events optional to reduce implementation overhead:

export type InputEvents = {
	blur: FormInputEvent<FocusEvent>;
	change: FormInputEvent<Event>;
	click: FormInputEvent<MouseEvent>;
	focus: FormInputEvent<FocusEvent>;
	input: FormInputEvent<InputEvent>;
-	focusin: FormInputEvent<FocusEvent>;
-	focusout: FormInputEvent<FocusEvent>;
-	keydown: FormInputEvent<KeyboardEvent>;
-	keypress: FormInputEvent<KeyboardEvent>;
-	keyup: FormInputEvent<KeyboardEvent>;
-	mouseover: FormInputEvent<MouseEvent>;
-	mouseenter: FormInputEvent<MouseEvent>;
-	mouseleave: FormInputEvent<MouseEvent>;
-	mousemove: FormInputEvent<MouseEvent>;
-	paste: FormInputEvent<ClipboardEvent>;
-	wheel: FormInputEvent<WheelEvent>;
+	focusin?: FormInputEvent<FocusEvent>;
+	focusout?: FormInputEvent<FocusEvent>;
+	keydown?: FormInputEvent<KeyboardEvent>;
+	keypress?: FormInputEvent<KeyboardEvent>;
+	keyup?: FormInputEvent<KeyboardEvent>;
+	mouseover?: FormInputEvent<MouseEvent>;
+	mouseenter?: FormInputEvent<MouseEvent>;
+	mouseleave?: FormInputEvent<MouseEvent>;
+	mousemove?: FormInputEvent<MouseEvent>;
+	paste?: FormInputEvent<ClipboardEvent>;
+	wheel?: FormInputEvent<WheelEvent>;
};
📝 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 InputEvents = {
	blur: FormInputEvent<FocusEvent>;
	change: FormInputEvent<Event>;
	click: FormInputEvent<MouseEvent>;
	focus: FormInputEvent<FocusEvent>;
	input: FormInputEvent<InputEvent>;
	focusin?: FormInputEvent<FocusEvent>;
	focusout?: FormInputEvent<FocusEvent>;
	keydown?: FormInputEvent<KeyboardEvent>;
	keypress?: FormInputEvent<KeyboardEvent>;
	keyup?: FormInputEvent<KeyboardEvent>;
	mouseover?: FormInputEvent<MouseEvent>;
	mouseenter?: FormInputEvent<MouseEvent>;
	mouseleave?: FormInputEvent<MouseEvent>;
	mousemove?: FormInputEvent<MouseEvent>;
	paste?: FormInputEvent<ClipboardEvent>;
	wheel?: FormInputEvent<WheelEvent>;
};
frontend/src/lib/components/ui/separator/separator.svelte (1)

16-22: 🛠️ Refactor suggestion

Consider using CSS variables for magic numbers.

The fullWidthExtend implementation uses hardcoded values (-mx-8 and calc(100%+4rem)) which could make maintenance difficult. Consider using CSS variables for these values.

<style lang="postcss">
+:root {
+  --separator-extend-margin: 2rem;
+}
</style>

<SeparatorPrimitive.Root
	class={cn(
		'bg-border shrink-0',
		orientation === 'horizontal' ? 'h-[1px] w-full' : 'min-h-full w-[1px]',
-		fullWidthExtend && 'relative w-[calc(100%+4rem)] -mx-8',
+		fullWidthExtend && 'relative w-[calc(100%+calc(var(--separator-extend-margin)*2))] -mx-[var(--separator-extend-margin)]',
		wide && 'h-[6px] bg-background border-y border-border',
		className
	)}
📝 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.

<style lang="postcss">
:root {
  --separator-extend-margin: 2rem;
}
</style>

	class={cn(
		'bg-border shrink-0',
		orientation === 'horizontal' ? 'h-[1px] w-full' : 'min-h-full w-[1px]',
		fullWidthExtend && 'relative w-[calc(100%+calc(var(--separator-extend-margin)*2))] -mx-[var(--separator-extend-margin)]',
		wide && 'h-[6px] bg-background border-y border-border',
		className
	)}
frontend/src/lib/components/ui/range-calendar/index.ts (1)

15-30: 🛠️ Refactor suggestion

Consider exporting component types for better TypeScript integration.

For better TypeScript support, consider exporting the component types alongside the components. This would help with type inference when using these components in other parts of the application.

Add type exports if available:

import type { RangeCalendarProps } from './range-calendar.svelte';
import type { CellProps } from './range-calendar-cell.svelte';
// ... other type imports

export type {
    RangeCalendarProps,
    CellProps,
    // ... other types
};
frontend/src/lib/components/BreadcrumbNav/BreadcrumbNav.svelte (2)

11-11: 💡 Codebase verification

Icon usage pattern needs alignment in BreadcrumbNav

The verification reveals inconsistent icon styling in BreadcrumbNav.svelte compared to other components:

  • Most components use size="16" and additional classes like mr-2
  • BreadcrumbNav only uses <Icon src={Slash}> without size or styling props
  • Other components consistently use the micro prop for smaller icons
🔗 Analysis chain

Verify consistent icon usage across components

Let's verify that the Icon component usage aligns with other components in the codebase.

Also applies to: 23-23

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for consistent Icon usage pattern across components
echo "Checking Icon usage patterns..."
rg -A 1 "import.*Icon.*svelte-hero-icons" frontend/src/lib/components/
rg "Icon.*src=" frontend/src/lib/components/

Length of output: 3198


16-16: 🛠️ Refactor suggestion

Make class composition more explicit

The cn utility usage could be more explicit about the default classes being applied.

-<Breadcrumb class={cn('', className)}>
+<Breadcrumb class={cn('flex items-center space-x-2', className)}>
📝 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.

<Breadcrumb class={cn('flex items-center space-x-2', className)}>
frontend/src/lib/components/ui/input/input.svelte (1)

19-22: 🛠️ Refactor suggestion

Consider extracting Tailwind classes for better maintainability.

While the styling is comprehensive and follows best practices, the long class string could be better organized for maintainability.

Consider extracting the base classes to a constant:

<script lang="ts">
+	const baseInputClasses = [
+		'flex h-9 w-full rounded-md border bg-transparent px-3 py-1 text-sm',
+		'border-input placeholder:text-muted-foreground',
+		'shadow-sm transition-colors',
+		'file:border-0 file:bg-transparent file:text-sm file:font-medium',
+		'focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring',
+		'disabled:cursor-not-allowed disabled:opacity-50'
+	].join(' ');
</script>

<input
-	class={cn(
-		'border-input placeholder:text-muted-foreground focus-visible:ring-ring flex h-9 w-full rounded-md border bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50',
-		className
-	)}
+	class={cn(baseInputClasses, className)}

Committable suggestion was skipped due to low confidence.

frontend/src/lib/components/ui/checkbox/checkbox.svelte (1)

15-23: 🛠️ Refactor suggestion

Consider enhancing accessibility and code organization.

  1. The checkbox should be associated with a label for accessibility. Consider adding aria-label or aria-labelledby if this component is used without an HTML label.

  2. The long class string could be extracted to improve readability.

+const rootClass = 'border-primary focus-visible:ring-ring data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground peer box-content h-4 w-4 shrink-0 rounded-sm border shadow focus-visible:outline-none focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50 data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-50';

 <CheckboxPrimitive.Root
-	class={cn(
-		'border-primary focus-visible:ring-ring data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground peer box-content h-4 w-4 shrink-0 rounded-sm border shadow focus-visible:outline-none focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50 data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-50',
-		className
-	)}
+	class={cn(rootClass, className)}
+	aria-label={$$props['aria-label']}

Committable suggestion was skipped due to low confidence.

frontend/src/lib/util/date-ranges.ts (1)

32-52: ⚠️ Potential issue

Add validation and error handling for date parameters.

The function could benefit from additional validation to handle edge cases and ensure data integrity:

  1. Validate timestamp parsing
  2. Add bounds checking
  3. Handle partial parameter scenarios

Consider applying these improvements:

 export function parseDateRangeParams(searchParams: URLSearchParams) {
   const dateRangeValue = searchParams.get(DATE_RANGE_PARAM);
   const startParam = searchParams.get(DATE_RANGE_START_PARAM);
   const endParam = searchParams.get(DATE_RANGE_END_PARAM);
 
   let startTimestamp: number;
   let endTimestamp: number;
 
-  if (startParam && endParam) {
-    startTimestamp = Number(startParam);
-    endTimestamp = Number(endParam);
+  if (startParam || endParam) {
+    // Handle case where only one parameter is provided
+    if (!startParam || !endParam) {
+      throw new Error('Both start and end dates must be provided together');
+    }
+    
+    startTimestamp = Number(startParam);
+    endTimestamp = Number(endParam);
+    
+    // Validate parsed timestamps
+    if (isNaN(startTimestamp) || isNaN(endTimestamp)) {
+      throw new Error('Invalid date format provided');
+    }
+    
+    // Ensure start is before end
+    if (startTimestamp >= endTimestamp) {
+      throw new Error('Start date must be before end date');
+    }
   } else {
     [startTimestamp, endTimestamp] = getDateRange(dateRangeValue || LAST_7_DAYS);
   }

Additionally, consider adding TypeScript types for better type safety:

interface DateRangeResult {
  dateRangeValue: string;
  startTimestamp: number;
  endTimestamp: number;
}
frontend/src/lib/components/CollapsibleSection/CollapsibleSection.svelte (2)

11-11: ⚠️ Potential issue

Fix typo in prop name: 'collabsibleContent'

The prop name contains a typo: 'collabsible' should be 'collapsible'.

Apply this fix:

-		collabsibleContent,
+		collapsibleContent,
-		collabsibleContent: Snippet;
+		collapsibleContent: Snippet;

Also applies to: 17-17


36-39: ⚠️ Potential issue

Update deprecated event directive and enhance accessibility

  1. The comment svelte-ignore event_directive_deprecated suggests we're using a deprecated event syntax.
  2. The role="presentation" might not be the most appropriate choice for interactive content.

Consider these improvements:

-				<!-- svelte-ignore event_directive_deprecated -->
-				<div on:click={stopPropogation} role="presentation">
+				<div on:click|stopPropagation role="group" aria-label="Header left content">
📝 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.

				<div on:click|stopPropagation role="group" aria-label="Header left content">
					{@render headerContentLeft()}
				</div>
frontend/src/routes/+layout.svelte (1)

20-22: 🛠️ Refactor suggestion

Consider adding type safety for navigation items.

The navigation items are well-structured with semantically appropriate icons. However, consider adding a TypeScript interface to enforce the structure.

Add this type definition above the navItems:

interface NavItem {
  label: string;
  href: string;
  icon: typeof import('svelte-hero-icons').Icon;
}

const navItems: NavItem[] = [
  // ... existing items
];
frontend/src/lib/components/ui/calendar/calendar.svelte (2)

46-52: 🛠️ Refactor suggestion

Consider using CSS Grid gap instead of margin for consistent spacing.

Using margin-top for row spacing might lead to inconsistent layouts. CSS Grid's gap property would provide more reliable spacing.

-						<Calendar.GridRow class="mt-2 w-full">
+						<Calendar.GridRow class="w-full">

Add this to your CSS:

.calendar-grid {
  display: grid;
  gap: 0.5rem;
}

38-40: ⚠️ Potential issue

Avoid hard-coded string slicing for weekday names.

The current implementation arbitrarily slices weekday names to 2 characters, which might not work well for all locales or when internationalization is needed.

-								{weekday.slice(0, 2)}
+								{new Intl.DateTimeFormat(undefined, { weekday: 'narrow' }).format(weekday)}

Committable suggestion was skipped due to low confidence.

frontend/src/routes/models/+page.svelte (1)

22-37: ⚠️ Potential issue

Add accessibility attributes and implement button functionality.

While the UI layout looks clean, consider these improvements:

  1. Add click handlers for the Filter and Sort buttons
  2. Enhance accessibility with ARIA labels
  3. Add tooltips to explain button actions

Apply these changes:

 <div class="flex space-x-3 mb-4">
-    <Button variant="secondary" size="sm">
+    <Button 
+      variant="secondary" 
+      size="sm"
+      on:click={() => handleFilter()}
+      aria-label="Filter models"
+      title="Filter models list">
       <Icon src={Plus} micro size="16" class="mr-2" />
       Filter
     </Button>
-    <Button variant="secondary" size="sm">
+    <Button 
+      variant="secondary" 
+      size="sm"
+      on:click={() => handleSort()}
+      aria-label="Sort models"
+      title="Sort models list">
       <Icon src={ArrowsUpDown} micro size="16" class="mr-2" />
       Sort
     </Button>
 </div>

Committable suggestion was skipped due to low confidence.

frontend/src/lib/components/ui/sheet/index.ts (1)

41-41: 💡 Codebase verification

Looking at the search results, I can see the padding patterns across various UI components. Let me analyze the findings:

  1. Dialog component uses p-6 (dialog-content.svelte)
  2. Popover and dropdown components use p-1 for their content
  3. Badge component uses distinct horizontal/vertical padding: px-2.5 py-0.5
  4. Most interactive elements (buttons, cells) use specific padding patterns based on their use case

The sheet component's new padding (px-4 py-5) appears to be inconsistent with the dialog component (p-6), which is the most similar in terms of functionality and visual hierarchy. Since sheets and dialogs are both modal-like components that display content overlaid on the main view, they should maintain consistent spacing.

Consider maintaining consistent padding between Sheet and Dialog components

The Sheet component now uses px-4 py-5 while the Dialog component uses p-6. Since both components serve similar purposes in the UI hierarchy, they should maintain consistent spacing patterns for a more cohesive user experience.

  • Consider using p-6 in the Sheet component to match the Dialog component
  • Or update both components to use the new px-4 py-5 pattern if that's the intended design direction
🔗 Analysis chain

LGTM! Consider documenting the spacing decision.

The change from uniform padding (p-6) to distinct horizontal and vertical padding (px-4 py-5) provides finer control over the sheet's spacing. This is a good UI enhancement that allows for more precise layout control.

Let's verify if this spacing pattern is consistent with other similar components:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check spacing patterns in other UI components
# Look for similar component variants to ensure consistent spacing patterns

# Search for variant definitions with padding classes
rg -g '*.ts' -g '*.svelte' 'base.*p[xy]-[0-9]|p-[0-9]' frontend/src/lib/components/ui/

Length of output: 5140

frontend/package.json (1)

33-33: ⚠️ Potential issue

Review UI component library dependencies

Several UI-related packages have been moved to devDependencies:

  • bits-ui
  • svelte-hero-icons
  • svelte-intersection-observer
  • svelte-radix

This might cause issues in production builds as these packages are likely needed at runtime.

Move these dependencies back to the dependencies section if they are used in the runtime code:

 "devDependencies": {
-  "bits-ui": "^0.21.16",
-  "svelte-hero-icons": "^5.2.0",
-  "svelte-intersection-observer": "^1.0.0",
-  "svelte-radix": "^1.1.1",
 },
 "dependencies": {
+  "bits-ui": "^0.21.16",
+  "svelte-hero-icons": "^5.2.0",
+  "svelte-intersection-observer": "^1.0.0",
+  "svelte-radix": "^1.1.1",
 }

Also applies to: 43-45

frontend/src/lib/components/ui/range-calendar/range-calendar.svelte (3)

29-33: ⚠️ Potential issue

Enhance accessibility for calendar navigation.

The header navigation buttons should have proper ARIA labels for better screen reader support.

 <RangeCalendar.Header>
-  <RangeCalendar.PrevButton />
+  <RangeCalendar.PrevButton aria-label="Previous month" />
   <RangeCalendar.Heading />
-  <RangeCalendar.NextButton />
+  <RangeCalendar.NextButton aria-label="Next month" />
 </RangeCalendar.Header>
📝 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.

	<RangeCalendar.Header>
		<RangeCalendar.PrevButton aria-label="Previous month" />
		<RangeCalendar.Heading />
		<RangeCalendar.NextButton aria-label="Next month" />
	</RangeCalendar.Header>

40-42: ⚠️ Potential issue

Use weekdayFormat prop instead of hardcoded slice.

The weekday formatting ignores the weekdayFormat prop, potentially causing inconsistency with the component's API.

-{weekday.slice(0, 2)}
+{weekday}

Committable suggestion was skipped due to low confidence.


3-3: 💡 Codebase verification

Import statement needs to be updated to reflect correct file extension

The import statement in range-calendar.svelte references ./index.js, but the file is actually index.ts. The import should be updated to:

import * as RangeCalendar from './index.ts';
🔗 Analysis chain

Verify the imported calendar components.

Let's ensure all required components are properly exported from the index file.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all required calendar components are exported from index.js

# Test: Check if all required components are exported
rg -l "export \* from.*(?:Header|PrevButton|NextButton|Months|Grid|GridHead|GridRow|HeadCell|GridBody|Cell|Day)" "frontend/src/lib/components/ui/range-calendar/"

Length of output: 161


Script:

#!/bin/bash
# Let's first check what files exist in the range-calendar directory
fd . frontend/src/lib/components/ui/range-calendar/

# Then check the content of index.js to see what it exports
cat frontend/src/lib/components/ui/range-calendar/index.js

Length of output: 1239


Script:

#!/bin/bash
# The file is index.ts, not index.js. Let's check its contents
cat frontend/src/lib/components/ui/range-calendar/index.ts

Length of output: 921

frontend/tailwind.config.js (1)

62-69: ⚠️ Potential issue

Adjust line height for '3xl' size to improve readability.

The line height configuration for the '3xl' size (34px font with 32px line height) results in a ratio of 0.94, which means text lines will overlap. This violates typography best practices where line height should typically be 1.2-1.5 times the font size for optimal readability.

Apply this fix to ensure proper text spacing:

 fontSize: {
   sm: ['13px', { lineHeight: '16px' }],
   md: ['14px', { lineHeight: '18px' }],
   lg: ['16px', { lineHeight: '21px' }],
   xl: ['20px', { lineHeight: '28px' }],
   '2xl': ['25px', { lineHeight: '32px' }],
-  '3xl': ['34px', { lineHeight: '32px' }],
+  '3xl': ['34px', { lineHeight: '44px' }],
   '4xl': ['52px', { lineHeight: '58px' }]
 }
📝 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.

			fontSize: {
				sm: ['13px', { lineHeight: '16px' }],
				md: ['14px', { lineHeight: '18px' }],
				lg: ['16px', { lineHeight: '21px' }],
				xl: ['20px', { lineHeight: '28px' }],
				'2xl': ['25px', { lineHeight: '32px' }],
				'3xl': ['34px', { lineHeight: '44px' }],
				'4xl': ['52px', { lineHeight: '58px' }]
frontend/src/lib/api/api.ts (1)

82-102: 🛠️ Refactor suggestion

Consider adding parameter validation

While the implementation is solid, consider adding validation for required parameters (featureName, startTs, endTs) to fail fast and provide better error messages.

 export async function getFeatureTimeseries(
 	featureName: string,
 	startTs: number,
 	endTs: number,
 	metricType: string = 'drift',
 	metrics: string = 'null',
 	offset: string = '10h',
 	algorithm: string = 'psi',
 	granularity: string = 'percentile'
 ): Promise<FeatureResponse> {
+	if (!featureName) {
+		throw new Error('featureName is required');
+	}
+	if (!Number.isFinite(startTs) || !Number.isFinite(endTs)) {
+		throw new Error('Invalid timestamp values');
+	}
+	if (startTs >= endTs) {
+		throw new Error('startTs must be less than endTs');
+	}
 	const params = new URLSearchParams({
📝 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 async function getFeatureTimeseries(
	featureName: string,
	startTs: number,
	endTs: number,
	metricType: string = 'drift',
	metrics: string = 'null',
	offset: string = '10h',
	algorithm: string = 'psi',
	granularity: string = 'percentile'
): Promise<FeatureResponse> {
	if (!featureName) {
		throw new Error('featureName is required');
	}
	if (!Number.isFinite(startTs) || !Number.isFinite(endTs)) {
		throw new Error('Invalid timestamp values');
	}
	if (startTs >= endTs) {
		throw new Error('startTs must be less than endTs');
	}
	const params = new URLSearchParams({
		startTs: startTs.toString(),
		endTs: endTs.toString(),
		metricType,
		metrics,
		offset,
		algorithm,
		granularity
	});
	return get(`feature/${featureName}/timeseries?${params.toString()}`);
}
frontend/src/lib/components/EChart/EChart.svelte (2)

36-39: 🛠️ Refactor suggestion

Consider a more maintainable approach to hide zoom buttons

Using empty paths as a hack to hide buttons is not ideal. Consider using ECharts' built-in show property instead.

 toolbox: {
   feature: {
     dataZoom: {
       yAxisIndex: 'none',
-      icon: {
-        zoom: 'path://', // hack to remove zoom button
-        back: 'path://' // hack to remove restore button
+      show: false,
+      showTitle: false
     }
   }
 }

Committable suggestion was skipped due to low confidence.


75-80: 🛠️ Refactor suggestion

Add error handling and cleanup for zoom functionality

The zoom activation should include error handling and proper cleanup when the component is destroyed.

 function activateZoom() {
+  try {
     chartInstance?.dispatchAction({
       type: 'takeGlobalCursor',
       key: 'dataZoomSelect',
       dataZoomSelectActive: true
     });
+  } catch (error) {
+    console.error('Failed to activate zoom:', error);
+  }
 }

 onDestroy(() => {
   chartInstance?.dispose();
+  // Deactivate zoom before disposal
+  chartInstance?.dispatchAction({
+    type: 'takeGlobalCursor',
+    key: 'dataZoomSelect',
+    dataZoomSelectActive: false
+  });
   resizeObserver?.disconnect();
 });

Committable suggestion was skipped due to low confidence.

frontend/src/lib/util/sample-data.ts (1)

201-203: ⚠️ Potential issue

Remove inconsistent labels in percentile data.

Found labels 'A', 'B', 'C' in the middle of percentile data which breaks the p0-p100 pattern. These labels appear to be accidentally mixed with categorical data.

Apply this diff to remove the inconsistent data points:

-		{ value: 0.3556266835103211, ts: 1725973200000, label: 'A', nullValue: 19 },
-		{ value: 0.038024628812456385, ts: 1725976800000, label: 'B', nullValue: 5 },
-		{ value: 0.7876377978962372, ts: 1725976800000, label: 'C', nullValue: 26 },
📝 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.


frontend/src/lib/components/DateRangeSelector/DateRangeSelector.svelte (1)

68-75: ⚠️ Potential issue

Add error handling for invalid URL parameters

If startTimestamp or endTimestamp are missing or invalid, Number(startTimestamp) will result in NaN, which can cause errors when passed to fromAbsolute(). Consider adding validation to handle missing or invalid parameters gracefully.

frontend/src/routes/models/[slug]/observability/+page.svelte (3)

33-49: ⚠️ Potential issue

Verify the usage of $state and $derived

The code utilizes $state and $derived for state management and derived values. These are not standard Svelte functions, and unless they are imported or defined elsewhere in your codebase, this may lead to errors. Please ensure that $state and $derived are properly imported or implemented. If they are custom implementations, consider providing context or comments for clarity.


245-246: ⚠️ Potential issue

Verify the usage of $derived for computed values

The variable shouldShowStickyHeader is assigned using $derived, which is not a standard Svelte pattern for derived values. Unless $derived is a custom function defined in your codebase, this might cause issues. Ensure that $derived is properly implemented or consider using Svelte's built-in reactive statements or the derived store from svelte/store.


58-61: ⚠️ Potential issue

Incorrect casting of axisLabel.formatter property

The axisLabel.formatter property is being assigned an object and then cast to unknown and finally to string. This casting is inappropriate and may cause runtime errors because the formatter expects a function or a string pattern. Assigning an object and forcing it into a string type is likely to result in incorrect behavior.

Consider defining the formatter as a function to correctly format the axis labels:

-    					formatter: {
-    						month: '{MMM} {d}',
-    						day: '{MMM} {d}'
-    					} as unknown as string
+    					formatter: (value: number) => {
+    						const date = new Date(value);
+    						return date.toLocaleDateString(undefined, { month: 'short', day: 'numeric' });
+    					}

Alternatively, if you intend to use the object formatter with time axes, ensure that the ECharts type definitions support this usage or update the type definitions accordingly.

📝 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.

						formatter: (value: number) => {
							const date = new Date(value);
							return date.toLocaleDateString(undefined, { month: 'short', day: 'numeric' });
						}
				},

@ken-zlai ken-zlai merged commit 37adea7 into main Nov 7, 2024
6 of 8 checks passed
@ken-zlai ken-zlai deleted the frontend-8/18-milestone branch November 7, 2024 00:04
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