Skip to content

Commit

Permalink
feat(usebreakpoint): useBreakpoint (#69)
Browse files Browse the repository at this point in the history
* feat(usebreakpoint): useBreakpoint 

---------

Co-authored-by: Thinh Trinh <thitri@on.sinch.com>
  • Loading branch information
trinhthinh388 and Thinh Trinh authored Feb 15, 2024
1 parent fdfd78c commit 7450a9d
Show file tree
Hide file tree
Showing 23 changed files with 714 additions and 9 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,10 @@ jobs:
token: ${{ secrets.CODECOV_TOKEN }}
flags: useToggle
files: ./packages/use-toggle/coverage/coverage-final.json

- name: Upload `useBreakpoint` coverage reports to Codecov
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: useBreakpoint
files: ./packages/use-breakpoint/coverage/coverage-final.json
4 changes: 4 additions & 0 deletions apps/docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,21 @@
"dependencies": {
"@react-awesome/components": "1.0.8",
"classnames": "^2.5.1",
"lodash": "^4.17.21",
"lucide-react": "^0.315.0",
"next": "^14.0.4",
"nextra": "^2.13.2",
"nextra-theme-docs": "^2.13.2",
"re-resizable": "^6.9.11",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-resizable-panels": "^2.0.3",
"remark-mdx-disable-explicit-jsx": "^0.1.0"
},
"devDependencies": {
"@react-awesome/eslint-config": "*",
"@react-awesome/tsconfig": "*",
"@types/lodash": "^4.14.202",
"@types/node": "^20.10.6",
"@types/react": "^18.2.46",
"@types/react-dom": "^18.2.18",
Expand Down
46 changes: 43 additions & 3 deletions apps/docs/src/components/Container.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,43 @@
export const Container = ({ children }: { children: React.ReactNode }) => (
<div className="mt-5 border rounded-lg p-4">{children}</div>
)
import classNames from 'classnames'
import { Resizable } from 're-resizable'

export const Container = ({
children,
showSizeHandler = false,
}: {
children: React.ReactNode
showSizeHandler?: boolean
}) => {
if (showSizeHandler) {
return (
<Resizable
bounds="parent"
enable={{
right: true,
}}
maxWidth="98%"
minWidth="30%"
handleComponent={{
right: (
<div
className="pointer-events-auto absolute top-1/2 -translate-y-1/2 hidden ml-3 md:block cursor-ew-resize"
draggable={false}
style={{
userSelect: 'none',
touchAction: 'pan-y',
}}
>
<div className="w-1.5 h-8 bg-slate-500/60 rounded-full"></div>
</div>
),
}}
>
<div className={classNames('mt-5 border rounded-lg p-4')}>
{children}
</div>
</Resizable>
)
}

return <div className="mt-5 border rounded-lg p-4">{children}</div>
}
3 changes: 3 additions & 0 deletions apps/docs/src/pages/docs/_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
"use-previous": {
"title": "usePrevious"
},
"use-breakpoint": {
"title": "useBreakpoint"
},
"use-click-outside": {
"title": "useClickOutside"
},
Expand Down
298 changes: 298 additions & 0 deletions apps/docs/src/pages/docs/use-breakpoint.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,298 @@
---
title: useBreakpoint
---

# useBreakpoint

**useBreakpoint** returns the current breakpoint of a element, contains useful utilities to work with user-defined breakpoints and automatically triggers
callback when the element's size is equal to a specific breakpoint.

## Install

To start using **useBreakpoint**, you can install the `@react-awesome/use-breakpoint` library or you can import it directly from `@react-awesome/components` if you have installed it before. In your project directory, run
the following command to install the dependencies:

```sh npm2yarn
npm i @react-awesome/use-breakpoint
```

## Usage

import { useState } from 'react'
import { Container } from '../../components/Container'
import { useBreakpoint } from '@react-awesome/components'

export const Example = () => {
const [ref, setRef] = useState(null)

const { currentBreakpoint } = useBreakpoint(ref, {
breakpoints: {
sm: 320,
md: 480,
lg: 640
},
callbacks: {}
})

return (

<div ref={setRef} className="w-full flex items-center justify-center">
<div className="h-32 w-full max-w-32 flex items-center justify-center p-0.5 overflow-hidden text-xl font-medium text-gray-900 rounded-lg group bg-gradient-to-br from-purple-600 to-blue-500 group-hover:from-purple-600 group-hover:to-blue-500 hover:text-white dark:text-white focus:ring-4 focus:outline-none focus:ring-blue-300 dark:focus:ring-blue-800">
{currentBreakpoint}
</div>
</div>
) }

By default, **useBreakpoint** has the same breakpoint configs with [TailwindCSS](https://tailwindcss.com/docs/responsive-design).
But you can freely use any configs that best suit your case.

<Container showSizeHandler>
<Example />
</Container>

```jsx
import { useBreakpoint } from '@react-awesome/use-breakpoint'

const Example = () => {
const ref = useRef(null)

const { currentBreakpoint } = useBreakpoint(ref.curent)

return (
<div ref={ref}>
<div>{currentBreakpoint}</div>
</div>
)
}
```

## Custom breakpoint configs

export const ExampleWithCustomConfig = () => {
const [ref, setRef] = useState(null)

const { currentBreakpoint } = useBreakpoint(ref, {
breakpoints: {
"📱": 320,
"💻": 480,
"🖥️": 640
},
callbacks: {}
})

return (

<div ref={setRef} className="w-full flex items-center justify-center">
<div className="h-32 w-full max-w-32 flex items-center justify-center p-0.5 overflow-hidden text-xl font-medium text-gray-900 rounded-lg group bg-gradient-to-br from-purple-600 to-blue-500 group-hover:from-purple-600 group-hover:to-blue-500 hover:text-white dark:text-white focus:ring-4 focus:outline-none focus:ring-blue-300 dark:focus:ring-blue-800">
{currentBreakpoint}
</div>
</div>
) }

<Container showSizeHandler>
<ExampleWithCustomConfig />
</Container>

```jsx
import { useBreakpoint } from '@react-awesome/use-breakpoint'

const Example = () => {
const ref = useRef(null)

const { currentBreakpoint } = useBreakpoint(ref.curent, {
breakpoints: {
'📱': 320,
'💻': 480,
'🖥️': 640,
},
})

return (
<div ref={ref}>
<div>{currentBreakpoint}</div>
</div>
)
}
```

## Breakpoint utilities

**useBreakpoint** returns some utilities to assert with the current container's size:

- `smaller`
- `greater`
- `smallerOrEqual`
- `greaterOrEqual`
- `between`

export const ExampleUseUtilities = () => {
const [ref, setRef] = useState(null)

const { smaller } = useBreakpoint(ref, {
breakpoints: {
sm: 320,
md: 480,
lg: 640
},
callbacks: {}
})

return (

<div ref={setRef} className="w-full flex flex-col items-center justify-center">
<p className="text-center text-lg font-semibold">
Shrink the container to see the alien!
</p>
<p className="text-2xl mt-3">{smaller('md') && '👽'}</p>
</div>
) }

<Container showSizeHandler>
<ExampleUseUtilities />
</Container>

```jsx
import { useBreakpoint } from '@react-awesome/use-breakpoint'

const Example = () => {
const ref = useRef(null)

const { smaller } = useBreakpoint(ref.curent)

return (
<div ref={setRef}>
<p>Shrink the container to see the alien!</p>
<p>{smaller('md') && '👽'}</p>
</div>
)
}
```

## Callbacks

**useBreakpoint** also supports to trigger provided callback on a specific breakpoint.

export const ExampleWithCallback = () => {
const [ref, setRef] = useState(null)
const [background, setBg] = useState('red')

useBreakpoint(ref, {
breakpoints: {
sm: 320,
md: 480,
lg: 640
},
callbacks: {
sm: () => setBg('red'),
md: () => setBg('green'),
lg: () => setBg('blue')
}
})

return (

<div ref={setRef} className="w-full flex flex-col items-center justify-center">
<p className="text-center text-lg font-semibold">
The background will change when container's size is changed
</p>
<div
style={{
background,
}}
className="h-32 mt-6 w-full max-w-32 flex items-center justify-center p-0.5 overflow-hidden text-xl font-medium text-gray-900 rounded-lg"
/>
</div>
) }

<Container showSizeHandler>
<ExampleWithCallback />
</Container>

```jsx
import { useBreakpoint } from '@react-awesome/use-breakpoint'

const Example = () => {
const ref = useRef(null)
const [background, setBg] = useState('red')

useBreakpoint(ref, {
breakpoints: {
sm: 320,
md: 480,
lg: 640,
},
callbacks: {
sm: () => setBg('red'),
md: () => setBg('green'),
lg: () => setBg('blue'),
},
})

return (
<>
<div ref={setRef}>
<p> The background will change when container's size is changed</p>
</div>
<div
style={{
background,
}}
/>
</>
)
}
```
## Parameters
The `useBreakpoint` takes the following parameters:
#### `containerEl`
- Type: `HTMLElement`
#### `Options`
- Type: `UseBreakpointOpts`
## API
#### `currentBreakpoint`
- Type: `string`
#### `smaller`
- Type: `(breakpoint: string) => boolean`
#### `smallerOrEqual`
- Type: `(breakpoint: string) => boolean`
#### `greater`
- Type: `(breakpoint: string) => boolean`
#### `greaterOrEqual`
- Type: `(breakpoint: string) => boolean`
#### `between`
- Type: `(breakpoint: string) => boolean`
## Types
#### `UseBreakpointOpts`
###### `breakpoints`
- Type: `Record<string, number>`
##### `callbacks`
- Type: `Record<string, () => void>`
##### `fallbackValue`
- Type: string
3 changes: 2 additions & 1 deletion packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"@react-awesome/use-preserve-input-caret-position": "0.0.3",
"@react-awesome/use-selection-range": "0.0.3",
"@react-awesome/use-previous": "0.0.3",
"@react-awesome/use-toggle": "0.0.1"
"@react-awesome/use-toggle": "0.0.1",
"@react-awesome/use-breakpoint": "0.0.0"
}
}
Loading

0 comments on commit 7450a9d

Please sign in to comment.