Fix extension buttons spacing, add extension example (#229)

* Fix extension buttons spacing & styles
* Refactor extension button styles
* Clean up extension prism
This commit is contained in:
Elliot 2022-06-26 12:00:59 -04:00 committed by GitHub
parent 2854881e17
commit 006121da91
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 121 additions and 44 deletions

View file

@ -0,0 +1,37 @@
import {editable as e, SheetProvider} from '@theatre/r3f'
import {Stars, TorusKnot} from '@react-three/drei'
import {getProject} from '@theatre/core'
import React from 'react'
import {Canvas} from '@react-three/fiber'
function App() {
return (
<div
onClick={() => {
// return setBgIndex((bgIndex) => (bgIndex + 1) % bgs.length)
}}
style={{
height: '100vh',
}}
>
<Canvas
dpr={[1.5, 2]}
linear
gl={{preserveDrawingBuffer: true}}
frameloop="demand"
>
<SheetProvider sheet={getProject('Space').sheet('Scene')}>
<ambientLight intensity={0.75} />
<e.group uniqueName="trefoil">
<TorusKnot scale={[1, 1, 1]} args={[1, 0.3, 128, 64]}>
<meshNormalMaterial />
</TorusKnot>
</e.group>
<Stars radius={500} depth={50} count={1000} factor={10} />
</SheetProvider>
</Canvas>
</div>
)
}
export default App

View file

@ -0,0 +1,50 @@
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import type {ToolsetConfig} from '@theatre/studio'
import studio from '@theatre/studio'
import extension from '@theatre/r3f/dist/extension'
import {Box, prism, Ticker, val} from '@theatre/dataverse'
studio.extend(extension)
studio.extend({
id: '@theatre/hello-world-extension',
toolbars: {
global(set, studio) {
const exampleBox = new Box('mobile')
return prism<ToolsetConfig>(() => [
{
type: 'Switch',
value: val(exampleBox.derivation),
onChange: (value) => exampleBox.set(value),
options: [
{
value: 'mobile',
label: 'view mobile version',
svgSource: '😀',
},
{
value: 'desktop',
label: 'view desktop version',
svgSource: '🪢',
},
],
},
{
type: 'Icon',
title: 'Example Icon',
svgSource: '👁‍🗨',
onClick: () => {
console.log('hello')
},
},
]).tapImmediate(Ticker.raf, (value) => {
set(value)
})
},
},
panes: [],
})
studio.initialize()
ReactDOM.render(<App />, document.getElementById('root'))

View file

@ -14,7 +14,7 @@ const Container = styled.div`
/* pointer-events: none; */ /* pointer-events: none; */
display: flex; display: flex;
gap: 1rem; gap: 0.5rem;
justify-content: center; justify-content: center;
` `
@ -34,6 +34,14 @@ const Bg = styled.div`
} }
` `
const GroupDivider = styled.div`
position: abolute;
height: 32px;
width: 1px;
background: #373b40;
opacity: 0.4;
`
const ExtensionToolsetRender: React.FC<{ const ExtensionToolsetRender: React.FC<{
extension: IExtension extension: IExtension
toolbarId: string toolbarId: string
@ -60,16 +68,22 @@ export const ExtensionToolbar: React.FC<{toolbarId: string}> = ({
const groups: Array<React.ReactNode> = [] const groups: Array<React.ReactNode> = []
const extensionsById = useVal(getStudio().atomP.ephemeral.extensions.byId) const extensionsById = useVal(getStudio().atomP.ephemeral.extensions.byId)
let isAfterFirstGroup = false
for (const [, extension] of Object.entries(extensionsById)) { for (const [, extension] of Object.entries(extensionsById)) {
if (!extension || !extension.toolbars?.[toolbarId]) continue if (!extension || !extension.toolbars?.[toolbarId]) continue
groups.push( groups.push(
<ExtensionToolsetRender <>
extension={extension} {isAfterFirstGroup ? <GroupDivider></GroupDivider> : undefined}
key={'extensionToolbar-' + extension.id} <ExtensionToolsetRender
toolbarId={toolbarId} extension={extension}
/>, key={'extensionToolbar-' + extension.id}
toolbarId={toolbarId}
/>
</>,
) )
isAfterFirstGroup = true
} }
if (groups.length === 0) return null if (groups.length === 0) return null

View file

@ -57,6 +57,14 @@ const HasUpdatesBadge = styled.div`
top: -2px; top: -2px;
` `
const GroupDivider = styled.div`
position: abolute;
height: 32px;
width: 1px;
background: #373b40;
opacity: 0.4;
`
const GlobalToolbar: React.FC = () => { const GlobalToolbar: React.FC = () => {
const conflicts = usePrism(() => { const conflicts = usePrism(() => {
const ephemeralStateOfAllProjects = val( const ephemeralStateOfAllProjects = val(
@ -126,6 +134,7 @@ const GlobalToolbar: React.FC = () => {
unpinHintIcon={<DoubleChevronLeft />} unpinHintIcon={<DoubleChevronLeft />}
pinned={outlinePinned} pinned={outlinePinned}
/> />
<GroupDivider />
{conflicts.length > 0 ? ( {conflicts.length > 0 ? (
<NumberOfConflictsIndicator> <NumberOfConflictsIndicator>
{conflicts.length} {conflicts.length}
@ -144,7 +153,6 @@ const GlobalToolbar: React.FC = () => {
<Ellipsis /> <Ellipsis />
{hasUpdates && <HasUpdatesBadge />} {hasUpdates && <HasUpdatesBadge />}
</ToolbarIconButton> </ToolbarIconButton>
<PinButton <PinButton
ref={triggerButtonRef as $IntentionalAny} ref={triggerButtonRef as $IntentionalAny}
onClick={() => { onClick={() => {

View file

@ -1,45 +1,14 @@
import styled from 'styled-components' import styled from 'styled-components'
import {pointerEventsAutoInNormalMode} from '@theatre/studio/css'
import type {ComponentPropsWithRef, ReactNode} from 'react' import type {ComponentPropsWithRef, ReactNode} from 'react'
import React, {forwardRef, useState} from 'react' import React, {forwardRef, useState} from 'react'
import ToolbarIconButton from '@theatre/studio/uiComponents/toolbar/ToolbarIconButton'
const Container = styled.button<{pinned?: boolean}>` const Container = styled(ToolbarIconButton)<{pinned?: boolean}>`
${pointerEventsAutoInNormalMode};
position: relative;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
font-weight: 600;
width: 32px;
height: 32px;
outline: none;
color: ${({pinned}) => (pinned ? 'rgba(255, 255, 255, 0.8)' : '#A8A8A9')}; color: ${({pinned}) => (pinned ? 'rgba(255, 255, 255, 0.8)' : '#A8A8A9')};
background: rgba(40, 43, 47, 0.8);
backdrop-filter: blur(14px);
border: none;
border-bottom: 1px solid border-bottom: 1px solid
${({pinned}) => ${({pinned}) =>
pinned ? 'rgba(255, 255, 255, 0.7)' : 'rgba(255, 255, 255, 0.08)'}; pinned ? 'rgba(255, 255, 255, 0.7)' : 'rgba(255, 255, 255, 0.08)'};
border-radius: 2px;
&:hover {
background: rgba(59, 63, 69, 0.8);
}
&:active {
background: rgba(82, 88, 96, 0.8);
}
svg {
display: block;
}
@supports not (backdrop-filter: blur()) {
background: rgba(40, 43, 47, 0.95);
}
` `
interface PinButtonProps extends ComponentPropsWithRef<'button'> { interface PinButtonProps extends ComponentPropsWithRef<'button'> {

View file

@ -27,8 +27,9 @@ export const Container = styled.button`
border-bottom: 1px solid rgba(255, 255, 255, 0.08); border-bottom: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 2px; border-radius: 2px;
filter: drop-shadow(0px 1px 1px rgba(0, 0, 0, 0.25)) svg {
drop-shadow(0px 2px 6px rgba(0, 0, 0, 0.15)); display: block;
}
&:hover { &:hover {
background: rgba(59, 63, 69, 0.8); background: rgba(59, 63, 69, 0.8);

View file

@ -6,8 +6,6 @@ const Container = styled(Group)`
height: fit-content; height: fit-content;
backdrop-filter: blur(14px); backdrop-filter: blur(14px);
border-radius: 2px; border-radius: 2px;
filter: drop-shadow(0px 1px 1px rgba(0, 0, 0, 0.25))
drop-shadow(0px 2px 6px rgba(0, 0, 0, 0.15));
` `
export default Container export default Container