Skip to content

Commit

Permalink
Merge pull request #2745 from SUI-Components/feat/behavior-sticky-sha…
Browse files Browse the repository at this point in the history
…re-state

feat: BehaviorSticky sharing isSticky state
  • Loading branch information
aarronte86 committed Jun 27, 2024
2 parents 7f06e7d + a214bd3 commit aca31e9
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 30 deletions.
52 changes: 31 additions & 21 deletions components/behavior/sticky/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,44 @@ $ npm install @s-ui/react-behavior-sticky --save
## Usage

```js
import BehaviorSticky, {
BehaviorStickyProvider
} from '@s-ui/react-behavior-sticky'
import BehaviorSticky, {BehaviorStickyProvider} from '@s-ui/react-behavior-sticky'
```

### Basic usage (Fixed at top)

```js
<BehaviorStickyProvider>
...
<BehaviorSticky>
<HeaderFixed />
</BehaviorSticky>
...
</BehaviorStickyProvider>
<BehaviorStickyProvider>
...
<BehaviorSticky>
<HeaderFixed />
</BehaviorSticky>
...
</BehaviorStickyProvider>
```

### Sticky state

```js
<BehaviorStickyProvider>
...
<BehaviorSticky>{({isSticky}) => <HeaderFixed variant={isSticky ? 'sticky' : 'default'} />}</BehaviorSticky>
...
</BehaviorStickyProvider>
```

### Sticky per container

```js
<BehaviorStickyProvider>
...
<div ref={container1}>
<BehaviorSticky container={container1} defaultOffsetTop={45} animate>
<HeaderWithButtons className={CLASS_DEMO_FIXED_BUTTONS} />
</BehaviorSticky>
<Content className={CLASS_DEMO_CONTENT} />
</div>
...
</BehaviorStickyProvider>
<BehaviorStickyProvider>
...
<div ref={container1}>
<BehaviorSticky container={container1} defaultOffsetTop={45} animate>
<HeaderWithButtons className={CLASS_DEMO_FIXED_BUTTONS} />
</BehaviorSticky>
<Content className={CLASS_DEMO_CONTENT} />
</div>
...
</BehaviorStickyProvider>
```

> **Find full description and more examples in the [demo page](https://sui-components.now.sh/workbench/behavior/sticky/demo).**
> **Find full description and more examples in the [demo page](https://sui-components.now.sh/workbench/behavior/sticky/demo).**
52 changes: 52 additions & 0 deletions components/behavior/sticky/demo/articles/ArticleStickyState.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {useRef} from 'react'

import PropTypes from 'prop-types'

import {Article, Bold, Box, Code, H2, Paragraph} from '@s-ui/documentation-library'

import BehaviorSticky, {BehaviorStickyProvider} from '../../src/index.js'
import LoremIpsum from '../LoremIpsum.js'
import {CLASS_DEMO_PLACEHOLDER} from '../settings.js'

const ArticleStickyState = ({className}) => {
const ref = useRef()
return (
<Article className={className}>
<H2>Sticky State</H2>
<Paragraph>
The <Code>BehaviorSticky</Code> allow us to know when the component given gets sticky. Using{' '}
<Code>children</Code> as a <Code>function</Code>, a parameter called <Code>isSticky</Code> is shared with the
current state. It allows rendering the sticky component with different variants depending on the{' '}
<Code>isSticky</Code> state.
</Paragraph>
<BehaviorStickyProvider>
<Box className={CLASS_DEMO_PLACEHOLDER} ref={ref} outline style={{overflowY: 'hidden'}}>
<BehaviorSticky container={ref}>
{({isSticky}) => (
<Box outline mode={isSticky && 'dark'}>
<Bold>{`The element wrapped by a BehaviorSticky is ${!isSticky ? 'not ' : ''}sticky`}.</Bold>
</Box>
)}
</BehaviorSticky>
<Paragraph>
<LoremIpsum count={10} format="plain" />
</Paragraph>
<Paragraph>
<LoremIpsum count={10} format="plain" />
</Paragraph>
<Paragraph>
<LoremIpsum count={10} format="plain" />
</Paragraph>
</Box>
</BehaviorStickyProvider>
</Article>
)
}

ArticleStickyState.displayName = 'ArticleStickyState'

ArticleStickyState.propTypes = {
className: PropTypes.string
}

export default ArticleStickyState
3 changes: 3 additions & 0 deletions components/behavior/sticky/demo/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import ArticleDefault from './articles/ArticleDefault.js'
import ArticleGridDemo from './articles/ArticleGridDemo.js'
import ArticleScrollUp from './articles/ArticleScrollUp.js'
import ArticleStacked from './articles/ArticleStacked.js'
import ArticleStickyState from './articles/ArticleStickyState.js'
import LoremIpsum from './LoremIpsum.js'
import {BASE_CLASS_DEMO, CLASS_DEMO_SECTION} from './settings.js'

Expand All @@ -33,6 +34,8 @@ const Demo = () => (
</UnorderedList>
<ArticleDefault className={CLASS_DEMO_SECTION} />
<br />
<ArticleStickyState className={CLASS_DEMO_SECTION} />
<br />
<ArticleScrollUp className={CLASS_DEMO_SECTION} />
<br />
<ArticleStacked className={CLASS_DEMO_SECTION} />
Expand Down
10 changes: 8 additions & 2 deletions components/behavior/sticky/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,24 @@ import PropTypes from 'prop-types'
import {BASE_CLASS, CLASS_ANIMATE} from './settings.js'
import BehaviorStickyScrollUp from './StickyScrollUp.js'

const isFunction = children => typeof children === 'function'

const BehaviorSticky = ({children, animate, ...props}) => {
return (
<Sticky className={BASE_CLASS} {...props}>
{({isSticky}) => <div className={cx({[CLASS_ANIMATE]: isSticky && animate})}>{children}</div>}
{({isSticky}) => (
<div className={cx({[CLASS_ANIMATE]: isSticky && animate})}>
{isFunction(children) ? children({isSticky}) : children}
</div>
)}
</Sticky>
)
}

BehaviorSticky.displayName = 'BehaviorSticky'

BehaviorSticky.propTypes = {
children: PropTypes.node,
children: PropTypes.oneOf([PropTypes.node, PropTypes.func]),
animate: PropTypes.bool,
container: PropTypes.exact({
current: PropTypes.object
Expand Down
11 changes: 4 additions & 7 deletions components/behavior/sticky/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,18 +70,15 @@ describe(json.name, () => {
expect(container.innerHTML).to.not.have.lengthOf(0)
})

it.skip('example', () => {
// Example TO BE DELETED!!!!

it('should allow knowing the sticky current state', () => {
// Given
// const props = {}
const props = {children: ({isSticky}) => <h1>{`Sticky position is ${isSticky}`}</h1>}

// When
// const {getByRole} = setup(props)
const {getByRole} = setup(props)

// Then
// expect(getByRole('button')).to.have.text('HOLA')
expect(true).to.be.eql(false)
expect(getByRole('heading')).to.have.text('Sticky position is false')
})
})
})

0 comments on commit aca31e9

Please sign in to comment.