Skip to content

Commit

Permalink
feat: zIndexOffset - multiple layers to render panels in front of tex…
Browse files Browse the repository at this point in the history
…t/images/...
  • Loading branch information
bbohlender committed Feb 21, 2024
1 parent 6a20bc7 commit b986bbd
Show file tree
Hide file tree
Showing 28 changed files with 376 additions and 223 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ jobs:
uses: gittools/actions/gitversion/execute@v0

- name: Set Version
working-directory: ./packages/uikit
run: pnpm exec json -f "package.json" -I -e 'this.version = "${{ steps.gitversion.outputs.fullSemVer }}"'
run: pnpm -r exec json -f "package.json" -I -e 'this.version = "${{ steps.gitversion.outputs.fullSemVer }}"'

- name: Set publishing config
run: pnpm config set '//registry.npmjs.org/:_authToken' "${{ secrets.NPM_TOKEN }}"
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ Build performant 3D user interfaces for Three.js using @react-three/fiber and yo

TODO Release

- fix bug: 3 draw calls for TabsDemo
- fix bug: interaction panel disappear unmount and mount
- add shadcn components
- cli for kits
- add apfel components
- Content "measureContent" flag => allow disabling content measuring and scaling
- support for visibility="hidden"
- input
- Label
- decrease clipping rect when scrollbar present
- multiple layers to render panels in front of text/images/... (e.g. for modals) - <IncrementLayer by={2} >{...content}</IncrementLayer>

TODO Later

Expand Down
57 changes: 26 additions & 31 deletions examples/dashboard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
import { StrictMode } from "react";
import { Canvas } from "@react-three/fiber";
import { createRoot } from "react-dom/client";
import { Container, Fullscreen, Root, Text } from "@react-three/uikit";
import { DefaultColors, colors } from "@/defaults.js";
import { Button } from "@/button.js";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/card.js";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/tabs.js";
import { CalendarDateRangePicker } from "./date-range-picker.js";
import { MainNav } from "./main-nav.js";
import { Overview } from "./overview.js";
import { RecentSales } from "./recent-sales.js";
import { TeamSwitcher } from "./team-switcher.js";
import { UserNav } from "./user-nav.js";
import { Activity, CreditCard, DollarSign, Users } from "@react-three/uikit-lucide";
import { Environment, OrbitControls } from "@react-three/drei";
import { Perf } from "r3f-perf"
import { StrictMode } from 'react'
import { Canvas } from '@react-three/fiber'
import { createRoot } from 'react-dom/client'
import { Container, Fullscreen, Root, Text } from '@react-three/uikit'
import { DefaultColors, colors } from '@/defaults.js'
import { Button } from '@/button.js'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/card.js'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/tabs.js'
import { CalendarDateRangePicker } from './date-range-picker.js'
import { MainNav } from './main-nav.js'
import { Overview } from './overview.js'
import { RecentSales } from './recent-sales.js'
import { TeamSwitcher } from './team-switcher.js'
import { UserNav } from './user-nav.js'
import { Activity, CreditCard, DollarSign, Users } from '@react-three/uikit-lucide'
import { Environment, OrbitControls } from '@react-three/drei'
import { Perf } from 'r3f-perf'

createRoot(document.getElementById("root")!).render(
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
</StrictMode>,
);
)

function App() {
return (
<Canvas style={{ height: "100dvh", touchAction: "none" }} gl={{ localClippingEnabled: true }}>
<Canvas style={{ height: '100dvh', touchAction: 'none' }} gl={{ localClippingEnabled: true }}>
<Perf />
<color attach="background" args={["black"]} />
<color attach="background" args={['black']} />
<ambientLight intensity={0.5} />
<directionalLight intensity={0} position={[5, 1, 10]} />
<OrbitControls />
Expand Down Expand Up @@ -75,7 +75,7 @@ function App() {
</Root>
</group>
</Canvas>
);
)
}

export function DashboardPage() {
Expand Down Expand Up @@ -118,15 +118,10 @@ export function DashboardPage() {
</TabsTrigger>
</TabsList>
<TabsContent value="overview" gap={16}>
<Container gap={16} lg={{ flexDirection: "row" }}>
<Container gap={16} lg={{ flexDirection: 'row' }}>
<Container flexGrow={1} gap={16} flexDirection="row">
<Card backgroundOpacity={0.8} flexBasis={0} flexGrow={1}>
<CardHeader
flexDirection="row"
alignItems="center"
justifyContent="space-between"
paddingBottom={8}
>
<CardHeader flexDirection="row" alignItems="center" justifyContent="space-between" paddingBottom={8}>
<CardTitle>
<Text fontSize={14} lineHeight={1.43}>
Total Revenue
Expand Down Expand Up @@ -219,7 +214,7 @@ export function DashboardPage() {
</Card>
</Container>
</Container>
<Container lg={{ flexDirection: "row" }} flexDirection="column" gap={16}>
<Container lg={{ flexDirection: 'row' }} flexDirection="column" gap={16}>
<Card backgroundOpacity={0.8} lg={{ flexGrow: 4 }}>
<CardHeader>
<CardTitle>
Expand Down Expand Up @@ -248,5 +243,5 @@ export function DashboardPage() {
</Tabs>
</Container>
</Container>
);
)
}
2 changes: 2 additions & 0 deletions examples/default/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { Switch } from '@/switch.js'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/tabs.js'
import { Toggle } from '@/toggle.js'
import { ToggleGroup, ToggleGroupItem } from '@/toggle-group.js'
import { Perf } from 'r3f-perf'

createRoot(document.getElementById('root')!).render(
<StrictMode>
Expand All @@ -40,6 +41,7 @@ createRoot(document.getElementById('root')!).render(
function App() {
return (
<Canvas style={{ height: '100dvh', touchAction: 'none' }} gl={{ localClippingEnabled: true }}>
<Perf />
<color attach="background" args={['black']} />
<ambientLight intensity={0.5} />
<directionalLight intensity={0} position={[5, 1, 10]} />
Expand Down
1 change: 1 addition & 0 deletions examples/default/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"@react-three/fiber": "^8.15.13",
"@react-three/uikit": "workspace:^",
"@react-three/uikit-lucide": "workspace:^",
"r3f-perf": "^7.1.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
Expand Down
21 changes: 17 additions & 4 deletions examples/uikit/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ function App() {
gap={10}
overflow="scroll"
padding={10}
alignItems="flex-start"
alignItems="center"
flexDirection="column"
border={10}
borderRight={0}
Expand Down Expand Up @@ -79,11 +79,11 @@ function App() {
height={100}
/>
<CustomContainer transformRotateZ={45} height={200} width={4}>
<meshPhongMaterial color="green" />
<meshPhongMaterial depthWrite={false} transparent color="green" />
</CustomContainer>
<Content height={200} hover={{ height: 300 }} depthAlign="center" onSizeChange={(w, h) => console.log(w, h)}>
<Content height={200} hover={{ height: 300 }} depthAlign="front" onSizeChange={(w, h) => console.log(w, h)}>
<Box>
<meshPhongMaterial />
<meshPhongMaterial depthWrite={false} transparent />
</Box>
</Content>
<Content width={100}>
Expand All @@ -100,6 +100,19 @@ function App() {
width={300}
/>
</DefaultProperties>

<Container
positionType="absolute"
inset="20%"
width="60%"
height="60%"
alignItems="center"
justifyContent="center"
backgroundColor="green"
zIndexOffset={1}
>
<Text>Hello world</Text>
</Container>
</Fullscreen>
</Canvas>
)
Expand Down
3 changes: 2 additions & 1 deletion examples/uikit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"@react-three/fiber": "^8.15.13",
"@react-three/uikit": "workspace:^",
"react": "^18.2.0",
"react-dom": "^18.2.0"
"react-dom": "^18.2.0",
"three": "^0.160.0"
},
"scripts": {
"dev": "vite --host"
Expand Down
2 changes: 1 addition & 1 deletion packages/kits/default/slider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export function Slider({
<Container height="100%" width={percentage} borderRadius={1000} backgroundColor={colors.primary} />
</Container>
<Container
zIndexOffset={2}
zIndexOffset={{ minor: 2 }}
positionType="absolute"
positionLeft={percentage}
transformTranslateX={-10}
Expand Down
13 changes: 9 additions & 4 deletions packages/uikit/src/components/container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { WithClasses, useApplyProperties } from '../properties/default.js'
import { useRootGroupRef } from '../utils.js'
import { useApplyResponsiveProperties } from '../responsive.js'
import { Group } from 'three'
import { ElementType, OrderInfoProvider, ZIndexOffset, useOrderInfo } from '../order.js'

export type ContainerProperties = WithConditionals<
WithClasses<
Expand All @@ -49,7 +50,7 @@ export const Container = forwardRef<
ComponentInternals,
{
children?: ReactNode
zIndexOffset?: number
zIndexOffset?: ZIndexOffset
backgroundMaterialClass?: MaterialClass
} & ContainerProperties &
EventHandlers &
Expand All @@ -65,14 +66,15 @@ export const Container = forwardRef<
const parentClippingRect = useParentClippingRect()
const globalMatrix = useGlobalMatrix(transformMatrix)
const isClipped = useIsClipped(parentClippingRect, globalMatrix, node.size, node)
const orderInfo = useOrderInfo(ElementType.Panel, properties.zIndexOffset)
useInstancedPanel(
collection,
globalMatrix,
node.size,
undefined,
node.borderInset,
isClipped,
node.depth + (properties.zIndexOffset ?? 0),
orderInfo,
parentClippingRect,
properties.backgroundMaterialClass,
panelAliasPropertyTransformation,
Expand All @@ -88,6 +90,7 @@ export const Container = forwardRef<
isClipped,
properties.scrollbarMaterialClass,
parentClippingRect,
orderInfo,
)

//apply all properties
Expand All @@ -110,7 +113,7 @@ export const Container = forwardRef<

const rootGroupRef = useRootGroupRef()

const interactionPanel = useInteractionPanel(node.size, node, rootGroupRef)
const interactionPanel = useInteractionPanel(node.size, node, orderInfo, rootGroupRef)

useComponentInternals(ref, node, interactionPanel, scrollPosition)

Expand All @@ -122,7 +125,9 @@ export const Container = forwardRef<
<ScrollGroup node={node} scrollPosition={scrollPosition}>
<MatrixProvider value={globalScrollMatrix}>
<FlexProvider value={node}>
<ClippingRectProvider value={clippingRect}>{properties.children}</ClippingRectProvider>
<ClippingRectProvider value={clippingRect}>
<OrderInfoProvider value={orderInfo}>{properties.children}</OrderInfoProvider>
</ClippingRectProvider>
</FlexProvider>
</MatrixProvider>
</ScrollGroup>
Expand Down
17 changes: 11 additions & 6 deletions packages/uikit/src/components/content.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { EventHandlers } from '@react-three/fiber/dist/declarations/src/core/events.js'
import { ReactNode, RefObject, forwardRef, useEffect, useMemo, useRef } from 'react'
import { CameraDistanceRef, YogaProperties } from '../flex/node.js'
import { YogaProperties } from '../flex/node.js'
import { FlexProvider, useFlexNode } from '../flex/react.js'
import { InteractionGroup, MaterialClass, useInstancedPanel, useInteractionPanel } from '../panel/react.js'
import {
Expand All @@ -20,7 +20,6 @@ import {
LayoutListeners,
ViewportListeners,
WithConditionals,
setupRenderingOrder,
useComponentInternals,
useGlobalMatrix,
useLayoutListeners,
Expand All @@ -38,6 +37,7 @@ import { TransformProperties, useTransformMatrix } from '../transform.js'
import { useImmediateProperties } from '../properties/immediate.js'
import { WithClasses, useApplyProperties } from '../properties/default.js'
import { useApplyResponsiveProperties } from '../responsive.js'
import { CameraDistanceRef, ElementType, OrderInfo, ZIndexOffset, setupRenderOrder, useOrderInfo } from '../order.js'

export type ContentProperties = WithConditionals<
WithClasses<
Expand All @@ -53,6 +53,7 @@ export const Content = forwardRef<
ComponentInternals,
{
children?: ReactNode
zIndexOffset?: ZIndexOffset
backgroundMaterialClass?: MaterialClass
} & ContentProperties &
EventHandlers &
Expand All @@ -69,26 +70,29 @@ export const Content = forwardRef<
const isClipped = useIsClipped(parentClippingRect, globalMatrix, node.size, node)
useLayoutListeners(properties, node.size)
useViewportListeners(properties, isClipped)
const backgroundOrderInfo = useOrderInfo(ElementType.Panel, properties.zIndexOffset)
useInstancedPanel(
collection,
globalMatrix,
node.size,
undefined,
node.borderInset,
isClipped,
node.depth,
backgroundOrderInfo,
parentClippingRect,
properties.backgroundMaterialClass,
panelAliasPropertyTransformation,
)
const innerGroupRef = useRef<Group>(null)
const rootGroupRef = useRootGroupRef()
const orderInfo = useOrderInfo(ElementType.Object, undefined, backgroundOrderInfo)
const aspectRatio = useNormalizedContent(
collection,
innerGroupRef,
rootGroupRef,
node.cameraDistance,
parentClippingRect,
orderInfo,
)

//apply all properties
Expand Down Expand Up @@ -117,7 +121,7 @@ export const Content = forwardRef<
[node, aspectRatio],
)

const interactionPanel = useInteractionPanel(node.size, node, rootGroupRef)
const interactionPanel = useInteractionPanel(node.size, node, backgroundOrderInfo, rootGroupRef)

useComponentInternals(ref, node, interactionPanel)

Expand Down Expand Up @@ -146,6 +150,7 @@ function useNormalizedContent(
rootGroupRef: RefObject<Group>,
rootCameraDistance: CameraDistanceRef,
parentClippingRect: Signal<ClippingRect | undefined> | undefined,
orderInfo: OrderInfo,
): Signal<number | undefined> {
const aspectRatio = useMemo(() => signal<number | undefined>(undefined), [])
const clippingPlanes = useGlobalClippingPlanes(parentClippingRect, rootGroupRef)
Expand All @@ -157,10 +162,10 @@ function useNormalizedContent(
}
group.traverse((object) => {
if (object instanceof Mesh) {
setupRenderingOrder(object, rootCameraDistance, 'Object')
setupRenderOrder(object, rootCameraDistance, orderInfo)
object.material.clippingPlanes = clippingPlanes
object.material.needsUpdate = true
object.raycast = makeClippedRaycast(object, object.raycast, rootGroupRef, parentClippingRect)
object.raycast = makeClippedRaycast(object, object.raycast, rootGroupRef, parentClippingRect, orderInfo)
}
})
const parent = group.parent
Expand Down
Loading

0 comments on commit b986bbd

Please sign in to comment.