Implement ToolbarIconButton
This commit is contained in:
parent
a11918fc20
commit
20603afd40
8 changed files with 147 additions and 132 deletions
|
@ -7,12 +7,10 @@ import {OrbitControls} from '@react-three/drei'
|
||||||
import shallow from 'zustand/shallow'
|
import shallow from 'zustand/shallow'
|
||||||
import root from 'react-shadow/styled-components'
|
import root from 'react-shadow/styled-components'
|
||||||
import ProxyManager from './ProxyManager'
|
import ProxyManager from './ProxyManager'
|
||||||
import studio from '@theatre/studio'
|
import studio, {ToolbarIconButton} from '@theatre/studio'
|
||||||
import {useVal} from '@theatre/dataverse-react'
|
import {useVal} from '@theatre/dataverse-react'
|
||||||
import styled, {createGlobalStyle, StyleSheetManager} from 'styled-components'
|
import styled, {createGlobalStyle, StyleSheetManager} from 'styled-components'
|
||||||
import IconButton from './Toolbar/utils/IconButton'
|
import {IoCameraReverseOutline} from 'react-icons/all'
|
||||||
import {BiRefresh} from 'react-icons/bi'
|
|
||||||
import {PortalContext} from 'reakit'
|
|
||||||
|
|
||||||
const GlobalStyle = createGlobalStyle`
|
const GlobalStyle = createGlobalStyle`
|
||||||
:host {
|
:host {
|
||||||
|
@ -134,42 +132,42 @@ const SnapshotEditor: React.FC<{}> = () => {
|
||||||
<StyleSheetManager disableVendorPrefixes>
|
<StyleSheetManager disableVendorPrefixes>
|
||||||
<>
|
<>
|
||||||
<GlobalStyle />
|
<GlobalStyle />
|
||||||
<PortalContext.Provider value={overlay}>
|
{/* <PortalContext.Provider value={overlay}> */}
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<Overlay ref={setOverlay}>
|
<Overlay ref={setOverlay}>
|
||||||
<Tools>
|
<Tools>
|
||||||
<IconButton
|
<ToolbarIconButton
|
||||||
icon={<BiRefresh />}
|
icon={<IoCameraReverseOutline />}
|
||||||
label="Refresh Snapshot"
|
label="Refresh Snapshot"
|
||||||
onClick={createSnapshot}
|
onClick={createSnapshot}
|
||||||
></IconButton>
|
></ToolbarIconButton>
|
||||||
</Tools>
|
</Tools>
|
||||||
</Overlay>
|
</Overlay>
|
||||||
|
|
||||||
{sceneSnapshot ? (
|
{sceneSnapshot ? (
|
||||||
<>
|
<>
|
||||||
<CanvasWrapper>
|
<CanvasWrapper>
|
||||||
<Canvas
|
<Canvas
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
colorManagement
|
colorManagement
|
||||||
camera={initialEditorCamera}
|
camera={initialEditorCamera}
|
||||||
onCreated={({gl}) => {
|
onCreated={({gl}) => {
|
||||||
gl.setClearColor('white')
|
gl.setClearColor('white')
|
||||||
}}
|
}}
|
||||||
shadowMap
|
shadowMap
|
||||||
dpr={[1, 2]}
|
dpr={[1, 2]}
|
||||||
fog={'red'}
|
fog={'red'}
|
||||||
onPointerMissed={() =>
|
onPointerMissed={() =>
|
||||||
studio.__experimental_setSelection([])
|
studio.__experimental_setSelection([])
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<EditorScene />
|
<EditorScene />
|
||||||
</Canvas>
|
</Canvas>
|
||||||
</CanvasWrapper>
|
</CanvasWrapper>
|
||||||
</>
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
</PortalContext.Provider>
|
{/* </PortalContext.Provider> */}
|
||||||
</>
|
</>
|
||||||
</StyleSheetManager>
|
</StyleSheetManager>
|
||||||
</root.div>
|
</root.div>
|
||||||
|
|
|
@ -1,17 +1,13 @@
|
||||||
import type {VFC} from 'react'
|
import type {VFC} from 'react'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import TransformControlsModeSelect from './TransformControlsModeSelect'
|
|
||||||
import {useEditorStore} from '../../store'
|
import {useEditorStore} from '../../store'
|
||||||
import shallow from 'zustand/shallow'
|
import shallow from 'zustand/shallow'
|
||||||
import TransformControlsSpaceSelect from './TransformControlsSpaceSelect'
|
import {GiPocketBow, IoCameraOutline} from 'react-icons/all'
|
||||||
import ViewportShadingSelect from './ViewportShadingSelect'
|
|
||||||
import {GiPocketBow, RiFocus3Line} from 'react-icons/all'
|
|
||||||
import {Vector3} from 'three'
|
import {Vector3} from 'three'
|
||||||
import type {$FixMe} from '@theatre/shared/utils/types'
|
import type {$FixMe} from '@theatre/shared/utils/types'
|
||||||
import studio from '@theatre/studio'
|
import studio, {ToolbarIconButton} from '@theatre/studio'
|
||||||
import {getSelected} from '../useSelected'
|
import {getSelected} from '../useSelected'
|
||||||
import {usePrism, useVal} from '@theatre/dataverse-react'
|
import {usePrism, useVal} from '@theatre/dataverse-react'
|
||||||
import IconButton from './utils/IconButton'
|
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
const ToolGroup = styled.div`
|
const ToolGroup = styled.div`
|
||||||
|
@ -40,15 +36,15 @@ const Toolbar: VFC = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ToolGroup>
|
<ToolGroup>
|
||||||
<button
|
<ToolbarIconButton
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
studio.createPane('snapshotEditor')
|
studio.createPane('snapshotEditor')
|
||||||
}}
|
}}
|
||||||
>
|
icon={<IoCameraOutline />}
|
||||||
Create snapshot
|
label="Create snapshot"
|
||||||
</button>
|
/>
|
||||||
</ToolGroup>
|
</ToolGroup>
|
||||||
<ToolGroup>
|
{/* <ToolGroup>
|
||||||
<TransformControlsModeSelect
|
<TransformControlsModeSelect
|
||||||
value={transformControlsMode}
|
value={transformControlsMode}
|
||||||
onChange={(value) =>
|
onChange={(value) =>
|
||||||
|
@ -103,9 +99,9 @@ const Toolbar: VFC = () => {
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</ToolGroup>
|
</ToolGroup> */}
|
||||||
<ToolGroup>
|
<ToolGroup>
|
||||||
<IconButton
|
<ToolbarIconButton
|
||||||
label="Align object to view"
|
label="Align object to view"
|
||||||
icon={<GiPocketBow />}
|
icon={<GiPocketBow />}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
import type {ReactElement} from 'react'
|
|
||||||
import React, {forwardRef} from 'react'
|
|
||||||
import type {ButtonProps} from 'reakit'
|
|
||||||
import {Button} from 'reakit'
|
|
||||||
import type {IconType} from 'react-icons'
|
|
||||||
import {Tooltip, TooltipReference, useTooltipState} from './Tooltip'
|
|
||||||
import styled from 'styled-components'
|
|
||||||
import {transparentize} from 'polished'
|
|
||||||
|
|
||||||
export interface IconButtonProps extends Exclude<ButtonProps, 'children'> {
|
|
||||||
icon: ReactElement<IconType>
|
|
||||||
label: string
|
|
||||||
}
|
|
||||||
|
|
||||||
const TheButton = styled(TooltipReference)`
|
|
||||||
display: flex;
|
|
||||||
position: relative;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
vertical-align: middle;
|
|
||||||
font-size: 11px;
|
|
||||||
line-height: 1.25em;
|
|
||||||
font-weight: 600;
|
|
||||||
height: 24px;
|
|
||||||
padding-left: 0.5em;
|
|
||||||
padding-right: 0.5em;
|
|
||||||
color: #e6e6e5;
|
|
||||||
background-color: #313131ba;
|
|
||||||
border: 0 transparent;
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
border-top-left-radius: 3px;
|
|
||||||
border-bottom-left-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
border-top-right-radius: 3px;
|
|
||||||
border-bottom-right-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
color: #e6e6e5;
|
|
||||||
background-color: #313131;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: ${transparentize(0.5, '#313131')};
|
|
||||||
}
|
|
||||||
|
|
||||||
border: 0 transparent;
|
|
||||||
`
|
|
||||||
const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
|
|
||||||
({label, icon, className, ...props}, ref) => {
|
|
||||||
const tooltip = useTooltipState()
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<TheButton
|
|
||||||
{...props}
|
|
||||||
{...tooltip}
|
|
||||||
forwardedAs={Button}
|
|
||||||
aria-label={label}
|
|
||||||
>
|
|
||||||
{icon}
|
|
||||||
</TheButton>
|
|
||||||
<Tooltip {...tooltip}>{label}</Tooltip>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
export default IconButton
|
|
|
@ -19,6 +19,8 @@ const Container = styled(TooltipImpl)`
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
`
|
`
|
||||||
|
|
||||||
export const Tooltip: VFC<TooltipProps> = ({className, ...props}) => (
|
export const Tooltip: VFC<TooltipProps> = ({className, ...props}) => {
|
||||||
<Container {...props} className={className as string} />
|
console.log('deprecate tooltip')
|
||||||
)
|
|
||||||
|
return <Container {...props} className={className as string} />
|
||||||
|
}
|
||||||
|
|
|
@ -40,9 +40,19 @@ const Container = styled.div`
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const PortalLayer = styled.div`
|
||||||
|
z-index: 51;
|
||||||
|
position: fixed;
|
||||||
|
top: 0px;
|
||||||
|
right: 0px;
|
||||||
|
bottom: 0px;
|
||||||
|
left: 0px;
|
||||||
|
pointer-events: none;
|
||||||
|
`
|
||||||
|
|
||||||
export default function UIRoot() {
|
export default function UIRoot() {
|
||||||
const studio = getStudio()
|
const studio = getStudio()
|
||||||
const [containerRef, container] = useRefAndState<HTMLDivElement>(
|
const [portalLayerRef, portalLayer] = useRefAndState<HTMLDivElement>(
|
||||||
undefined as $IntentionalAny,
|
undefined as $IntentionalAny,
|
||||||
)
|
)
|
||||||
const inside = usePrism(() => {
|
const inside = usePrism(() => {
|
||||||
|
@ -61,8 +71,9 @@ export default function UIRoot() {
|
||||||
<>
|
<>
|
||||||
<GlobalStyle />
|
<GlobalStyle />
|
||||||
<ProvideTheme>
|
<ProvideTheme>
|
||||||
<PortalContext.Provider value={container}>
|
<PortalContext.Provider value={portalLayer}>
|
||||||
<Container ref={containerRef}>
|
<PortalLayer ref={portalLayerRef} />
|
||||||
|
<Container>
|
||||||
{shouldShowGlobalToolbar && <GlobalToolbar />}
|
{shouldShowGlobalToolbar && <GlobalToolbar />}
|
||||||
{shouldShowTrigger && <TheTrigger />}
|
{shouldShowTrigger && <TheTrigger />}
|
||||||
{shouldShowPanels && <PanelsRoot />}
|
{shouldShowPanels && <PanelsRoot />}
|
||||||
|
@ -72,7 +83,7 @@ export default function UIRoot() {
|
||||||
</>
|
</>
|
||||||
</StyleSheetManager>
|
</StyleSheetManager>
|
||||||
)
|
)
|
||||||
}, [studio, containerRef, container])
|
}, [studio, portalLayerRef, portalLayer])
|
||||||
|
|
||||||
return inside
|
return inside
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import * as globalVariableNames from '@theatre/shared/globalVariableNames'
|
||||||
import type {$FixMe} from '@theatre/shared/utils/types'
|
import type {$FixMe} from '@theatre/shared/utils/types'
|
||||||
import StudioBundle from './StudioBundle'
|
import StudioBundle from './StudioBundle'
|
||||||
import type CoreBundle from '@theatre/core/CoreBundle'
|
import type CoreBundle from '@theatre/core/CoreBundle'
|
||||||
|
export {default as ToolbarIconButton} from './uiComponents/toolbar/ToolbarIconButton'
|
||||||
|
|
||||||
const studioPrivateAPI = new Studio()
|
const studioPrivateAPI = new Studio()
|
||||||
setStudio(studioPrivateAPI)
|
setStudio(studioPrivateAPI)
|
||||||
|
|
23
theatre/studio/src/uiComponents/Tooltip.tsx
Normal file
23
theatre/studio/src/uiComponents/Tooltip.tsx
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import type {VFC} from 'react'
|
||||||
|
import React from 'react'
|
||||||
|
import {Tooltip as TooltipImpl, TooltipReference, useTooltipState} from 'reakit'
|
||||||
|
import type {TooltipProps} from 'reakit'
|
||||||
|
import styled from 'styled-components'
|
||||||
|
|
||||||
|
export {TooltipReference, useTooltipState}
|
||||||
|
|
||||||
|
const Container = styled(TooltipImpl)`
|
||||||
|
padding: 8px 14px;
|
||||||
|
|
||||||
|
font-size: 11px;
|
||||||
|
line-height: 1.25em;
|
||||||
|
border-radius: 2px;
|
||||||
|
background-color: #201f20;
|
||||||
|
color: white;
|
||||||
|
pointer-events: none;
|
||||||
|
font-weight: 500;
|
||||||
|
`
|
||||||
|
|
||||||
|
export const Tooltip: VFC<TooltipProps> = ({className, ...props}) => (
|
||||||
|
<Container {...props} className={className as string} />
|
||||||
|
)
|
|
@ -0,0 +1,57 @@
|
||||||
|
import type {ReactElement} from 'react'
|
||||||
|
import React from 'react'
|
||||||
|
import styled from 'styled-components'
|
||||||
|
import {Tooltip, TooltipReference} from '@theatre/studio/uiComponents/Tooltip'
|
||||||
|
import {lighten} from 'polished'
|
||||||
|
import type {ButtonProps} from 'reakit'
|
||||||
|
import {useTooltipState} from 'reakit'
|
||||||
|
import {Button} from 'reakit'
|
||||||
|
|
||||||
|
const TheButton = styled(TooltipReference)`
|
||||||
|
pointer-events: auto;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
outline: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: ${lighten(0.02, '#313131')};
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
color: #c0c0c0;
|
||||||
|
background-color: #313131;
|
||||||
|
border: 1px solid #272727;
|
||||||
|
border-radius: 3px;
|
||||||
|
box-shadow: 1px 1px 0px #0000001c;
|
||||||
|
`
|
||||||
|
|
||||||
|
const ToolbarIconButton: React.FC<
|
||||||
|
Exclude<ButtonProps, 'children'> & {
|
||||||
|
icon: ReactElement
|
||||||
|
label: string
|
||||||
|
}
|
||||||
|
> = (props) => {
|
||||||
|
const tooltip = useTooltipState()
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<TheButton
|
||||||
|
{...tooltip}
|
||||||
|
forwardedAs={Button}
|
||||||
|
aria-label={props.label}
|
||||||
|
onClick={props.onClick}
|
||||||
|
className={props.className}
|
||||||
|
>
|
||||||
|
{props.icon}
|
||||||
|
</TheButton>
|
||||||
|
<Tooltip {...tooltip}>{props.label}</Tooltip>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ToolbarIconButton
|
Loading…
Reference in a new issue