11import React , { useLayoutEffect , useMemo , useRef , useState } from "react"
2- import { ColorDescriptionConfig , dropElementConfigs , LAYOUT } from "@/constants"
2+ import {
3+ ColorDescriptionConfig ,
4+ dropElementConfigs ,
5+ LAYOUT ,
6+ MOBILE_VIEW_QUERY ,
7+ } from "@/constants"
38import { useMetadataStore } from "@/store/context"
49import { useShallow } from "zustand/shallow"
510import { DraggableGhost } from "./DraggableGhost"
611import { ApollonView } from "@/typings"
712import {
13+ COMPACT_PALETTE ,
814 PALETTE ,
915 computePaletteLayout ,
1016 previewScaleForCell ,
@@ -53,12 +59,13 @@ export const Sidebar = () => {
5359 // Measure the canvas the palette floats over (its positioned ancestor) so the
5460 // grid can size itself to the available room.
5561 const asideRef = useRef < HTMLElement > ( null )
56- const [ canvas , setCanvas ] = useState ( { w : 0 , h : 0 } )
62+ const [ canvas , setCanvas ] = useState ( { w : 0 , h : 0 , compact : false } )
5763
5864 useLayoutEffect ( ( ) => {
5965 const aside = asideRef . current
6066 const parent = aside ?. offsetParent as HTMLElement | null
6167 if ( ! aside || ! parent ) return
68+ const mobileQuery = window . matchMedia ( MOBILE_VIEW_QUERY )
6269 const measure = ( ) => {
6370 const rect = parent . getBoundingClientRect ( )
6471 // Size the grid to the palette's ACTUAL available height — the gap between
@@ -74,21 +81,33 @@ export const Sidebar = () => {
7481 ? controls . getBoundingClientRect ( ) . top - GAP
7582 : rect . bottom - ( asideTop - rect . top ) // symmetric fallback
7683 const h = Math . max ( 0 , bottomLimit - asideTop )
77- setCanvas ( { w : rect . width , h } )
84+ setCanvas ( { w : rect . width , h, compact : mobileQuery . matches } )
7885 }
7986 measure ( )
8087 const observer = new ResizeObserver ( measure )
8188 observer . observe ( parent )
82- return ( ) => observer . disconnect ( )
89+ mobileQuery . addEventListener ( "change" , measure )
90+ return ( ) => {
91+ observer . disconnect ( )
92+ mobileQuery . removeEventListener ( "change" , measure )
93+ }
8394 } , [ ] )
8495
8596 // The color-description element is the last grid cell.
8697 const cellCount = paletteItems . length + 1
8798 const chromeHeight = showInteractiveSelectionView ? VIEW_SWITCH_HEIGHT : 0
8899 const layout = useMemo (
89- ( ) => computePaletteLayout ( cellCount , canvas . w , canvas . h , chromeHeight ) ,
90- [ cellCount , canvas . w , canvas . h , chromeHeight ]
100+ ( ) =>
101+ computePaletteLayout (
102+ cellCount ,
103+ canvas . w ,
104+ canvas . h ,
105+ chromeHeight ,
106+ canvas . compact
107+ ) ,
108+ [ cellCount , canvas . w , canvas . h , canvas . compact , chromeHeight ]
91109 )
110+ const paletteMetrics = canvas . compact ? COMPACT_PALETTE : PALETTE
92111
93112 // One uniform scale for the whole palette: pick the largest scale at which
94113 // EVERY element still fits its cell, then render them all at it. This keeps
@@ -103,11 +122,12 @@ export const Sidebar = () => {
103122 config . width ,
104123 config . height + previewExtraHeight ( config . type ) ,
105124 layout . cellW ,
106- layout . cellH
125+ layout . cellH ,
126+ canvas . compact
107127 )
108128 )
109129 )
110- } , [ paletteItems , layout . cellW , layout . cellH ] )
130+ } , [ paletteItems , layout . cellW , layout . cellH , canvas . compact ] )
111131
112132 if ( paletteItems . length === 0 ) {
113133 return null
@@ -196,7 +216,7 @@ export const Sidebar = () => {
196216 className = "apollon-palette__entries"
197217 style = { {
198218 gridTemplateColumns : `repeat(${ layout . cols } , ${ layout . cellW } px)` ,
199- gap : PALETTE . GAP ,
219+ gap : paletteMetrics . GAP ,
200220 } }
201221 >
202222 { paletteItems . map ( ( config , index ) =>
0 commit comments