Skip to content

Commit

Permalink
feat(react): add floating panel
Browse files Browse the repository at this point in the history
  • Loading branch information
mverissimo committed Aug 22, 2024
1 parent 2055ac0 commit da1bfaf
Show file tree
Hide file tree
Showing 30 changed files with 1,057 additions and 0 deletions.
90 changes: 90 additions & 0 deletions packages/react/.storybook/styles/floating-panel.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
[data-scope='floating-panel'] button {
appearance: none;
border: 1px solid black;
margin: 0;
padding: 0;
}
[data-scope='floating-panel'][data-part='content'] {
box-shadow:
rgba(0, 0, 0, 0.28) 0px 16px 18px 0px,
rgba(0, 0, 0, 0.12) 0px 4px 16px 0px;
outline: 0 !important;
background-color: white;
display: flex;
flex-direction: column;

&[data-topmost] {
z-index: 999999;
}

&[data-behind] {
opacity: 0.4;
}
}

[data-scope='floating-panel'][data-part='body'] {
position: relative;
overflow: auto;
flex: 1 1 auto;
padding-block: 16px;
padding-inline: 16px;
background-color: white;
}

[data-scope='floating-panel'][data-part='header'] {
padding-block: 16px;
padding-inline: 16px;
background-color: #f5f5f5;
border-bottom: 1px solid #ebebeb;
display: flex;
justify-content: space-between;
align-items: center;
}

[data-scope='floating-panel'][data-part='header'] button {
width: 24px;
height: 24px;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 14px;
padding: 0;
svg {
width: 1em;
height: 1em;
}
}

[data-scope='floating-panel'][data-part='trigger-group'] {
display: flex;
align-items: center;
gap: 8px;
}

[data-scope='floating-panel'][data-part='resize-trigger'] {
background-color: rgba(154, 18, 18, 0.396);

&[data-axis='n'],
&[data-axis='s'] {
height: 6px;
max-width: 90%;
}

&[data-axis='e'],
&[data-axis='w'] {
width: 6px;
max-height: 90%;
}

&[data-axis='ne'],
&[data-axis='nw'],
&[data-axis='se'],
&[data-axis='sw'] {
width: 10px;
height: 10px;
}
}

[hidden] {
display: none !important;
}
59 changes: 59 additions & 0 deletions packages/react/src/components/floating-panel/examples/basic.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import {
FloatingPanel,
FloatingPanelBody,
FloatingPanelCloseTrigger,
FloatingPanelContent,
FloatingPanelDragTrigger,
FloatingPanelHeader,
FloatingPanelMaximizeTrigger,
FloatingPanelMinimizeTrigger,
FloatingPanelPositioner,
FloatingPanelResizeTrigger,
FloatingPanelRestoreTrigger,
FloatingPanelTitle,
FloatingPanelTrigger,
Portal,
} from '../..'

import { ArrowDownLeft, Maximize2, Minus, XIcon } from 'lucide-react'

export const Basic = () => (
<FloatingPanel.Root>
<FloatingPanelTrigger>Toggle Panel</FloatingPanelTrigger>
<FloatingPanelPositioner>
<FloatingPanelContent>
<FloatingPanelDragTrigger>
<FloatingPanelHeader>
<FloatingPanelTitle>Floating Panel</FloatingPanelTitle>
<div data-scope="floating-panel" data-part="trigger-group">
<FloatingPanelMinimizeTrigger>
<Minus />
</FloatingPanelMinimizeTrigger>
<FloatingPanelMaximizeTrigger>
<Maximize2 />
</FloatingPanelMaximizeTrigger>
<FloatingPanelRestoreTrigger>
<ArrowDownLeft />
</FloatingPanelRestoreTrigger>
<FloatingPanelCloseTrigger>
<XIcon />
</FloatingPanelCloseTrigger>
</div>
</FloatingPanelHeader>
</FloatingPanelDragTrigger>
<FloatingPanelBody>
<p>Some content</p>
</FloatingPanelBody>

<FloatingPanelResizeTrigger axis="n" />
<FloatingPanelResizeTrigger axis="e" />
<FloatingPanelResizeTrigger axis="w" />
<FloatingPanelResizeTrigger axis="s" />
<FloatingPanelResizeTrigger axis="ne" />
<FloatingPanelResizeTrigger axis="se" />
<FloatingPanelResizeTrigger axis="sw" />
<FloatingPanelResizeTrigger axis="nw" />
</FloatingPanelContent>
</FloatingPanelPositioner>
</FloatingPanel.Root>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { useState } from 'react'
import {
FloatingPanel,
FloatingPanelBody,
FloatingPanelCloseTrigger,
FloatingPanelContent,
FloatingPanelDragTrigger,
FloatingPanelHeader,
FloatingPanelMaximizeTrigger,
FloatingPanelMinimizeTrigger,
FloatingPanelPositioner,
FloatingPanelResizeTrigger,
FloatingPanelRestoreTrigger,
FloatingPanelTitle,
FloatingPanelTrigger,
Portal,
} from '../..'

import { ArrowDownLeft, Maximize2, Minus, XIcon } from 'lucide-react'

export const Controlled = () => {
const [isOpen, setIsOpen] = useState(false)

return (
<FloatingPanel.Root open={isOpen} onOpenChange={(e) => setIsOpen(e.open)}>
<FloatingPanelTrigger onClick={() => setIsOpen(true)}>Toggle Panel</FloatingPanelTrigger>
<Portal>
<FloatingPanelPositioner>
<FloatingPanelContent>
<FloatingPanelDragTrigger>
<FloatingPanelHeader>
<FloatingPanelTitle>Floating Panel</FloatingPanelTitle>
<div data-scope="floating-panel" data-part="trigger-group">
<FloatingPanelMinimizeTrigger>
<Minus />
</FloatingPanelMinimizeTrigger>
<FloatingPanelMaximizeTrigger>
<Maximize2 />
</FloatingPanelMaximizeTrigger>
<FloatingPanelRestoreTrigger>
<ArrowDownLeft />
</FloatingPanelRestoreTrigger>
<FloatingPanelCloseTrigger>
<XIcon />
</FloatingPanelCloseTrigger>
</div>
</FloatingPanelHeader>
</FloatingPanelDragTrigger>
<FloatingPanelBody>
<p>Some content</p>
</FloatingPanelBody>

<FloatingPanelResizeTrigger axis="n" />
<FloatingPanelResizeTrigger axis="e" />
<FloatingPanelResizeTrigger axis="w" />
<FloatingPanelResizeTrigger axis="s" />
<FloatingPanelResizeTrigger axis="ne" />
<FloatingPanelResizeTrigger axis="se" />
<FloatingPanelResizeTrigger axis="sw" />
<FloatingPanelResizeTrigger axis="nw" />
</FloatingPanelContent>
</FloatingPanelPositioner>
</Portal>
</FloatingPanel.Root>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import {
FloatingPanel,
FloatingPanelBody,
FloatingPanelCloseTrigger,
FloatingPanelContent,
FloatingPanelDragTrigger,
FloatingPanelHeader,
FloatingPanelMaximizeTrigger,
FloatingPanelMinimizeTrigger,
FloatingPanelPositioner,
FloatingPanelResizeTrigger,
FloatingPanelRestoreTrigger,
FloatingPanelTitle,
FloatingPanelTrigger,
Portal,
} from '../..'

import { ArrowDownLeft, Maximize2, Minus, XIcon } from 'lucide-react'

export const LazyMount = () => (
<FloatingPanel.Root lazyMount onExitComplete={() => console.log('onExitComplete invoked')}>
<FloatingPanelTrigger>Toggle Panel</FloatingPanelTrigger>
<Portal>
<FloatingPanelPositioner>
<FloatingPanelContent>
<FloatingPanelDragTrigger>
<FloatingPanelHeader>
<FloatingPanelTitle>Floating Panel</FloatingPanelTitle>
<div data-scope="floating-panel" data-part="trigger-group">
<FloatingPanelMinimizeTrigger>
<Minus />
</FloatingPanelMinimizeTrigger>
<FloatingPanelMaximizeTrigger>
<Maximize2 />
</FloatingPanelMaximizeTrigger>
<FloatingPanelRestoreTrigger>
<ArrowDownLeft />
</FloatingPanelRestoreTrigger>
<FloatingPanelCloseTrigger>
<XIcon />
</FloatingPanelCloseTrigger>
</div>
</FloatingPanelHeader>
</FloatingPanelDragTrigger>
<FloatingPanelBody>
<p>Some content</p>
</FloatingPanelBody>

<FloatingPanelResizeTrigger axis="n" />
<FloatingPanelResizeTrigger axis="e" />
<FloatingPanelResizeTrigger axis="w" />
<FloatingPanelResizeTrigger axis="s" />
<FloatingPanelResizeTrigger axis="ne" />
<FloatingPanelResizeTrigger axis="se" />
<FloatingPanelResizeTrigger axis="sw" />
<FloatingPanelResizeTrigger axis="nw" />
</FloatingPanelContent>
</FloatingPanelPositioner>
</Portal>
</FloatingPanel.Root>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import {
FloatingPanel,
FloatingPanelBody,
FloatingPanelCloseTrigger,
FloatingPanelContent,
FloatingPanelContext,
FloatingPanelDragTrigger,
FloatingPanelHeader,
FloatingPanelMaximizeTrigger,
FloatingPanelMinimizeTrigger,
FloatingPanelPositioner,
FloatingPanelResizeTrigger,
FloatingPanelRestoreTrigger,
FloatingPanelTitle,
FloatingPanelTrigger,
Portal,
} from '../..'

import { ArrowDownLeft, Maximize2, Minus, XIcon } from 'lucide-react'

export const RenderFn = () => (
<FloatingPanel.Root>
<FloatingPanelTrigger>Toggle Panel</FloatingPanelTrigger>
<Portal>
<FloatingPanelPositioner>
<FloatingPanelContent>
<FloatingPanelDragTrigger>
<FloatingPanelHeader>
<FloatingPanelTitle>Floating Panel</FloatingPanelTitle>
<div data-scope="floating-panel" data-part="trigger-group">
<FloatingPanelMinimizeTrigger>
<Minus />
</FloatingPanelMinimizeTrigger>
<FloatingPanelMaximizeTrigger>
<Maximize2 />
</FloatingPanelMaximizeTrigger>
<FloatingPanelRestoreTrigger>
<ArrowDownLeft />
</FloatingPanelRestoreTrigger>
<FloatingPanelCloseTrigger>
<XIcon />
</FloatingPanelCloseTrigger>
</div>
</FloatingPanelHeader>
</FloatingPanelDragTrigger>
<FloatingPanelBody>
<p>Some content</p>
</FloatingPanelBody>

<FloatingPanelResizeTrigger axis="n" />
<FloatingPanelResizeTrigger axis="e" />
<FloatingPanelResizeTrigger axis="w" />
<FloatingPanelResizeTrigger axis="s" />
<FloatingPanelResizeTrigger axis="ne" />
<FloatingPanelResizeTrigger axis="se" />
<FloatingPanelResizeTrigger axis="sw" />
<FloatingPanelResizeTrigger axis="nw" />
</FloatingPanelContent>
</FloatingPanelPositioner>
</Portal>
<FloatingPanelContext>
{(floatingPanel) => <p>floatingPanel is {floatingPanel.open ? 'open' : 'closed'}</p>}
</FloatingPanelContext>
</FloatingPanel.Root>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { mergeProps } from '@zag-js/react'
import { forwardRef } from 'react'
import { type HTMLProps, type PolymorphicProps, ark } from '../factory'
import { useFloatingPanelContext } from './use-floating-panel-context'

export interface FloatingPanelBodyBaseProps extends PolymorphicProps {}
export interface FloatingPanelBodyProps extends HTMLProps<'div'>, FloatingPanelBodyBaseProps {}

export const FloatingPanelBody = forwardRef<HTMLDivElement, FloatingPanelBodyProps>(
(props, ref) => {
const floatingPanel = useFloatingPanelContext()
const mergedProps = mergeProps(floatingPanel.getBodyProps(), props)

return <ark.div {...mergedProps} ref={ref} />
},
)

FloatingPanelBody.displayName = 'FloatingPanelBody'
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { mergeProps } from '@zag-js/react'
import { forwardRef } from 'react'
import { type HTMLProps, type PolymorphicProps, ark } from '../factory'
import { useFloatingPanelContext } from './use-floating-panel-context'

export interface FloatingPanelCloseTriggerBaseProps extends PolymorphicProps {}
export interface FloatingPanelCloseTriggerProps
extends HTMLProps<'button'>,
FloatingPanelCloseTriggerBaseProps {}

export const FloatingPanelCloseTrigger = forwardRef<
HTMLButtonElement,
FloatingPanelCloseTriggerProps
>((props, ref) => {
const floatingPanel = useFloatingPanelContext()
const mergedProps = mergeProps(floatingPanel.getCloseTriggerProps(), props)

return <ark.button {...mergedProps} ref={ref} />
})

FloatingPanelCloseTrigger.displayName = 'FloatingPanelCloseTrigger'
Loading

0 comments on commit da1bfaf

Please sign in to comment.