Conversation
…cture Split monolithic ProductFilters.tsx (479 lines) into 8 focused components under products/filters/. Extract shared utilities (color-map, price-buckets, filters) into lib/utils/. Fix stale closure bug in infinite scroll by using refs. Remove all non-functional comments. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughModularizes product filtering: introduces FilterBar, dropdowns, chips, and mobile drawer; adds utilities for colors, filters, and price buckets; centralizes ActiveFilters type; updates listing/layout/hooks to use ActiveFilters; removes legacy ProductFilters file and adds a small globals.css animation. (≤50 words) Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant FilterBar
participant DropdownContent
participant API
participant ProductListing
User->>FilterBar: open/toggle dropdown or drawer
FilterBar->>DropdownContent: render option/price/availability/sort UI
User->>DropdownContent: select/toggle option or bucket or availability
DropdownContent-->>FilterBar: emit change (activeFilters)
FilterBar->>API: request products with activeFilters
API-->>ProductListing: return filtered products
ProductListing->>User: render updated product grid
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (4)
src/lib/utils/filters.ts (1)
24-39: Consider consolidating duplicate sort label mappings.
SORT_LABELScontains duplicate human-readable labels for different API key formats (e.g.,"price"and"price asc"both map to"Price: Low to High"). While this provides flexibility for different backend formats, it may lead to maintenance overhead.If the backend consistently uses one format, consider removing the unused mappings to reduce duplication.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/lib/utils/filters.ts` around lines 24 - 39, SORT_LABELS contains duplicate human-readable labels for multiple key formats (e.g., "price" vs "price asc", "available_on" vs "available_on asc/desc", "name" vs "name asc/desc"); consolidate by picking a canonical key format or normalizing incoming sort keys before lookup to avoid duplicate entries. Update SORT_LABELS to only include the canonical keys you expect from the backend (for example "price", "-price", "available_on", "-available_on", "name", "-name", "manual", "best_selling") and add a small normalization step where sort keys are converted from variants like "price asc"/"price desc" to the canonical form before accessing SORT_LABELS (refer to SORT_LABELS and the normalization function you add or update).src/components/products/filters/AvailabilityDropdownContent.tsx (1)
29-29: Type assertion bypasses type safety.The cast
option.id as AvailabilityStatusassumes the SDK'sAvailabilityFilter.options[].idvalues will always be"in_stock"or"out_of_stock". If the SDK returns unexpected values, this could propagate invalid data through the filter system.Consider adding a runtime guard:
🛡️ Proposed safer implementation
+const isValidAvailability = (id: string): id is AvailabilityStatus => + id === "in_stock" || id === "out_of_stock"; onClick={() => { if (isSelected) { onChange(undefined); } else { - onChange(option.id as AvailabilityStatus); + if (isValidAvailability(option.id)) { + onChange(option.id); + } } }}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/products/filters/AvailabilityDropdownContent.tsx` at line 29, The code casts option.id to AvailabilityStatus which bypasses type safety; in AvailabilityDropdownContent replace the direct cast before calling onChange(option.id as AvailabilityStatus) with a runtime guard that checks option.id against the allowed AvailabilityStatus values (e.g., "in_stock" and "out_of_stock") or an AvailabilityStatus enum/const set, and only call onChange with the validated value, otherwise handle the unexpected case (no-op, fallback, or error/log) to avoid propagating invalid values from the SDK.src/components/products/filters/FilterDropdown.tsx (1)
56-57: Minor: Verifyaria-haspopupvalue matches dropdown content.The
aria-haspopup="listbox"is appropriate if the dropdown content contains selectable options. If the content varies (e.g., price range inputs vs. option lists), you might want the parent to pass the appropriatearia-haspopupvalue.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/products/filters/FilterDropdown.tsx` around lines 56 - 57, The aria-haspopup value is hardcoded to "listbox" in FilterDropdown (aria-expanded={isOpen} aria-haspopup="listbox"), which may be incorrect for varying dropdown content; add a new prop (e.g., ariaHaspopup?: string or a union of allowed values) to the FilterDropdown component, update its prop types/interface to include ariaHaspopup, use aria-haspopup={ariaHaspopup ?? 'listbox'} when rendering, and document the prop so callers can pass the correct value for price inputs, dialogs, menus, etc.src/components/products/filters/MobileFilterDrawer.tsx (1)
42-59: Consider adding focus trap for accessibility.The drawer lacks focus management, which can cause keyboard users to tab outside the visible drawer while it's open. Consider:
- Trapping focus within the drawer when open
- Moving focus to the close button when the drawer opens
- Returning focus to the trigger element when the drawer closes
This is a recommended improvement for WCAG 2.1 compliance (Success Criterion 2.4.3: Focus Order).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/products/filters/MobileFilterDrawer.tsx` around lines 42 - 59, The drawer component MobileFilterDrawer.tsx currently lacks focus management; update it to trap focus inside the drawer while open, move focus to the close button when opening, and restore focus to the element that opened the drawer when closing. Implement this by capturing the trigger element (store document.activeElement before opening), adding a ref to the close button (e.g., closeButtonRef) and calling focus on it in useEffect when the drawer opens, and setting focus back to the saved trigger in the onClose handler; ensure tab/shift-tab are constrained to elements inside the drawer (either via a small focus-trap implementation using keydown handlers that cycle focus within the drawer containerRef or by integrating a lightweight library like focus-trap-react) and clean up any event listeners on unmount.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/components/products/filters/ProductFilters.tsx`:
- Around line 80-82: The clearFilters callback currently only resets
optionValues; update the clearFilters function to call onFilterChange with a
payload that clears all filter fields (e.g., set optionValues: [], priceMin:
undefined or null, priceMax: undefined or null, availability: undefined or null)
while intentionally leaving sortBy untouched; locate the clearFilters
useCallback and change its argument to include optionValues plus priceMin,
priceMax and availability resets so the "Clear All" action in FilterChips truly
clears filters.
---
Nitpick comments:
In `@src/components/products/filters/AvailabilityDropdownContent.tsx`:
- Line 29: The code casts option.id to AvailabilityStatus which bypasses type
safety; in AvailabilityDropdownContent replace the direct cast before calling
onChange(option.id as AvailabilityStatus) with a runtime guard that checks
option.id against the allowed AvailabilityStatus values (e.g., "in_stock" and
"out_of_stock") or an AvailabilityStatus enum/const set, and only call onChange
with the validated value, otherwise handle the unexpected case (no-op, fallback,
or error/log) to avoid propagating invalid values from the SDK.
In `@src/components/products/filters/FilterDropdown.tsx`:
- Around line 56-57: The aria-haspopup value is hardcoded to "listbox" in
FilterDropdown (aria-expanded={isOpen} aria-haspopup="listbox"), which may be
incorrect for varying dropdown content; add a new prop (e.g., ariaHaspopup?:
string or a union of allowed values) to the FilterDropdown component, update its
prop types/interface to include ariaHaspopup, use aria-haspopup={ariaHaspopup ??
'listbox'} when rendering, and document the prop so callers can pass the correct
value for price inputs, dialogs, menus, etc.
In `@src/components/products/filters/MobileFilterDrawer.tsx`:
- Around line 42-59: The drawer component MobileFilterDrawer.tsx currently lacks
focus management; update it to trap focus inside the drawer while open, move
focus to the close button when opening, and restore focus to the element that
opened the drawer when closing. Implement this by capturing the trigger element
(store document.activeElement before opening), adding a ref to the close button
(e.g., closeButtonRef) and calling focus on it in useEffect when the drawer
opens, and setting focus back to the saved trigger in the onClose handler;
ensure tab/shift-tab are constrained to elements inside the drawer (either via a
small focus-trap implementation using keydown handlers that cycle focus within
the drawer containerRef or by integrating a lightweight library like
focus-trap-react) and clean up any event listeners on unmount.
In `@src/lib/utils/filters.ts`:
- Around line 24-39: SORT_LABELS contains duplicate human-readable labels for
multiple key formats (e.g., "price" vs "price asc", "available_on" vs
"available_on asc/desc", "name" vs "name asc/desc"); consolidate by picking a
canonical key format or normalizing incoming sort keys before lookup to avoid
duplicate entries. Update SORT_LABELS to only include the canonical keys you
expect from the backend (for example "price", "-price", "available_on",
"-available_on", "name", "-name", "manual", "best_selling") and add a small
normalization step where sort keys are converted from variants like "price
asc"/"price desc" to the canonical form before accessing SORT_LABELS (refer to
SORT_LABELS and the normalization function you add or update).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 94a17d1e-9ce5-4e6e-8f79-e5308594713e
📒 Files selected for processing (20)
src/app/[country]/[locale]/(storefront)/t/[...permalink]/CategoryProductsContent.tsxsrc/app/globals.csssrc/components/products/ProductFilters.tsxsrc/components/products/ProductListingLayout.tsxsrc/components/products/VariantPicker.tsxsrc/components/products/filters/AvailabilityDropdownContent.tsxsrc/components/products/filters/FilterChips.tsxsrc/components/products/filters/FilterDropdown.tsxsrc/components/products/filters/MobileFilterDrawer.tsxsrc/components/products/filters/OptionDropdownContent.tsxsrc/components/products/filters/PriceDropdownContent.tsxsrc/components/products/filters/ProductFilters.tsxsrc/components/products/filters/SortDropdownContent.tsxsrc/components/products/filters/index.tssrc/hooks/useProductListing.tssrc/lib/utils/color-map.tssrc/lib/utils/filters.tssrc/lib/utils/price-buckets.tssrc/lib/utils/product-query.tssrc/types/filters.ts
💤 Files with no reviewable changes (2)
- src/components/products/ProductFilters.tsx
- src/app/[country]/[locale]/(storefront)/t/[...permalink]/CategoryProductsContent.tsx
- Fix clearFilters to reset all filter fields (price, availability) not just optionValues - Replace unsafe AvailabilityStatus casts with runtime type guard - Add focus trap and ARIA attributes to MobileFilterDrawer - Normalize SORT_LABELS to remove duplicate entries Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
src/components/products/filters/ProductFilters.tsx (1)
14-20: Switch the sibling component imports to the@alias.This file still uses
./...imports for local filter components, which diverges from the repo import convention.♻️ Suggested change
-import { AvailabilityDropdownContent } from "./AvailabilityDropdownContent"; -import { FilterChips } from "./FilterChips"; -import { FilterDropdown } from "./FilterDropdown"; -import { MobileFilterDrawer } from "./MobileFilterDrawer"; -import { OptionDropdownContent } from "./OptionDropdownContent"; -import { PriceDropdownContent } from "./PriceDropdownContent"; -import { SortDropdownContent } from "./SortDropdownContent"; +import { AvailabilityDropdownContent } from "@/components/products/filters/AvailabilityDropdownContent"; +import { FilterChips } from "@/components/products/filters/FilterChips"; +import { FilterDropdown } from "@/components/products/filters/FilterDropdown"; +import { MobileFilterDrawer } from "@/components/products/filters/MobileFilterDrawer"; +import { OptionDropdownContent } from "@/components/products/filters/OptionDropdownContent"; +import { PriceDropdownContent } from "@/components/products/filters/PriceDropdownContent"; +import { SortDropdownContent } from "@/components/products/filters/SortDropdownContent";As per coding guidelines, "Use absolute imports with @ alias (e.g.,
@/components/...,@/lib/...) instead of relative imports".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/products/filters/ProductFilters.tsx` around lines 14 - 20, Replace the relative sibling imports with the project’s @ alias: update the import paths for AvailabilityDropdownContent, FilterChips, FilterDropdown, MobileFilterDrawer, OptionDropdownContent, PriceDropdownContent, and SortDropdownContent to use "@/components/..." (or the repo’s configured @ root) instead of "./..."; keep the same exported symbols and import names so only the module paths change and no other code needs modification.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/components/products/filters/AvailabilityDropdownContent.tsx`:
- Around line 24-40: The button only changes visual styling; add accessible
pressed semantics by setting an ARIA pressed state and a clear accessible label:
update the button in AvailabilityDropdownContent to include
aria-pressed={isSelected} (or role="menuitemradio" with
aria-checked={isSelected} if it's inside a single-select menu) and ensure the
visible label (AVAILABILITY_LABELS[option.id] || option.id) remains unchanged so
assistive tech announces which option is active; keep the onClick logic using
isSelected, onChange, and isAvailabilityStatus(option.id) but add the aria
attribute to the button element.
In `@src/components/products/filters/MobileFilterDrawer.tsx`:
- Around line 196-223: The buttons rendering filter options (the element keyed
by option.id and using onToggle, including the CheckIcon and resolveColor usage)
lack accessible selection semantics; update each interactive button to expose
selection state by adding aria-pressed={isSelected} (or
role="checkbox"/aria-checked={isSelected} if you prefer checkbox semantics) and
ensure the button label remains the accessible name (e.g., option.presentation)
so assistive tech can announce it; make the same change to the other button
groups referenced (the blocks around the other ranges: 231-241, 276-295,
321-343) so all four control groups consistently expose selection with either
aria-pressed or checkbox/radio roles and aria-checked attributes.
In `@src/components/products/filters/ProductFilters.tsx`:
- Around line 48-88: Current handlers (handleOptionValueToggle,
handlePriceChange, handleAvailabilityChange, clearFilters, and handleSortChange)
mutate global filters immediately and are passed into MobileFilterDrawer; change
them to update a drawer-local draft state (e.g., stagedFilters) instead of
calling onFilterChange, pass these staged handlers into MobileFilterDrawer, make
clearFilters reset stagedFilters (not the global state), and add/rename a commit
function (e.g., applyStagedFilters) that calls onFilterChange(stagedFilters)
from the drawer footer Confirm/Show results action; ensure closeDropdown/cancel
simply discards stagedFilters so accidental edits are cancelable.
In `@src/components/products/filters/SortDropdownContent.tsx`:
- Around line 20-31: The sort option buttons only indicate selection visually;
update the button in SortDropdownContent to expose selection semantics by adding
a type="button" and setting aria-pressed={isActive} (or aria-current="true" when
active) so assistive tech knows the active option; ensure the onClick handler
(onSortChange(option.id)), getSortLabel(option.id) label, and option.id remain
unchanged and no other behavior is altered.
---
Nitpick comments:
In `@src/components/products/filters/ProductFilters.tsx`:
- Around line 14-20: Replace the relative sibling imports with the project’s @
alias: update the import paths for AvailabilityDropdownContent, FilterChips,
FilterDropdown, MobileFilterDrawer, OptionDropdownContent, PriceDropdownContent,
and SortDropdownContent to use "@/components/..." (or the repo’s configured @
root) instead of "./..."; keep the same exported symbols and import names so
only the module paths change and no other code needs modification.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 5720de0d-2d7d-441f-aef8-b7ecc4bf0bbb
📒 Files selected for processing (6)
src/components/products/filters/AvailabilityDropdownContent.tsxsrc/components/products/filters/MobileFilterDrawer.tsxsrc/components/products/filters/ProductFilters.tsxsrc/components/products/filters/SortDropdownContent.tsxsrc/lib/utils/filters.tssrc/types/filters.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- src/types/filters.ts
- Add type="button" and aria-pressed to filter buttons in AvailabilityDropdownContent, SortDropdownContent, and all MobileFilterDrawer button groups (colors, sizes, prices, availability) - Refactor MobileFilterDrawer to use staged/draft filter state so selections are only applied on "Show results" and discarded on close - Replace relative imports with @/ alias in ProductFilters Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/components/products/filters/ProductFilters.tsx (1)
30-36: Add an explicit return type to the exported component.
FilterBaris part of the public component surface, but its return type is inferred. The repo guideline asks for explicit return types in TS/TSX, so this is worth annotating directly.♻️ Proposed fix
+import type { ReactElement } from "react"; import { memo, useCallback, useMemo, useState } from "react"; @@ export const FilterBar = memo(function FilterBar({ filtersData, filtersLoading, activeFilters, totalCount, onFilterChange, -}: FilterBarProps) { +}: FilterBarProps): ReactElement | null {As per coding guidelines "Use strict TypeScript type checking; define explicit return types for functions and avoid 'any' type".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/products/filters/ProductFilters.tsx` around lines 30 - 36, The exported memoized component FilterBar currently relies on an inferred return type; update its declaration to include an explicit return type (e.g., React.ReactElement or JSX.Element) so it conforms to TypeScript strict typing for public components—modify the function signature that uses memo(function FilterBar({ ... }: FilterBarProps): JSX.Element { ... }) (or equivalent) to annotate the return type while keeping the use of memo and FilterBarProps unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/components/products/filters/ProductFilters.tsx`:
- Around line 229-245: The mobile Filters trigger button currently lacks an
explicit type and can inadvertently submit ancestor forms; update the button
element used with onClick={() => setShowMobileDrawer(true)} (the element that
renders FilterIcon, hasActiveFilters, and totalActiveFilters) to include
type="button" so it does not act as a submit control.
---
Nitpick comments:
In `@src/components/products/filters/ProductFilters.tsx`:
- Around line 30-36: The exported memoized component FilterBar currently relies
on an inferred return type; update its declaration to include an explicit return
type (e.g., React.ReactElement or JSX.Element) so it conforms to TypeScript
strict typing for public components—modify the function signature that uses
memo(function FilterBar({ ... }: FilterBarProps): JSX.Element { ... }) (or
equivalent) to annotate the return type while keeping the use of memo and
FilterBarProps unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 9a46fb0b-9eec-4c4a-a082-1df71c59cad9
📒 Files selected for processing (4)
src/components/products/filters/AvailabilityDropdownContent.tsxsrc/components/products/filters/MobileFilterDrawer.tsxsrc/components/products/filters/ProductFilters.tsxsrc/components/products/filters/SortDropdownContent.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
- src/components/products/filters/AvailabilityDropdownContent.tsx
- src/components/products/filters/MobileFilterDrawer.tsx
- src/components/products/filters/SortDropdownContent.tsx
…to FilterBar Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolve merge conflicts in VariantPicker and useProductListing by adopting new SDK type names (StoreVariant → Variant, StoreProduct → Product). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
🧹 Nitpick comments (2)
src/components/products/ProductListingLayout.tsx (1)
28-43: Consider adding explicit return type.Per coding guidelines, functions should have explicit return types. While TypeScript infers the return type correctly here, adding it would improve maintainability.
✨ Suggested enhancement
+import type { ReactElement } from "react"; + export function ProductListingLayout({ products, loading, ... -}: ProductListingLayoutProps) { +}: ProductListingLayoutProps): ReactElement {As per coding guidelines: "Use strict TypeScript type checking; define explicit return types for functions."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/products/ProductListingLayout.tsx` around lines 28 - 43, The ProductListingLayout component lacks an explicit return type; update its signature (the export function ProductListingLayout(...) declaration) to include an explicit React return type such as React.ReactElement or JSX.Element (e.g., export function ProductListingLayout(...): React.ReactElement) and, if your project’s TSX setup requires it, add an import type { ReactElement } from 'react' and use that type to satisfy the linter and strict TypeScript rules.src/hooks/useProductListing.ts (1)
135-136: Consider groupingloadingMoreRefwith other refs.The
loadingMoreRefis declared separately from the other refs (lines 38-50). For consistency and readability, consider moving it alongsidehasMoreRefand other pagination-related refs.📍 Suggested placement
Move this declaration to approximately line 40, after
hasMoreRef:const hasMoreRef = useRef(false); + const loadingMoreRef = useRef(false); const filtersRef = useRef<ActiveFilters>({ optionValues: [] });Then remove lines 135-136.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/hooks/useProductListing.ts` around lines 135 - 136, Move the loadingMoreRef declaration next to the other pagination refs for consistency: locate the hasMoreRef and related refs in useProductListing and add the const loadingMoreRef = useRef(false); directly after them, then remove the separate declaration currently named loadingMoreRef declared later in the file; update any references to loadingMoreRef to use the moved ref (no other logic changes).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/components/products/ProductListingLayout.tsx`:
- Around line 28-43: The ProductListingLayout component lacks an explicit return
type; update its signature (the export function ProductListingLayout(...)
declaration) to include an explicit React return type such as React.ReactElement
or JSX.Element (e.g., export function ProductListingLayout(...):
React.ReactElement) and, if your project’s TSX setup requires it, add an import
type { ReactElement } from 'react' and use that type to satisfy the linter and
strict TypeScript rules.
In `@src/hooks/useProductListing.ts`:
- Around line 135-136: Move the loadingMoreRef declaration next to the other
pagination refs for consistency: locate the hasMoreRef and related refs in
useProductListing and add the const loadingMoreRef = useRef(false); directly
after them, then remove the separate declaration currently named loadingMoreRef
declared later in the file; update any references to loadingMoreRef to use the
moved ref (no other logic changes).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 72ee9ea7-4653-49b5-97a6-c5362b12c500
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (3)
src/components/products/ProductListingLayout.tsxsrc/components/products/VariantPicker.tsxsrc/hooks/useProductListing.ts
…ether Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
ProductFilters.tsx(479 lines, 5 components) into 8 focused files underproducts/filters/with barrel exportcolor-map.ts,price-buckets.ts,filters.ts) intolib/utils/— DRY across filter components andVariantPickerloadMorecallback by using refs instead of stateTest plan
npm run check— passes ✅npx tsc --noEmit— passes ✅🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Improvements
Style