Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Accordion): new promo version #1437

Merged
merged 6 commits into from
Nov 26, 2024
Merged

feat(Accordion): new promo version #1437

merged 6 commits into from
Nov 26, 2024

Conversation

marcinsawicki
Copy link
Contributor

@marcinsawicki marcinsawicki commented Nov 22, 2024

Resolves: #1346

Description

A new variant of the Accordion component as a separate component.

Storybook

https://feature-1346--613a8e945a5665003a05113b.chromatic.com

Checklist

Obligatory:

  • Self review (use this as your final check for proposed changes before requesting the review)
  • Add correct label
  • Assign pull request with the correct issue

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a new Promo Accordion variant with enhanced styling and functionality.
    • Added documentation sections for Default Accordion and Promo Accordion with example implementations.
    • Enhanced storytelling capabilities with new examples showcasing footers and multiline labels.
  • Bug Fixes

    • Added tests to ensure footer visibility when the accordion is toggled.
  • Documentation

    • Improved documentation structure for the Accordion component, providing clearer examples and usage guidelines.
  • Style

    • New promotional styles added for the Accordion component and its subcomponents.
  • Chores

    • Updated exports to include the new AccordionPromo component.

@marcinsawicki marcinsawicki added the feature New feature or request label Nov 22, 2024
@marcinsawicki marcinsawicki added this to the Cycle #10 milestone Nov 22, 2024
@marcinsawicki marcinsawicki self-assigned this Nov 22, 2024
@marcinsawicki marcinsawicki linked an issue Nov 22, 2024 that may be closed by this pull request
Comment on lines 26 to 29
!isControlled && setShouldBeVisible(false);
} else {
onOpen?.();
!isControlled && setShouldBeVisible(true);
Copy link
Contributor

Choose a reason for hiding this comment

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

You do not need to duplicate the setter, use isExpanded value as an argument for this function

Comment on lines 35 to 41
if (!isExpanded && (event.key === 'Enter' || event.key === ' ')) {
handleExpandChange(isExpanded);
}

if (isExpanded && event.key === 'Escape') {
handleExpandChange(isExpanded);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

what is the difference between those if's?

interface UseAccordionProps {
isControlled: boolean;
isExpanded: boolean;
setShouldBeVisible: React.Dispatch<React.SetStateAction<boolean>>;
Copy link
Contributor

Choose a reason for hiding this comment

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

You can make it a simple callback with a parameter, so you do not need a react dispatch types here.

Copy link
Contributor

coderabbitai bot commented Nov 26, 2024

Walkthrough

The changes in this pull request enhance the Accordion component by introducing a new promotional variant and improving documentation. Key updates include the addition of new sections in the documentation, new styles for promotional use, and the creation of a custom hook to manage accordion state. The Accordion component is refactored into two components: AccordionComponent and AccordionPromo, allowing for better separation of concerns and functionality. Additionally, new test cases and story examples are provided to illustrate the new features.

Changes

File Change Summary
packages/react-components/src/components/Accordion/Accordion.mdx Added sections for "Default Accordion" and "Promo Accordion" with example implementations.
packages/react-components/src/components/Accordion/Accordion.module.scss Introduced new styles and modifiers for promotional use in various accordion classes.
packages/react-components/src/components/Accordion/Accordion.spec.tsx Added a test case to verify footer visibility in the Accordion component.
packages/react-components/src/components/Accordion/Accordion.stories.css Added new CSS classes for promotional styling in stories.
packages/react-components/src/components/Accordion/Accordion.stories.tsx Expanded stories to include AccordionPromo and new examples for Accordion with footers.
packages/react-components/src/components/Accordion/Accordion.tsx Refactored Accordion into AccordionComponent and AccordionPromo, added new props.
packages/react-components/src/components/Accordion/hooks.ts Introduced useAccordion hook for managing accordion state and behavior.
packages/react-components/src/components/Accordion/index.ts Updated exports to include AccordionPromo.
packages/react-components/src/components/Accordion/types.ts Renamed and reorganized interfaces for better modularity and clarity.

Assessment against linked issues

Objective Addressed Explanation
New variants for Accordion (#1346)
Improved documentation for new variants
Enhanced styling for promotional variant
Testing for new functionalities
Clear separation of component logic

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Outside diff range and nitpick comments (8)
packages/react-components/src/components/Accordion/hooks.ts (1)

3-14: Improve interface naming consistency and documentation

  1. Remove the 'I' prefix from IUseAccordion to follow modern TypeScript conventions
  2. Consider renaming setShouldBeVisible to setExpanded for clarity
 interface UseAccordionProps {
   isControlled: boolean;
   isExpanded: boolean;
-  setShouldBeVisible: (isVisible: boolean) => void;
+  setExpanded: (isExpanded: boolean) => void;
   onOpen?: () => void;
   onClose?: () => void;
 }

-interface IUseAccordion {
+interface UseAccordionReturn {
   handleExpandChange: (isExpanded: boolean) => void;
   handleKeyDown: (event: React.KeyboardEvent<HTMLDivElement>) => void;
 }
packages/react-components/src/components/Accordion/types.ts (2)

44-49: Consider using an enum for kind variants

The interface structure is good, but consider using an enum for the kind variants to improve type safety and maintainability.

+export enum AccordionKind {
+  Default = 'default',
+  Warning = 'warning',
+  Error = 'error'
+}

 export interface IAccordionProps extends IAccordionGlobalProps {
   /**
    * Specify the kind of the accordion
    */
-  kind?: 'default' | 'warning' | 'error';
+  kind?: AccordionKind;
 }

51-52: Document the purpose of IAccordionPromoProps

Even if the interface is currently empty, add JSDoc comments to explain its purpose and future extensibility.

+/**
+ * Interface for the promotional variant of Accordion
+ * Extends global props without additional properties
+ */
 export interface IAccordionPromoProps extends IAccordionGlobalProps {}
packages/react-components/src/components/Accordion/Accordion.mdx (2)

24-31: Add prop descriptions for better clarity

Consider adding brief descriptions for multilineElement and footer props to explain their purpose and usage.

 <Accordion
   label={{
     closed: (<div>Label for closed accordion</div>),
     open: (<div>Label for open accordion</div>),
   }}
+  // Displays additional content below the label
   multilineElement={<div>Multiline element</div>}
+  // Renders at the bottom of the expanded accordion
   footer={<div>Footer element</div>}
 >

36-55: Highlight PromoAccordion's unique features

The example effectively shows the implementation but could benefit from a brief description of how PromoAccordion differs from the default variant.

 ### Promo Accordion <a id="Promo" />
+
+The Promo variant of Accordion provides enhanced styling options optimized for promotional content.
+Key differences from the default variant include:
+- Custom styling for promotional content
+- Specialized layout for marketing materials
packages/react-components/src/components/Accordion/Accordion.module.scss (1)

108-114: Consider adding transition to footer

The footer section looks good, but could benefit from a smooth transition like other elements.

 &__footer {
   border-top: 1px solid var(--border-basic-secondary);
   padding: var(--spacing-5);
+  transition: all var(--transition-duration-moderate-1);

   &--promo {
     padding: var(--spacing-6);
   }
 }
packages/react-components/src/components/Accordion/Accordion.spec.tsx (1)

88-97: LGTM! Consider adding edge cases.

The test case effectively verifies the footer visibility toggle behavior.

Consider adding these test scenarios:

it('should not show footer when accordion is closed after being open', async () => {
  const { queryByText, getByRole } = renderComponent({
    ...DEFAULT_PROPS,
    footer: <div>Footer</div>,
  });
  
  userEvent.click(getByRole('button')); // open
  await waitFor(() => expect(queryByText('Footer')).toBeInTheDocument());
  
  userEvent.click(getByRole('button')); // close
  await waitFor(() => expect(queryByText('Footer')).not.toBeInTheDocument());
});

it('should show footer immediately when openOnInit is true', () => {
  const { queryByText } = renderComponent({
    ...DEFAULT_PROPS,
    footer: <div>Footer</div>,
    openOnInit: true,
  });
  
  expect(queryByText('Footer')).toBeInTheDocument();
});
packages/react-components/src/components/Accordion/Accordion.stories.tsx (1)

118-122: Enhance footer example with realistic content

Consider enriching the footer example with more realistic content like action buttons or links that demonstrate typical usage patterns.

-        <Accordion label="Default" footer={<div>Example footer element</div>}>
+        <Accordion 
+          label="Default" 
+          footer={
+            <div className="accordion-footer">
+              <button onClick={() => console.log('Primary action')}>
+                Save Changes
+              </button>
+              <a href="#">Learn more</a>
+            </div>
+          }
+        >
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between e1242cc and 9aa4e99.

📒 Files selected for processing (9)
  • packages/react-components/src/components/Accordion/Accordion.mdx (1 hunks)
  • packages/react-components/src/components/Accordion/Accordion.module.scss (4 hunks)
  • packages/react-components/src/components/Accordion/Accordion.spec.tsx (1 hunks)
  • packages/react-components/src/components/Accordion/Accordion.stories.css (1 hunks)
  • packages/react-components/src/components/Accordion/Accordion.stories.tsx (2 hunks)
  • packages/react-components/src/components/Accordion/Accordion.tsx (4 hunks)
  • packages/react-components/src/components/Accordion/hooks.ts (1 hunks)
  • packages/react-components/src/components/Accordion/index.ts (1 hunks)
  • packages/react-components/src/components/Accordion/types.ts (3 hunks)
✅ Files skipped from review due to trivial changes (1)
  • packages/react-components/src/components/Accordion/Accordion.stories.css
🔇 Additional comments (12)
packages/react-components/src/components/Accordion/index.ts (2)

1-1: Clean and standard export syntax

The barrel export follows best practices for component organization.


1-1: Verify AccordionPromo implementation

Let's ensure the new component is properly defined and documented.

✅ Verification successful

AccordionPromo implementation is complete and well-documented

The component is properly implemented with:

  • Full TypeScript interface definition
  • Comprehensive documentation in MDX
  • Multiple usage examples in stories
  • Proper component implementation with all necessary props
  • Correct export setup
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify AccordionPromo implementation and documentation

# Check if AccordionPromo is defined in Accordion.tsx
ast-grep --pattern 'export const AccordionPromo = $_'

# Check for documentation
fd -e mdx -e md . | xargs rg -l "AccordionPromo"

Length of output: 894


Script:

#!/bin/bash
# Let's check the actual implementation of AccordionPromo component
ast-grep --pattern 'export const AccordionPromo: React.FC = $_'

# Check the content of the documentation file
cat packages/react-components/src/components/Accordion/Accordion.mdx

# Check if AccordionPromo is properly exported from the main file
ast-grep --pattern 'export { $$$, AccordionPromo, $$$ } from $_'

Length of output: 1742


Script:

#!/bin/bash
# Let's check the actual implementation in the Accordion.tsx file
cat packages/react-components/src/components/Accordion/Accordion.tsx

# And check if there are any tests for AccordionPromo
fd -e test -e spec . | xargs rg -l "AccordionPromo"

Length of output: 4726


Script:

#!/bin/bash
# Let's check the types for AccordionPromo
cat packages/react-components/src/components/Accordion/types.ts

# And check the stories implementation
cat packages/react-components/src/components/Accordion/Accordion.stories.tsx

Length of output: 7646

packages/react-components/src/components/Accordion/types.ts (1)

Line range hint 9-25: LGTM! Verify interface rename impact

The rename to IAccordionGlobalProps and addition of footer property are well structured.

✅ Verification successful

Interface rename is properly implemented

The rename from IAccordionProps to IAccordionGlobalProps is correctly handled:

  • IAccordionProps now extends IAccordionGlobalProps
  • All imports and usages are consistent with this hierarchy
  • No orphaned exports or imports found
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify all usages of the renamed interface have been updated
rg "IAccordionProps" --type ts

Length of output: 619


Script:

#!/bin/bash
# Check if IAccordionProps is used in any exports or imports
ast-grep --pattern 'export { $$$ IAccordionProps $$$ }'
ast-grep --pattern 'import { $$$ IAccordionProps $$$ }'

# Check the implementation to understand the interface hierarchy
ast-grep --pattern 'interface IAccordionProps extends IAccordionGlobalProps { $$$ }'

Length of output: 740

packages/react-components/src/components/Accordion/Accordion.mdx (1)

9-9: LGTM! Clear navigation structure

The navigation links provide easy access to all major sections of the documentation.

packages/react-components/src/components/Accordion/Accordion.module.scss (4)

42-45: LGTM! Proper use of design system variables

The promotional variant styling maintains consistency with the design system.


68-70: Verify chevron positioning with design specs

The chevron's top position is adjusted by 4px. Please ensure this matches the Figma specs.


82-85: LGTM! Consistent spacing usage

The padding adjustments use proper design system spacing variables.


102-104: LGTM! Consistent padding with label

The content padding matches the label's padding, maintaining visual harmony.

packages/react-components/src/components/Accordion/Accordion.stories.tsx (4)

10-15: Clean component organization!

The Typography imports and AccordionPromo subcomponent registration align perfectly with the new promo variant requirements.

Also applies to: 23-25


127-133: Basic example looks good!

Clean implementation of the basic AccordionPromo story.


135-194: Well-structured examples with comprehensive coverage

The examples effectively demonstrate all component variants and features. Good use of Typography components for consistent styling.


143-149: Consider accessibility implications of heading structure

The as="div" with size="xs" might affect document outline. Consider using semantic heading levels that match the content hierarchy.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (1)
packages/react-components/src/components/Accordion/Accordion.tsx (1)

62-75: Simplify buildHeader implementation

The props spreading logic can be simplified by moving common props to a base object.

  const buildHeader = (isPromo?: boolean) => {
    const Component = isPromo ? Heading : Text;
-   const props = {
+   const baseProps = {
      'aria-expanded': isExpanded,
      as: 'div',
      className: cx(styles[`${baseClass}__label`], {
        [styles[`${baseClass}__label--promo`]]: isPromo,
      }),
      onClick: () => handleExpandChange(isExpanded),
-     bold: !isPromo ? true : undefined,
-     ...(isPromo ? { size: 'xs' as TTextSize } : {}),
    };
+   const props = isPromo 
+     ? { ...baseProps, size: 'xs' as TTextSize }
+     : { ...baseProps, bold: true };

    return <Component {...props}>{getLabel(label, isExpanded)}</Component>;
  };
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 9aa4e99 and a5690cc.

📒 Files selected for processing (2)
  • packages/react-components/src/components/Accordion/Accordion.tsx (4 hunks)
  • packages/react-components/src/components/Accordion/types.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/react-components/src/components/Accordion/types.ts
🔇 Additional comments (2)
packages/react-components/src/components/Accordion/Accordion.tsx (2)

136-150: Well-structured component separation

The split into separate Accordion and AccordionPromo components provides better type safety and maintainability than parameterization.


Line range hint 79-83: Move keyboard handler to interactive elements

The onKeyDown handler should be on the same elements that have role="button" for proper keyboard accessibility.

This issue was previously raised and needs to be addressed. Move the onKeyDown handler from the outer div to the header component in the buildHeader function.

marcinsawicki and others added 2 commits November 26, 2024 13:44
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (3)
packages/react-components/src/components/Accordion/Accordion.tsx (3)

136-136: Move constant declaration to the top

The baseClass constant should be defined before the components for better code organization.

-const baseClass = 'accordion';  // current position
+const baseClass = 'accordion';  // move to top, after imports
 
 const AccordionComponent: React.FC<IAccordionComponentProps> = ({

62-75: Memoize buildHeader function

The buildHeader function is recreated on every render but its logic depends only on isPromo, isExpanded, and label.

+const buildHeader = React.useCallback(
   (isPromo?: boolean) => {
     const Component = isPromo ? Heading : Text;
     const props = {
       'aria-expanded': isExpanded,
       as: 'div',
       className: cx(styles[`${baseClass}__label`], {
         [styles[`${baseClass}__label--promo`]]: isPromo,
       }),
       onClick: () => handleExpandChange(isExpanded),
       bold: !isPromo ? true : undefined,
       ...(isPromo ? { size: 'xs' as TTextSize } : {}),
     };
     return <Component {...props}>{getLabel(label, isExpanded)}</Component>;
   },
+  [isExpanded, label, handleExpandChange]
+);

Line range hint 79-84: Move keyboard handler to interactive elements

The onKeyDown handler should be on the same elements that have the interactive roles (the header components) rather than the outer div.

 <div
   tabIndex={0}
-  aria-expanded={isExpanded}
   className={mergedClassName}
-  onKeyDown={handleKeyDown}
   {...props}
 >

Then update the buildHeader function:

   const props = {
     'aria-expanded': isExpanded,
     as: 'div',
     className: cx(styles[`${baseClass}__label`], {
       [styles[`${baseClass}__label--promo`]]: isPromo,
     }),
     onClick: () => handleExpandChange(isExpanded),
+    onKeyDown: handleKeyDown,
     bold: !isPromo ? true : undefined,
     ...(isPromo ? { size: 'xs' as TTextSize } : {}),
   };
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between a5690cc and 1b844d8.

📒 Files selected for processing (2)
  • packages/react-components/src/components/Accordion/Accordion.spec.tsx (3 hunks)
  • packages/react-components/src/components/Accordion/Accordion.tsx (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/react-components/src/components/Accordion/Accordion.spec.tsx
🔇 Additional comments (1)
packages/react-components/src/components/Accordion/Accordion.tsx (1)

138-152: Clean implementation of component variants

The separation into Accordion and AccordionPromo components with shared base functionality is well done. This addresses the previous feedback about component parameterization.

@marcinsawicki marcinsawicki merged commit 75e7e14 into main Nov 26, 2024
6 checks passed
@marcinsawicki marcinsawicki deleted the feature/1346 branch November 26, 2024 13:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or request
Projects
Development

Successfully merging this pull request may close these issues.

[Accordion] - new variants
3 participants