-
Notifications
You must be signed in to change notification settings - Fork 74
[LG-844] feat(collection-toolbar): CollectionToolbar Title SubComponent #3420
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
Changes from 3 commits
98da991
9279070
d84c9e2
526097c
a20fa54
517b874
9e650ea
ae26238
b4711fc
9010485
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| # PR Title | ||
|
|
||
| `[LG-5844] feat(collection-toolbar): add CollectionToolbarTitle compound component` | ||
|
|
||
| --- | ||
|
|
||
| # PR Description | ||
|
|
||
| ## ✍️ Proposed changes | ||
|
|
||
| This PR introduces the `CollectionToolbarTitle` compound component for the `CollectionToolbar` package. The title component: | ||
|
|
||
| - Uses the compound component pattern (`CompoundComponent` and `CompoundSubComponent` utilities) to integrate seamlessly with the parent `CollectionToolbar` | ||
| - Renders an `H3` typography element for the title content | ||
| - Only displays when the `CollectionToolbar` variant is set to `Collapsible` | ||
| - Exports `Size` and `Variant` enums for better component API ergonomics | ||
|
|
||
| Additionally, this PR improves the Storybook configuration with proper `StoryMetaType`, argument types, and a `LiveExample` story that demonstrates the title component usage. | ||
|
|
||
| 🎟️ _Jira ticket:_ [LG-5844](https://jira.mongodb.org/browse/LG-5844) | ||
|
|
||
| ## ✅ Checklist | ||
|
|
||
| - [ ] I have added stories/tests that prove my fix is effective or that my feature works | ||
| - [ ] I have added necessary documentation (if appropriate) | ||
| - [ ] I have run `pnpm changeset` and documented my changes | ||
|
|
||
| ## 🧪 How to test changes | ||
|
|
||
| 1. Run `pnpm storybook` and navigate to **Components / CollectionToolbar** | ||
| 2. View the **LiveExample** story to see the `CollectionToolbar.Title` in action | ||
| 3. Toggle the `variant` control to `Collapsible` - the title should appear | ||
| 4. Toggle the `variant` control to `Default` - the title should be hidden | ||
| 5. Verify that the title renders correctly with different `size` and `darkMode` combinations | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,38 @@ | ||
| import React from 'react'; | ||
| import { render, screen } from '@testing-library/react'; | ||
|
|
||
| import { CollectionToolbar } from '.'; | ||
| import { CollectionToolbar, Variant } from '.'; | ||
|
|
||
| describe('packages/collection-toolbar', () => { | ||
| test('renders correctly', () => { | ||
| render(<CollectionToolbar>Collection Toolbar</CollectionToolbar>); | ||
| expect(screen.getByText('Collection Toolbar')).toBeInTheDocument(); | ||
| render(<CollectionToolbar />); | ||
| expect(screen.getByTestId('lg-collection_toolbar')).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| test('applies className to the root element', () => { | ||
| render(<CollectionToolbar className="test-class" />); | ||
| expect(screen.getByTestId('lg-collection_toolbar')).toHaveClass( | ||
| 'test-class', | ||
| ); | ||
| }); | ||
|
|
||
| describe('variant: collapsible', () => { | ||
| test('renders title when variant is collapsible', () => { | ||
| render( | ||
| <CollectionToolbar variant={Variant.Collapsible}> | ||
| <CollectionToolbar.Title>Test Title</CollectionToolbar.Title> | ||
| </CollectionToolbar>, | ||
| ); | ||
| expect(screen.getByText('Test Title')).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| test('does not render title when variant is not collapsible', () => { | ||
| render( | ||
| <CollectionToolbar variant={Variant.Default}> | ||
| <CollectionToolbar.Title>Test Title</CollectionToolbar.Title> | ||
| </CollectionToolbar>, | ||
| ); | ||
| expect(screen.queryByText('Test Title')).not.toBeInTheDocument(); | ||
| }); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,23 +1,50 @@ | ||
| import React from 'react'; | ||
|
|
||
| import { | ||
| CompoundComponent, | ||
| findChild, | ||
| } from '@leafygreen-ui/compound-component'; | ||
|
|
||
| import { getLgIds } from '../utils/getLgIds'; | ||
|
|
||
| import { getCollectionToolbarStyles } from './CollectionToolbar.styles'; | ||
| import { | ||
| CollectionToolbarProps, | ||
| CollectionToolbarSubComponentProperty, | ||
| Size, | ||
| Variant, | ||
| } from './CollectionToolbar.types'; | ||
| import { CollectionToolbarTitle } from './CollectionToolbarTitle'; | ||
adamrasheed marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| export const CollectionToolbar = CompoundComponent( | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we want to include a
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is wrapped in |
||
| ({ | ||
| size = Size.Default, | ||
| variant = Variant.Default, | ||
| className, | ||
| children, | ||
| }: CollectionToolbarProps) => { | ||
| const lgIds = getLgIds(); | ||
| const title = findChild( | ||
| children, | ||
| CollectionToolbarSubComponentProperty.Title, | ||
| ); | ||
|
|
||
| const showTitle = title && variant === Variant.Collapsible; | ||
|
|
||
| export function CollectionToolbar({ | ||
| size = Size.Default, | ||
| variant = Variant.Default, | ||
| className, | ||
| children, | ||
| }: CollectionToolbarProps) { | ||
| return ( | ||
| <div className={getCollectionToolbarStyles({ size, variant, className })}> | ||
| {children} | ||
| </div> | ||
| ); | ||
| } | ||
| return ( | ||
| <div | ||
adamrasheed marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| data-testid={lgIds.root} | ||
adamrasheed marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| className={getCollectionToolbarStyles({ size, variant, className })} | ||
adamrasheed marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| > | ||
| {showTitle && title} | ||
| CollectionToolbar | ||
adamrasheed marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| </div> | ||
| ); | ||
| }, | ||
| { | ||
| displayName: 'CollectionToolbar', | ||
| Title: CollectionToolbarTitle, | ||
| }, | ||
adamrasheed marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ); | ||
|
|
||
| CollectionToolbar.displayName = 'CollectionToolbar'; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| import React from 'react'; | ||
| import { render, screen } from '@testing-library/react'; | ||
|
|
||
| import { CollectionToolbarSubComponentProperty } from '../CollectionToolbar.types'; | ||
|
|
||
| import CollectionToolbarTitle from './CollectionToolbarTitle'; | ||
|
|
||
| describe('packages/collection-toolbar/CollectionToolbarTitle', () => { | ||
| test('renders children correctly', () => { | ||
| render(<CollectionToolbarTitle>Test Title</CollectionToolbarTitle>); | ||
| expect(screen.getByText('Test Title')).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| test('renders as an h3 element', () => { | ||
| render(<CollectionToolbarTitle>Test Title</CollectionToolbarTitle>); | ||
| expect(screen.getByRole('heading', { level: 3 })).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| test('applies className to the rendered element', () => { | ||
| render( | ||
| <CollectionToolbarTitle className="custom-class"> | ||
| Test Title | ||
| </CollectionToolbarTitle>, | ||
| ); | ||
| expect(screen.getByText('Test Title')).toHaveClass('custom-class'); | ||
| }); | ||
|
|
||
| test('passes additional props to the rendered element', () => { | ||
| render( | ||
| <CollectionToolbarTitle data-testid="custom-test-id"> | ||
| Test Title | ||
| </CollectionToolbarTitle>, | ||
| ); | ||
| expect(screen.getByTestId('custom-test-id')).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| test('has the correct displayName', () => { | ||
adamrasheed marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| expect(CollectionToolbarTitle.displayName).toBe('CollectionToolbarTitle'); | ||
| }); | ||
|
|
||
| test('has the correct static property for compound component identification', () => { | ||
adamrasheed marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| expect( | ||
| CollectionToolbarTitle[CollectionToolbarSubComponentProperty.Title], | ||
| ).toBe(true); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| import React from 'react'; | ||
|
|
||
| import { CompoundSubComponent } from '@leafygreen-ui/compound-component'; | ||
| import { H3 } from '@leafygreen-ui/typography'; | ||
|
|
||
| import { CollectionToolbarSubComponentProperty } from '../CollectionToolbar.types'; | ||
|
|
||
| import { CollectionToolbarTitleProps } from './CollectionToolbarTitle.types'; | ||
|
|
||
| /** | ||
| * CollectionToolbarTitle is a compound component that renders a title for a collection toolbar. | ||
| * It will only render if the CollectionToolbar variant is set to Collapsible. | ||
| */ | ||
| const CollectionToolbarTitle = CompoundSubComponent( | ||
| ({ className, children, ...rest }: CollectionToolbarTitleProps) => ( | ||
| <H3 className={className} {...rest}> | ||
| {children} | ||
| </H3> | ||
| ), | ||
| { | ||
| displayName: 'CollectionToolbarTitle', | ||
| key: CollectionToolbarSubComponentProperty.Title, | ||
| }, | ||
| ); | ||
|
|
||
| CollectionToolbarTitle.displayName = 'CollectionToolbarTitle'; | ||
adamrasheed marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| export default CollectionToolbarTitle; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| import { ComponentPropsWithRef } from 'react'; | ||
|
|
||
| import { DarkModeProps } from '@leafygreen-ui/lib'; | ||
|
|
||
| export interface CollectionToolbarTitleProps | ||
| extends ComponentPropsWithRef<'h3'>, | ||
| DarkModeProps { | ||
adamrasheed marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| children?: React.ReactNode; | ||
| className?: string; | ||
adamrasheed marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| export { default as CollectionToolbarTitle } from './CollectionToolbarTitle'; | ||
| export { type CollectionToolbarTitleProps } from './CollectionToolbarTitle.types'; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| export { | ||
| CollectionToolbar, | ||
| type CollectionToolbarProps, | ||
| type CollectionToolbarTitleProps, | ||
| Size, | ||
| Variant, | ||
| } from './CollectionToolbar'; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,3 @@ | ||
| import React from 'react'; | ||
| import { render } from '@testing-library/react'; | ||
|
|
||
| import { CollectionToolbar } from '.'; | ||
|
|
||
| describe('packages/collection-toolbar/getTestUtils', () => { | ||
| test('condition', () => {}); | ||
| }); |
Uh oh!
There was an error while loading. Please reload this page.