1+ // Area 1: “Imports and constants”
12import React , { useState , useRef , useEffect } from 'react' ;
23import './DesktopIcon.css' ;
34
@@ -18,6 +19,7 @@ import {
1819// 30%-opacity overlay PNG
1920import disabledOverlay from '../../media/icons/disable.png' ;
2021
22+ // Area 2: “Component state and effects”
2123function DesktopIcon ( {
2224 wrapId,
2325 id,
@@ -30,22 +32,19 @@ function DesktopIcon({
3032 disableClick,
3133 clearDisableClick,
3234 icon,
33- available = true , // ← new prop
35+ available = true ,
3436 position : controlledPosition ,
3537 onPositionChange
3638} ) {
39+ // 2.1: Position, drag and tap state
3740 const iconRef = useRef ( null ) ;
3841 const { log, enabled } = useLogger ( `DesktopIcon[${ wrapId } ]` ) ;
3942 const { state } = useStateManager ( ) ;
4043 const desktopCfg = state . groups . desktop ;
41-
42- // grid & icon sizing
4344 const gridGap = parseInt ( desktopCfg . gridGap , 10 ) || 30 ;
4445 const iconWidth = parseInt ( desktopCfg . iconWidth , 10 ) || 64 ;
4546 const iconHeight = parseInt ( desktopCfg . iconHeight , 10 ) || 64 ;
4647 const gridSize = iconHeight ;
47-
48- // margins
4948 const topMargin = parseInt ( desktopCfg . topMargin , 10 ) || 40 ;
5049 const leftMargin = parseInt ( desktopCfg . leftMargin , 10 ) || 20 ;
5150 const rightMargin = parseInt ( desktopCfg . rightMargin , 10 ) || 20 ;
@@ -57,13 +56,24 @@ function DesktopIcon({
5756 const [ isDragging , setIsDragging ] = useState ( false ) ;
5857 const [ holdTimer , setHoldTimer ] = useState ( null ) ;
5958 const [ lastTap , setLastTap ] = useState ( 0 ) ;
59+ const isIconVisible = desktopCfg . iconVisible !== 'false' ;
6060
61- // sync controlledPosition
61+ // 2.2: Animation state for initial mount
62+ // Icons start scaled/down-opacity, then animate in on first render
63+ const [ hasMounted , setHasMounted ] = useState ( false ) ;
64+ useEffect ( ( ) => {
65+ if ( isIconVisible ) {
66+ // trigger animation one tick after mount
67+ setHasMounted ( true ) ;
68+ }
69+ } , [ isIconVisible ] ) ;
70+
71+ // keep controlledPosition in sync
6272 useEffect ( ( ) => {
6373 if (
6474 controlledPosition &&
6575 ( controlledPosition . x !== position . x ||
66- controlledPosition . y !== position . y )
76+ controlledPosition . y !== position . y )
6777 ) {
6878 setPosition ( controlledPosition ) ;
6979 }
@@ -74,16 +84,12 @@ function DesktopIcon({
7484 if ( onPositionChange ) onPositionChange ( newPos ) ;
7585 } ;
7686
77- const isIconVisible = desktopCfg . iconVisible !== 'false' ;
78-
7987 if ( enabled ) {
80- log (
81- 'render' ,
82- `Rendering "${ name } " at x=${ position . x } ,y=${ position . y } `
83- ) ;
88+ log ( 'render' , `Rendering "${ name } " at x=${ position . x } ,y=${ position . y } ` ) ;
8489 }
8590
86- // Hold/drag/tap interactions (unchanged)…
91+ // Area 3: “Event handlers”
92+ // 3.1: Mouse/touch down, up, leave, tap logic…
8793 const handleMouseDown = ( e ) => {
8894 if ( isSelected && selectedCount > 1 && onGroupMouseDown ) {
8995 onGroupMouseDown ( e ) ;
@@ -97,10 +103,7 @@ function DesktopIcon({
97103 setHoldTimer ,
98104 ( x , y , offsetX , offsetY ) => {
99105 startDragging (
100- x ,
101- y ,
102- offsetX ,
103- offsetY ,
106+ x , y , offsetX , offsetY ,
104107 iconRef ,
105108 updatePosition ,
106109 setIsDragging ,
@@ -135,10 +138,7 @@ function DesktopIcon({
135138 setHoldTimer ,
136139 ( x , y , offsetX , offsetY ) => {
137140 startDragging (
138- x ,
139- y ,
140- offsetX ,
141- offsetY ,
141+ x , y , offsetX , offsetY ,
142142 iconRef ,
143143 updatePosition ,
144144 setIsDragging ,
@@ -159,20 +159,24 @@ function DesktopIcon({
159159 const wrapperOnClick = ( ) => onClick ( ) ;
160160 const wrapperOnDoubleClick = ( ) => onDoubleClick ( ) ;
161161
162+ // Area 4: “Render”
163+ // 4.1: Compute inline style (adds opacity & transform animation)
162164 const iconStyle = {
163165 '--icon-width' : `${ iconWidth } px` ,
164166 '--icon-height' : `${ iconHeight } px` ,
165167 width : iconWidth ,
166168 height : iconHeight ,
167169 left : position . x ,
168170 top : position . y ,
169- opacity : isIconVisible ? 1 : 0 ,
171+ opacity : hasMounted && isIconVisible ? 1 : 0 ,
172+ transform : hasMounted && isIconVisible ? 'scale(1)' : 'scale(0.8)' ,
170173 transition : isDragging
171174 ? 'none'
172- : 'left 0.3s, top 0.3s, opacity 0.5s'
175+ : 'left 0.3s, top 0.3s, opacity 0.5s, transform 0.5s '
173176 } ;
174177
175178 return (
179+ // 4.2: JSX structure with a possible disabled overlay
176180 < div
177181 id = { `desktop-icon-${ wrapId } -${ id } ` }
178182 ref = { iconRef }
@@ -219,7 +223,6 @@ function DesktopIcon({
219223 className = "icon-image"
220224 style = { { backgroundImage : `url(${ icon } )` } }
221225 />
222- { /* Disabled-overlay */ }
223226 { ! available && (
224227 < img
225228 src = { disabledOverlay }
0 commit comments