-
Notifications
You must be signed in to change notification settings - Fork 3
Create ResponsiveComponent Block
#1106
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
+75
−26
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
3c4bb09
Add Responsive Component Component
jimwei1 a66e81c
Update ResponsiveComponent.tsx
jimwei1 26e0004
Update src/components/ui/ResponsiveComponent/ResponsiveComponent.tsx
jimwei1 e2d5b5c
Update src/components/ui/ResponsiveComponent/responsiveComponent.scss
jimwei1 518f17f
Remove `currentVariant` from `handleResize` dependency array
jimwei1 259c347
Update ResponsiveComponent.tsx
jimwei1 6f127da
Add immediate first callback on useElementSize
jimwei1 e94db9f
move isFirstCallback to local variable
jimwei1 f06dd2c
Merge branch 'main' into zjw/responsive-component
jimwei1 7b1a41d
Refactor useElementSize
jimwei1 3335877
Update useElementSize.ts
jimwei1 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
36 changes: 36 additions & 0 deletions
36
src/components/ui/ResponsiveComponent/ResponsiveComponent.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| import { type ReactNode, useCallback, useState } from 'react' | ||
|
|
||
| import { type ElementSize, useElementSize } from '@hooks/useElementSize/useElementSize' | ||
|
|
||
| import './responsiveComponent.scss' | ||
|
|
||
| export type DefaultVariant = 'Desktop' | 'SmallDesktop' | 'Mobile' | ||
|
|
||
| export type VariantResolver<T extends string> = ({ width }: { width: number }) => T | ||
|
|
||
| export interface ResponsiveComponentProps<T extends string = DefaultVariant> { | ||
| slots: Record<T, ReactNode> | ||
| resolveVariant: VariantResolver<T> | ||
| } | ||
|
|
||
| export const ResponsiveComponent = <T extends string = DefaultVariant>({ | ||
| slots, | ||
| resolveVariant, | ||
| }: ResponsiveComponentProps<T>) => { | ||
| const [currentVariant, setCurrentVariant] = useState<T | null>(null) | ||
jimwei1 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| const handleResize = useCallback((size: ElementSize) => { | ||
| setCurrentVariant(resolveVariant({ width: size.width })) | ||
| }, [resolveVariant]) | ||
|
|
||
| const containerRef = useElementSize<HTMLDivElement>(handleResize) | ||
|
|
||
| return ( | ||
| <div | ||
| ref={containerRef} | ||
| className='Layer__ResponsiveComponent' | ||
| > | ||
| {currentVariant !== null && slots[currentVariant]} | ||
jimwei1 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| </div> | ||
| ) | ||
| } | ||
4 changes: 4 additions & 0 deletions
4
src/components/ui/ResponsiveComponent/responsiveComponent.scss
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| .Layer__ResponsiveComponent { | ||
| height: 100%; | ||
| width: 100%; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,49 +1,58 @@ | ||
| import { useLayoutEffect, useRef } from 'react' | ||
|
|
||
| export interface ElementSize { | ||
| width: number | ||
| height: number | ||
| } | ||
|
|
||
| export const useElementSize = <T extends HTMLElement>( | ||
| callback: ( | ||
| target: T, | ||
| entry: ResizeObserverEntry, | ||
| size: { | ||
| width: number | ||
| height: number | ||
| clientWidth: number | ||
| clientHeight: number | ||
| }, | ||
| ) => void, | ||
| callback: (size: ElementSize) => void, | ||
| ) => { | ||
| const ref = useRef<T>(null) | ||
| const callbackRef = useRef(callback) | ||
| const isFirstRender = useRef(true) | ||
| const resizeTimeout = useRef<number | null>(null) | ||
|
|
||
| callbackRef.current = callback | ||
|
|
||
| useLayoutEffect(() => { | ||
| const element = ref?.current | ||
|
|
||
| if (!element) { | ||
| return | ||
| if (!element) return | ||
|
|
||
| const invokeCallback = ({ width, height }: ElementSize) => { | ||
| callbackRef.current({ width, height }) | ||
| } | ||
|
|
||
| if (isFirstRender.current) { | ||
| const rect = element.getBoundingClientRect() | ||
| invokeCallback({ | ||
| width: rect.width, | ||
| height: rect.height, | ||
| }) | ||
| isFirstRender.current = false | ||
| } | ||
|
|
||
| const observer = new ResizeObserver((entries) => { | ||
| const width = entries[0].borderBoxSize[0].inlineSize | ||
| const height = entries[0].borderBoxSize[0].blockSize | ||
|
|
||
| if (resizeTimeout.current) { | ||
| clearTimeout(resizeTimeout.current) | ||
| } | ||
| resizeTimeout.current = window.setTimeout(() => { | ||
| const entry = entries[0] | ||
| callback(element, entry, { | ||
| width: element.offsetWidth, | ||
| height: element.offsetHeight, | ||
| clientWidth: element.clientWidth, | ||
| clientHeight: element.clientHeight, | ||
| }) | ||
| invokeCallback({ width, height }) | ||
| }, 100) | ||
| }) | ||
|
|
||
| observer.observe(element) | ||
|
|
||
| return () => { | ||
| observer.disconnect() | ||
| if (resizeTimeout.current) { | ||
| clearTimeout(resizeTimeout.current) | ||
| } | ||
| } | ||
| }, [callback, ref]) | ||
|
|
||
| }, []) | ||
| return ref | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed truthy check allows zero width update
Low Severity
The condition was changed from
c.width && c?.width !== currentWidthtosize.width !== currentWidth, removing the truthy check on width. Previously, when the element's width became 0 (e.g., when hidden),currentWidthwould retain its last non-zero value. Now it will update to 0, which triggersupdateSelectPositionvia theuseEffectdependency oncurrentWidth. This could cause incorrect thumb positioning calculations when the tabs component is temporarily hidden and then shown again.