[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"navigation":3,"url-settings":86,"blog-\u002Fblog\u002Fbuild-a-macos-inspired-dock-with-flutter":663,"blog-author-\u002Fblog\u002Fbuild-a-macos-inspired-dock-with-flutter":1577,"i-material-symbols:arrow-back-rounded":1592},{"id":4,"extension":5,"footer":6,"header":73,"meta":83,"stem":84,"__hash__":85},"navigation\u002Fdata\u002Fshared\u002Fnavigation.yml","yml",{"brand":7,"columns":13,"legal":63},{"name":8,"tagline":9,"downloadCta":10},"Pieces","The memory layer for modern work.",{"label":11,"href":12},"All downloads","\u002Fdownloads",[14,26,39,51],{"title":15,"links":16},"Product",[17,20,23],{"label":18,"href":19},"Pieces Desktop","\u002F",{"label":21,"href":22},"Pieces Enterprise","\u002Fenterprise",{"label":24,"href":25},"Pieces MCP","\u002Fmcp",{"title":27,"links":28},"Resources",[29,33,36],{"label":30,"href":31,"external":32},"Documentation","url:docs.home",true,{"label":34,"href":35},"Blog","\u002Fblog",{"label":37,"href":38,"external":32},"GitHub","url:github.org",{"title":40,"links":41},"Community",[42,45,48],{"label":43,"href":44,"external":32},"Discord","url:social.discord",{"label":46,"href":47,"external":32},"X \u002F Twitter","url:social.x",{"label":49,"href":50,"external":32},"LinkedIn","url:social.linkedin",{"title":52,"links":53},"Company",[54,57,60],{"label":55,"href":56},"About","\u002Fabout",{"label":58,"href":59},"Updates","\u002Fupdates",{"label":61,"href":62},"Contact","\u002Fcontact",[64,67,70],{"label":65,"href":66},"Privacy Policy","\u002Flegal\u002Fprivacy",{"label":68,"href":69},"Refund Policy","\u002Flegal\u002Frefund",{"label":71,"href":72},"Terms of Service","\u002Flegal\u002Fterms",{"links":74,"signIn":75,"contact":78,"cta":80},[],{"label":76,"href":77},"Sign in","url:portal.home",{"label":79,"href":62},"Get in touch",{"label":81,"href":82},"Download","url:routes.downloads",{},"data\u002Fshared\u002Fnavigation","VdirGIa8cUm6xLprbBeTKcw914JfyJjWfF-9hSVOX5Y",{"id":87,"extension":5,"links":88,"meta":660,"stem":661,"__hash__":662},"urlSettings\u002Fdata\u002Fshared\u002Furls.yml",[89,93,97,101,105,109,113,117,121,125,129,133,137,141,145,149,153,157,161,165,169,173,177,181,185,189,192,196,200,204,208,212,216,220,224,228,232,236,240,244,248,252,256,260,264,268,272,276,280,284,288,292,295,299,303,306,310,314,318,322,326,330,334,338,342,346,350,354,358,362,366,370,374,378,382,386,390,394,398,402,406,410,414,418,422,426,430,434,438,442,446,450,453,457,461,465,469,473,477,480,483,486,489,493,497,500,504,508,512,516,520,524,528,532,536,540,544,548,551,555,559,563,567,571,574,577,580,584,587,591,595,599,603,606,610,614,617,620,623,627,631,635,638,641,644,648,652,656],{"key":90,"label":91,"href":92},"downloads.desktop","Desktop download page","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fdownload",{"key":94,"label":95,"href":96},"downloads.macOS.dmgArm64","macOS DMG Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fdmg-arm64\u002Fdownload",{"key":98,"label":99,"href":100},"downloads.macOS.dmgIntel","macOS DMG Intel","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fdmg\u002Fdownload",{"key":102,"label":103,"href":104},"downloads.macOS.pkg","macOS PKG","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg\u002Fdownload",{"key":106,"label":107,"href":108},"downloads.macOS.universal","Desktop macOS Universal","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fmacos-universal\u002Fdownload",{"key":110,"label":111,"href":112},"downloads.macOS.pkgArm64","Desktop macOS PKG Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-pfd-arm64\u002Fdownload",{"key":114,"label":115,"href":116},"downloads.macOS.pkgIntel","Desktop macOS PKG Intel","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-pfd\u002Fdownload",{"key":118,"label":119,"href":120},"downloads.windows.appinstaller","Windows App Installer","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fappinstaller\u002Fpieces_for_x.appinstaller",{"key":122,"label":123,"href":124},"downloads.windows.exe","Windows EXE","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fwindows-exe\u002Fdownload",{"key":126,"label":127,"href":128},"downloads.windows.msix","Windows MSIX","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fwindows-msix\u002Fdownload",{"key":130,"label":131,"href":132},"downloads.windows.suiteManager","Windows Suite Manager","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_suite_windows\u002Fappinstaller\u002Fdownload",{"key":134,"label":135,"href":136},"downloads.linux.flatpakRepo","Linux Flatpak repository","https:\u002F\u002Fbuilds.pieces.app\u002Fpieces-flatpak-repo\u002Fpieces-flatpak.flatpakrepo",{"key":138,"label":139,"href":140},"downloads.linux.snapDesktop","Linux Snap Desktop","https:\u002F\u002Fsnapcraft.io\u002Fpieces-for-developers",{"key":142,"label":143,"href":144},"downloads.linux.snapPiecesOS","Linux Snap PiecesOS","https:\u002F\u002Fsnapcraft.io\u002Fpieces-os",{"key":146,"label":147,"href":148},"downloads.linux.snap","Desktop Linux Snap package","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fsnap\u002Fdownload",{"key":150,"label":151,"href":152},"downloads.piecesOS.macOS.dmgArm64","PiecesOS macOS DMG Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fdmg-arm64\u002Fdownload",{"key":154,"label":155,"href":156},"downloads.piecesOS.macOS.dmgIntel","PiecesOS macOS DMG Intel","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fdmg\u002Fdownload",{"key":158,"label":159,"href":160},"downloads.piecesOS.macOS.universal","PiecesOS macOS Universal","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fmacos-universal\u002Fdownload",{"key":162,"label":163,"href":164},"downloads.piecesOS.macOS.pkgArm64","PiecesOS macOS PKG Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-pos-launch-only-arm64\u002Fdownload",{"key":166,"label":167,"href":168},"downloads.piecesOS.macOS.pkgIntel","PiecesOS macOS PKG Intel","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-pos-launch-only\u002Fdownload",{"key":170,"label":171,"href":172},"downloads.piecesOS.windows.appinstaller","PiecesOS Windows App Installer","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fappinstaller\u002Fos_server.appinstaller",{"key":174,"label":175,"href":176},"downloads.piecesOS.windows.exe","PiecesOS Windows EXE","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fwindows-exe\u002Fdownload",{"key":178,"label":179,"href":180},"downloads.piecesOS.windows.msix","PiecesOS Windows MSIX","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fwindows-msix\u002Fdownload",{"key":182,"label":183,"href":184},"downloads.piecesOS.linux.snap","PiecesOS Linux Snap package","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fsnap\u002Fdownload",{"key":186,"label":187,"href":188},"downloads.combined.macOS.appleSilicon","Combined macOS installer Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-arm64\u002Fdownload",{"key":190,"label":191,"href":104},"downloads.combined.macOS.intel","Combined macOS installer Intel",{"key":193,"label":194,"href":195},"downloads.guides.macOS","macOS installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Fmacos-installation-guide",{"key":197,"label":198,"href":199},"downloads.guides.windows","Windows installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Fwindows-installation-guide",{"key":201,"label":202,"href":203},"downloads.guides.linux","Linux installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Flinux-installation-guide",{"key":205,"label":206,"href":207},"downloads.guides.piecesOS","PiecesOS manual installation","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os\u002Fmanual-installation",{"key":209,"label":210,"href":211},"extensions.chrome","Chrome extension","https:\u002F\u002Fchrome.google.com\u002Fwebstore\u002Fdetail\u002Fpieces-save-code-snippets\u002Figbgibhbfonhmjlechmeefimncpekepm",{"key":213,"label":214,"href":215},"extensions.firefox","Firefox add-on","https:\u002F\u002Faddons.mozilla.org\u002Fen-US\u002Ffirefox\u002Faddon\u002Fpieces-save-code-from-the-web\u002F",{"key":217,"label":218,"href":219},"extensions.edge","Edge add-on","https:\u002F\u002Fmicrosoftedge.microsoft.com\u002Faddons\u002Fdetail\u002Fpieces-save-code-snippet\u002Fhglfimcdgonaeeobjckfdabcldfidmim",{"key":221,"label":222,"href":223},"extensions.vscode","VS Code extension","https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=MeshIntelligentTechnologiesInc.pieces-vscode",{"key":225,"label":226,"href":227},"extensions.visualStudio","Visual Studio extension","https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=MeshIntelligentTechnologiesInc.PiecesVisualStudio",{"key":229,"label":230,"href":231},"extensions.jetbrains","JetBrains plugin","https:\u002F\u002Fplugins.jetbrains.com\u002Fplugin\u002F17328-pieces--save-search-share--reuse-code-snippets",{"key":233,"label":234,"href":235},"extensions.obsidian","Obsidian plugin","https:\u002F\u002Fobsidian.md\u002Fplugins?id=pieces-for-developers",{"key":237,"label":238,"href":239},"extensions.sublime","Sublime package","https:\u002F\u002Fpackagecontrol.io\u002Fpackages\u002FPieces",{"key":241,"label":242,"href":243},"extensions.neovim","Neovim plugin","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fplugin_neo_vim",{"key":245,"label":246,"href":247},"extensions.jupyterlab","JupyterLab plugin","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fjupyterlab-pieces",{"key":249,"label":250,"href":251},"extensions.cli","Pieces CLI","https:\u002F\u002Fpypi.org\u002Fproject\u002Fpieces-cli\u002F",{"key":253,"label":254,"href":255},"docs.home","Documentation home","https:\u002F\u002Fdocs.pieces.app",{"key":257,"label":258,"href":259},"docs.getStarted","Get started docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces",{"key":261,"label":262,"href":263},"docs.api","API docs","https:\u002F\u002Fdocs.pieces.app\u002Fapi",{"key":265,"label":266,"href":267},"docs.desktop.overview","Desktop overview","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop",{"key":269,"label":270,"href":271},"docs.desktop.onboarding","Desktop onboarding","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fonboarding",{"key":273,"label":274,"href":275},"docs.desktop.timeline","Desktop timeline docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Ftimeline",{"key":277,"label":278,"href":279},"docs.desktop.summaries","Desktop summaries docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fsingle-click-summaries",{"key":281,"label":282,"href":283},"docs.desktop.search","Desktop conversational search docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fconversational-search",{"key":285,"label":286,"href":287},"docs.desktop.drive","Desktop drive docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fdrive",{"key":289,"label":290,"href":291},"docs.desktop.account","Desktop account settings docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fconfiguration\u002Faccount",{"key":293,"label":294,"href":92},"docs.desktop.download","Desktop download docs",{"key":296,"label":297,"href":298},"docs.piecesOS.overview","PiecesOS overview docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies",{"key":300,"label":301,"href":302},"docs.piecesOS.details","PiecesOS details docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os",{"key":304,"label":305,"href":207},"docs.piecesOS.install","PiecesOS install docs",{"key":307,"label":308,"href":309},"docs.piecesOS.quickMenu","PiecesOS quick menu docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os\u002Fquick-menu",{"key":311,"label":312,"href":313},"docs.piecesOS.storage","On-device storage docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fon-device-storage",{"key":315,"label":316,"href":317},"docs.piecesOS.troubleshooting","PiecesOS troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os\u002Ftroubleshooting",{"key":319,"label":320,"href":321},"docs.mcp.overview","MCP overview docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp",{"key":323,"label":324,"href":325},"docs.mcp.cursor","MCP Cursor docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fcursor",{"key":327,"label":328,"href":329},"docs.mcp.vscode","MCP VS Code docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fvs-code",{"key":331,"label":332,"href":333},"docs.mcp.claudeDesktop","MCP Claude Desktop docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fclaude-desktop",{"key":335,"label":336,"href":337},"docs.mcp.claudeCode","MCP Claude Code docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fclaude-code",{"key":339,"label":340,"href":341},"docs.mcp.claudeCowork","MCP Claude Cowork docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fclaude-cowork",{"key":343,"label":344,"href":345},"docs.mcp.githubCopilot","MCP GitHub Copilot docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fgithub-copilot",{"key":347,"label":348,"href":349},"docs.mcp.goose","MCP Goose docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fgoose",{"key":351,"label":352,"href":353},"docs.mcp.windsurf","MCP Windsurf docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fwindsurf",{"key":355,"label":356,"href":357},"docs.mcp.zed","MCP Zed docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fzed",{"key":359,"label":360,"href":361},"docs.mcp.jetbrains","MCP JetBrains docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fjetbrains-ides",{"key":363,"label":364,"href":365},"docs.mcp.continueDev","MCP Continue docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fcontinue-dev",{"key":367,"label":368,"href":369},"docs.mcp.cline","MCP Cline docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fcline",{"key":371,"label":372,"href":373},"docs.mcp.raycast","MCP Raycast docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fraycast",{"key":375,"label":376,"href":377},"docs.mcp.rovoDevCli","MCP Rovo Dev CLI docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Frovo-dev-cli",{"key":379,"label":380,"href":381},"docs.mcp.openaiCodexCli","MCP OpenAI Codex CLI docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fopenai-codex-cli",{"key":383,"label":384,"href":385},"docs.mcp.googleGeminiCli","MCP Google Gemini CLI docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fgoogle-gemini-cli",{"key":387,"label":388,"href":389},"docs.mcp.amazonQ","MCP Amazon Q docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Famazon-q-developer",{"key":391,"label":392,"href":393},"docs.mcp.chatgptDev","MCP ChatGPT Developer Mode docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fchatgpt-developer-mode",{"key":395,"label":396,"href":397},"docs.mcp.openclaw","MCP OpenClaw docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fopenclaw",{"key":399,"label":400,"href":401},"docs.mcp.mcpRemote","MCP Remote docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fmcp-remote",{"key":403,"label":404,"href":405},"docs.mcp.ngrok","MCP ngrok docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fngrok-setup",{"key":407,"label":408,"href":409},"docs.troubleshooting.macOS","macOS troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Ftroubleshooting\u002Fmacos",{"key":411,"label":412,"href":413},"docs.troubleshooting.windows","Windows troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Ftroubleshooting\u002Fwindows",{"key":415,"label":416,"href":417},"docs.troubleshooting.linux","Linux troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Ftroubleshooting\u002Flinux",{"key":419,"label":420,"href":421},"docs.privacy","Privacy and security docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fprivacy-security-your-data",{"key":423,"label":424,"href":425},"docs.support","Support docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fsupport",{"key":427,"label":428,"href":429},"portal.home","Pieces portal","https:\u002F\u002Fportal.pieces.app",{"key":431,"label":432,"href":433},"site.home","Website home","https:\u002F\u002Fpieces.app",{"key":435,"label":436,"href":437},"site.about","About page","https:\u002F\u002Fpieces.app\u002Fabout",{"key":439,"label":440,"href":441},"site.features","Features page","https:\u002F\u002Fpieces.app\u002Ffeatures",{"key":443,"label":444,"href":445},"site.plugins","Plugins page","https:\u002F\u002Fpieces.app\u002Fplugins",{"key":447,"label":448,"href":449},"site.contact","Contact page","https:\u002F\u002Fpieces.app\u002Fcontact",{"key":451,"label":58,"href":452},"site.updates","https:\u002F\u002Fpieces.app\u002Fupdates",{"key":454,"label":455,"href":456},"site.news","News","https:\u002F\u002Fpieces.app\u002Fnews",{"key":458,"label":459,"href":460},"site.events","Community events","https:\u002F\u002Fpieces.app\u002Fcommunity\u002Fevents",{"key":462,"label":463,"href":464},"site.userStories","User stories","https:\u002F\u002Fpieces.app\u002Fuser-stories",{"key":466,"label":467,"href":468},"site.academy","Academy","https:\u002F\u002Fpieces.app\u002Flearn\u002Facademy",{"key":470,"label":471,"href":472},"site.support","Website support","https:\u002F\u002Fpieces.app\u002Fsupport",{"key":474,"label":475,"href":476},"site.standup","Standup","https:\u002F\u002Fpieces.app\u002Fstandup",{"key":478,"label":34,"href":479},"site.blog","https:\u002F\u002Fcode.pieces.app\u002Fblog",{"key":481,"label":43,"href":482},"social.discord","https:\u002F\u002Fdiscord.gg\u002Fgetpieces",{"key":484,"label":46,"href":485},"social.x","https:\u002F\u002Fx.com\u002Fgetpieces",{"key":487,"label":488,"href":485},"social.twitter","Twitter",{"key":490,"label":491,"href":492},"social.instagram","Instagram","https:\u002F\u002Fwww.instagram.com\u002Fgetpieces\u002F",{"key":494,"label":495,"href":496},"social.tiktok","TikTok","https:\u002F\u002Fwww.tiktok.com\u002F@getpieces",{"key":498,"label":49,"href":499},"social.linkedin","https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002Fgetpieces\u002F",{"key":501,"label":502,"href":503},"social.youtube","YouTube","https:\u002F\u002Fyoutube.com\u002F@getpieces",{"key":505,"label":506,"href":507},"github.org","GitHub organization","https:\u002F\u002Fgithub.com\u002Fpieces-app",{"key":509,"label":510,"href":511},"github.support","GitHub support","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fsupport",{"key":513,"label":514,"href":515},"github.issues","GitHub issues","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fsupport\u002Fissues",{"key":517,"label":518,"href":519},"github.discussions","GitHub discussions","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fsupport\u002Fdiscussions",{"key":521,"label":522,"href":523},"github.documentation","GitHub documentation","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fdocumentation",{"key":525,"label":526,"href":527},"github.opensource","GitHub open source","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fopensource",{"key":529,"label":530,"href":531},"github.sdks.python","Python SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-python",{"key":533,"label":534,"href":535},"github.sdks.typescript","TypeScript SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-typescript",{"key":537,"label":538,"href":539},"github.sdks.dart","Dart SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-dart",{"key":541,"label":542,"href":543},"github.sdks.kotlin","Kotlin SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-kotlin",{"key":545,"label":546,"href":547},"github.plugins.obsidian","Obsidian plugin repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fobsidian-pieces",{"key":549,"label":550,"href":247},"github.plugins.jupyterlab","JupyterLab plugin repository",{"key":552,"label":553,"href":554},"github.plugins.sublime","Sublime plugin repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fplugin_sublime",{"key":556,"label":557,"href":558},"github.plugins.neovim","Neovim plugin repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fplugin_neovim",{"key":560,"label":561,"href":562},"github.cliAgent","CLI agent repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fcli-agent",{"key":564,"label":565,"href":566},"github.mcpDart","MCP Dart repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fmcp_dart",{"key":568,"label":569,"href":570},"github.awesomePieces","Awesome Pieces repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fawesome-pieces",{"key":572,"label":573,"href":66},"legal.privacyPolicy","Privacy policy",{"key":575,"label":576,"href":69},"legal.refundPolicy","Refund policy",{"key":578,"label":579,"href":72},"legal.terms","Terms",{"key":581,"label":582,"href":583},"legal.security","Legal security","https:\u002F\u002Fpieces.app\u002Flegal\u002Fsecurity",{"key":585,"label":586,"href":503},"videos.youtubeChannel","YouTube channel",{"key":588,"label":589,"href":590},"videos.gettingStartedDesktop","Getting started desktop video","https:\u002F\u002Fyoutu.be\u002FdUr1lRM_TYk",{"key":592,"label":593,"href":594},"videos.snippetDiscoveryxR","Snippet discovery video","https:\u002F\u002Fyoutu.be\u002FG6vb1USw-30",{"key":596,"label":597,"href":598},"sales.bookACall","Book a sales call","https:\u002F\u002Fcalendar.app.google\u002FWVUDtUfNy5Vst3sH7",{"key":600,"label":601,"href":602},"sales.enterprise","Enterprise form","https:\u002F\u002Fgetpieces.typeform.com\u002Fto\u002FaVQFTvpE",{"key":604,"label":605,"href":519},"sales.feedback","Feedback discussions",{"key":607,"label":608,"href":609},"sales.earlyAccess","Early access form","https:\u002F\u002Fgetpieces.typeform.com\u002Fearlyaccess",{"key":611,"label":612,"href":613},"sales.supportEmail","Support email","mailto:support@pieces.app",{"key":615,"label":616,"href":19},"routes.home","Home route",{"key":618,"label":619,"href":56},"routes.about","About route",{"key":621,"label":622,"href":12},"routes.downloads","Downloads route",{"key":624,"label":625,"href":626},"routes.thanks","Post-install thanks route","\u002Finstall\u002Fthanks",{"key":628,"label":629,"href":630},"routes.pricing","Pricing route","\u002Fpricing",{"key":632,"label":633,"href":634},"cta.freeTrial","Start free trial CTA (Pieces Pro) — used by \u002Fcampaigns\u002F* landing pages","https:\u002F\u002Fcampaigns.pieces.app\u002F",{"key":636,"label":637,"href":22},"routes.enterprise","Enterprise route",{"key":639,"label":640,"href":62},"routes.contact","Contact route",{"key":642,"label":643,"href":59},"routes.updates","Updates route",{"key":645,"label":646,"href":647},"routes.migrationError","Migration error route","\u002Fmigration\u002Ferror",{"key":649,"label":650,"href":651},"routes.authenticated","Post-login authenticated route","\u002Fauth\u002Fsigned-in",{"key":653,"label":654,"href":655},"routes.signed-out","Signed out route","\u002Fauth\u002Fsigned-out",{"key":657,"label":658,"href":659},"routes.authentication-error","Authentication error route","\u002Fauth\u002Ferror",{},"data\u002Fshared\u002Furls","NLkVE1lIUws518K-1QsSB6T-GvlXYIzcRL1HDhqarGQ",{"id":664,"title":665,"author":666,"authorPhoto":667,"authorPhotoAlt":668,"authorSlug":669,"body":670,"buttonText":668,"buttonUrl":668,"category":1565,"date":1566,"description":1567,"draft":1568,"editorsPick":1568,"extension":1569,"featured":1568,"image":1570,"imageAlt":1571,"meta":1572,"navigation":32,"ogImage":668,"ogImageAlt":668,"path":1573,"seo":1574,"stem":1575,"tags":668,"__hash__":1576},"blog\u002Fblog\u002Fbuild-a-macos-inspired-dock-with-flutter.md","Build an Imitation Mac Dock With Flutter","Rutvik Tak","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fbuild-a-macos-inspired-dock-with-flutter\u002Fauthor.jpeg",null,"rutvik-tak",{"type":671,"value":672,"toc":1549},"minimark",[673,677,680,687,690,703,708,724,727,730,736,740,751,763,766,771,774,777,780,786,794,801,804,807,814,817,820,839,845,851,879,883,886,889,895,898,907,910,913,917,929,935,942,945,1006,1008,1014,1018,1021,1027,1038,1043,1046,1053,1059,1065,1068,1075,1101,1104,1152,1158,1193,1198,1236,1242,1262,1268,1274,1286,1318,1330,1338,1344,1350,1356,1372,1375,1377,1383,1387,1398,1405,1415,1418,1423,1429,1435,1462,1468,1480,1483,1485,1490,1493,1503,1507,1522,1525,1529,1532,1542],[674,675,676],"p",{},"‍A couple of months ago, I started doing some UI challenges✨ in Flutter. The goal of these challenges was to be creative and explore building unique UI experiences in Flutter while sticking to what the framework offers.",[674,678,679],{},"As a result, I created some 😁 really interesting animations and designs in Flutter that showcase what you can build with it. In this article, I’ll walk you through one of my creations, inspired by the macOS dock experience.",[674,681,682],{},[683,684],"img",{"alt":685,"src":686},"The end animation of emojis that enlarge on hover.","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fbuild-a-macos-inspired-dock-with-flutter\u002Fimg-001.gif",[674,688,689],{},"By the end of this article, along with how to build this Flutter dock, you’ll have learned a little more about:",[691,692,693,697,700],"ul",{},[694,695,696],"li",{},"Constraints in Flutter",[694,698,699],{},"Implicit Animations",[694,701,702],{},"Design breakdown",[704,705,707],"h2",{"id":706},"getting-started","Getting Started",[674,709,710,717,718,723],{},[711,712,716],"a",{"href":713,"rel":714},"https:\u002F\u002Fgithub.com\u002Frutvik110\u002FMacOS-Inspired-Doc-Starter",[715],"nofollow","Download the starter project",". If you're not familiar with Flutter, check out this guide to ",[711,719,722],{"href":720,"rel":721},"https:\u002F\u002Fpieces.app\u002Fblog\u002Fbuilding-a-flutter-web-app-from-scratch-a-complete-guide",[715],"building a Flutter app from scratch",".",[674,725,726],{},"Once you build it, you’ll see a black screen, but we’ll soon add our animated dock there.🧑🏽💻",[674,728,729],{},"Build & run:",[674,731,732],{},[683,733],{"alt":734,"src":735},"A blank flutter UI.","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fbuild-a-macos-inspired-dock-with-flutter\u002Fimg-002.png",[704,737,739],{"id":738},"constraints-and-implicit-animations","Constraints And Implicit Animations",[674,741,742,743,747,748,750],{},"Before getting our hands dirty in the code, are you familiar with ",[744,745,746],"strong",{},"Constraints"," and ",[744,749,699],{}," in Flutter? 🤔",[674,752,753,754,747,756,758,759,762],{},"If you are, then you can skip the next two sections, which talk about ",[744,755,746],{},[744,757,699],{},", and 🏎 race straight up to the ",[744,760,761],{},"Design Breakdown"," section.",[674,764,765],{},"But if you’re not familiar, then you should read through the following two sections to understand some basics of these two topics.",[767,768,770],"h3",{"id":769},"understanding-flutter-constraints","Understanding Flutter Constraints",[674,772,773],{},"UI development in Flutter is quite different from the way it is in HTML and other frameworks.",[674,775,776],{},"We don’t deal with sizes directly, but rather with constraints. The constraints are basically a set of four points: the min-max width and the min-max height.",[674,778,779],{},"There’s one rule of thumb that guides Flutter UI development:",[674,781,782],{},[683,783],{"alt":784,"src":785},"Constraints go down. Sizes go up. Parent sets position.","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fbuild-a-macos-inspired-dock-with-flutter\u002Fimg-003.png",[674,787,788,789],{},"From ",[711,790,793],{"href":791,"rel":792},"https:\u002F\u002Fdocs.flutter.dev\u002Fdevelopment\u002Fui\u002Flayout\u002Fconstraints",[715],"flutter.dev",[674,795,796,797,800],{},"While you’re building Flutter UI, you will see this ",[744,798,799],{},"parent-child composition",". When the parent widget wants to lay out on the screen, it checks if it has any children. If it does, then it passes its constraints to its children and asks them how big\u002Fsmall they want to be. The child widget may repeat this process if it has children of its own.",[674,802,803],{},"Once the Parent gets the sizes for each of its child widgets, it then checks those sizes against its own constraints. Based on this, it calculates the final size for each of its child widgets and lays them out.",[674,805,806],{},"As you can see, the one in control of determining the size and position of a widget is the Parent widget, not the Child widget.",[674,808,809,810,723],{},"This is too big a topic to continue in this article; if you want to read about this in more depth, ",[711,811,813],{"href":791,"rel":812},[715],"check out the official docs",[767,815,699],{"id":816},"implicit-animations",[674,818,819],{},"One of the reasons it's easy to build beautiful Flutter animations is that it provides many ways to animate widgets depending on your use case.",[674,821,822,823,826,827,830,831,834,835,838],{},"One of the ways is using ",[744,824,825],{},"AnimatedFoo"," widgets (also called  ",[744,828,829],{},"Implicit Animation"," ",[744,832,833],{},"Widgets","), where ",[744,836,837],{},"Foo"," is the property that you want animate.",[674,840,841],{},[683,842],{"alt":843,"src":844},"A gif of five different common Flutter animations.","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fbuild-a-macos-inspired-dock-with-flutter\u002Fimg-004.gif",[674,846,847,848,850],{},"When working with ",[744,849,825],{}," widgets, you only have to worry about providing the property value. AnimatedFoo widgets handle the animation flow, or the transition from the old value to the new value whenever the property value changes. These will be important for our Mac dock later!",[674,852,853,854,856,857,860,861,860,864,860,867,870,871,873,874,723],{},"There are different ",[744,855,825],{}," widgets for animating the different properties of a widget, like ",[744,858,859],{},"AnimatedScale",", ",[744,862,863],{},"AnimatedOpacity",[744,865,866],{},"AnimatedSize",[744,868,869],{},"AnimatedContainer",", etc. We’ll be making use of some of these ",[744,872,825],{}," widgets. You can learn more about them in ",[711,875,878],{"href":876,"rel":877},"https:\u002F\u002Fdocs.flutter.dev\u002Fdevelopment\u002Fui\u002Fanimations\u002Fimplicit-animations",[715],"the official docs",[704,880,882],{"id":881},"mac-dock-design-breakdown","Mac Dock Design Breakdown",[674,884,885],{},"When you’re trying to build animations or any kind of interaction, try to always break down the design into parts. Then, understand each part and its animations and how it’s affected by other components in the design.",[674,887,888],{},"Below is a breakdown of our MacOS dock design:",[674,890,891],{},[683,892],{"alt":893,"src":894},"The two main components of the mac dock: the emojis and the gradient background.","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fbuild-a-macos-inspired-dock-with-flutter\u002Fimg-005.gif",[674,896,897],{},"As you can see, there are two main components here:",[899,900,901,904],"ol",{},[694,902,903],{},"The row of items",[694,905,906],{},"The Mac dock",[674,908,909],{},"The item’s row is stacked on top of the dock. Both of these components have different behaviors when you hover over any one of the items. Our items scale and translate along the Y-axis while the dock’s width increases as items are scaled.",[674,911,912],{},"In the next sections, we’ll explore how these Flutter animations work in detail and see how we can implement them.",[767,914,916],{"id":915},"adding-the-items","Adding The Items",[674,918,919,920,923,924,928],{},"In ",[744,921,922],{},"lib\u002Fmacos_doc.dart",", replace the ",[925,926,927],"em",{},"\u002F\u002FTODO: add items ui"," with the following code:",[674,930,931],{},[683,932],{"alt":933,"src":934},"A Flutter widget code snippet.","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fbuild-a-macos-inspired-dock-with-flutter\u002Fimg-006.png",[674,936,937],{},[711,938,941],{"href":939,"rel":940},"https:\u002F\u002Framan.pieces.cloud\u002F?p=823140b916",[715],"Save to Pieces",[674,943,944],{},"Let’s go over the code step-by-step:",[899,946,947,961,979,990,996],{},[694,948,949,952,953,956,957,960],{},[744,950,951],{},"Items Row:"," The row holding the items has the ",[925,954,955],{},"mainAxisSize"," set to ",[925,958,959],{},"mainAxisSize.min",". This tells the row to size itself to the combined width of the items within it, instead of expanding to capture all of the available width along the main axis.",[694,962,963,966,967,970,971,974,975,978],{},[744,964,965],{},"MouseRegion:"," Flutter provides a ",[744,968,969],{},"MouseRegion"," widget which we can use to be notified when the user hovers on our item. When the mouse is within the item hover region, we set the ",[925,972,973],{},"hoveredIndex"," to that item’s index and reset it to ",[925,976,977],{},"null"," when the mouse exits the item’s hover region.",[694,980,981,984,985,987,988,723],{},[744,982,983],{},"AnimatedContainer:"," This is the container that holds our item. It’s an ",[744,986,869],{}," which will animate its scale and translate itself depending on the ",[925,989,973],{},[694,991,992,995],{},[744,993,994],{},"FittedBox",": If the child of this widget has a size larger than the constraints passed down to it, then this widget will scale and position the child to fit within the constraints based on the fit set.",[694,997,998,1001,1002,1005],{},[744,999,1000],{},"The item:"," The item in our case is text, so I’m using the ",[744,1003,1004],{},"AnimatedDefaultTextStyle"," for scaling. Your item can be anything else, including an icon or an SVG. Use the appropriate Flutter animation widgets to get the smooth scale animation for them.",[674,1007,729],{},[674,1009,1010],{},[683,1011],{"alt":1012,"src":1013},"Emojis on a black background.","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fbuild-a-macos-inspired-dock-with-flutter\u002Fimg-007.png",[767,1015,1017],{"id":1016},"animating-the-items","Animating The Items",[674,1019,1020],{},"Let’s dive a little deeper into our item’s animations.",[674,1022,1023],{},[683,1024],{"alt":1025,"src":1026},"Emojis expanding on hover.","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fbuild-a-macos-inspired-dock-with-flutter\u002Fimg-008.gif",[674,1028,1029,1030,1033,1034,1037],{},"Each item on our Mac dock has two animation properties. The first one is the change in its ",[744,1031,1032],{},"size,"," and the second is its ",[744,1035,1036],{},"translation along the Y-axis",". The item in focus has the max scale and the max translation along the Y-axis. The other items are then scaled and translated accordingly.",[674,1039,1040,1041,723],{},"Now, both of these properties change for items depending on their position from the hovered item. The trick to this animation is to calculate these two properties based on the item’s index and the ",[925,1042,973],{},[674,1044,1045],{},"Let’s see how we can calculate those values!",[674,1047,1048,1049,1052],{},"Replace ",[925,1050,1051],{},"\u002F\u002FTODO: add getPropertyValue method"," with the following code :",[674,1054,1055],{},[683,1056],{"alt":1057,"src":1058},"An animated dock Flutter widget.","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fbuild-a-macos-inspired-dock-with-flutter\u002Fimg-009.png",[674,1060,1061],{},[711,1062,941],{"href":1063,"rel":1064},"https:\u002F\u002Framan.pieces.cloud\u002F?p=de6c4086f4",[715],[674,1066,1067],{},"First of all, if you’re scared a bit 😅 because of all of the math this method is screaming at you, don’t worry! It’s actually really simple. 😄 I’ll try my best to explain what’s going on here.",[674,1069,1070,1071,1074],{},"The ",[925,1072,1073],{},"getPropertyValue"," method is a general property value calculator for our scale and translation properties. It has four parameters:",[899,1076,1077,1083,1089,1095],{},[694,1078,1079,1082],{},[744,1080,1081],{},"index:"," Index of the item for whom the value needs to be calculated.",[694,1084,1085,1088],{},[744,1086,1087],{},"baseValue:"," Value when none of the items are in focus.",[694,1090,1091,1094],{},[744,1092,1093],{},"maxValue:"," Value for the hovered item.",[694,1096,1097,1100],{},[744,1098,1099],{},"nonHoveredMaxValue:"," Maximum value for the items around the hovered item.",[674,1102,1103],{},"Let's go over the method step-by-step.",[899,1105,1106,1115],{},[694,1107,1108,1109,1111,1112,723],{},"Check if ",[925,1110,973],{}," is null. If it is, then return ",[925,1113,1114],{},"baseValue",[694,1116,1117,1118,1121,1122,1125,1126,1129,1130,1133,1134,1137,1138,1140,1141,1144,1145,1147,1148,1151],{},"Calculate the difference between the ",[925,1119,1120],{},"index"," of the ",[744,1123,1124],{},"hovered"," item and the ",[744,1127,1128],{},"current",". Note that ",[744,1131,1132],{},"we take the positive of the difference",". So, if we try to plot the ",[925,1135,1136],{},"difference"," for our items by assuming the ",[925,1139,973],{}," is ",[744,1142,1143],{},"2,"," then for each ",[925,1146,1120],{}," we get the following ",[744,1149,1150],{},"differences"," as shown by the graph.",[674,1153,1154],{},[683,1155],{"alt":1156,"src":1157},"A graph showing difference vs index.","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fbuild-a-macos-inspired-dock-with-flutter\u002Fimg-010.png",[674,1159,1160],{},[925,1161,1162,1168,1169,1174,1175,1180,1181,1186,1187,1192],{},[744,1163,1164],{},[1165,1166,1167],"span",{},"0"," -> 2, ",[744,1170,1171],{},[1165,1172,1173],{},"1"," ->1, ",[744,1176,1177],{},[1165,1178,1179],{},"2"," ->0, ",[744,1182,1183],{},[1165,1184,1185],{},"3","->1, ",[744,1188,1189],{},[1165,1190,1191],{},"4","->2",[674,1194,1195,1196,723],{},"Note how the difference is distributed equally on left and right of the ",[925,1197,973],{},[899,1199,1201,1213],{"start":1200},3,[694,1202,1203,1204,747,1206,1208,1209,1212],{},"For the hovered item, the difference would be 0, as ",[925,1205,973],{},[925,1207,1120],{}," would be the same. So, we return the ",[925,1210,1211],{},"maxValue"," for it.",[694,1214,1215,1216,1219,1220,1223,1224,1227,1228,1230,1231,1233,1234,723],{},"If the difference is ",[744,1217,1218],{},"less than or equal"," to the ",[925,1221,1222],{},"itemsAffected",", then we do two things. First, calculate a ",[925,1225,1226],{},"ratio",", which is the value between 0.0–1.0 obtained by subtracting the ",[925,1229,1136],{}," from ",[925,1232,1222],{}," and then dividing it by ",[925,1235,1222],{},[674,1237,1238],{},[683,1239],{"alt":1240,"src":1241},"A graph showing ratio vs index.","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fbuild-a-macos-inspired-dock-with-flutter\u002Fimg-011.png",[674,1243,1244,1245,1248,1249,1252,1253,747,1255,1258,1259,1261],{},"Then, the ",[925,1246,1247],{},"propertyValue"," is calculated by doing a ",[925,1250,1251],{},"lerpDouble"," over the ",[925,1254,1114],{},[925,1256,1257],{},"nonHoveredMaxValue","; the ratio decides the ",[925,1260,1251],{}," percentage.",[674,1263,1264,1265,1267],{},"To understand what ",[925,1266,1251],{}," is actually doing, take a look at the following explainer:",[674,1269,1270],{},[683,1271],{"alt":1272,"src":1273},"A gif showing the different ratios based on cursor position.","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fbuild-a-macos-inspired-dock-with-flutter\u002Fimg-012.gif",[674,1275,1276,1278,1279,747,1281,1278,1284,723],{},[744,1277,711],{}," represents ",[925,1280,1114],{},[744,1282,1283],{},"b",[925,1285,1257],{},[674,1287,1288,1289,1292,1293,1296,1297,1300,1301,1303,1304,1306,1307,1292,1310,1296,1312,1315,1316,723],{},"For a ratio of ",[744,1290,1291],{},"0.0,"," the ",[744,1294,1295],{},"lerp"," percentage would be ",[744,1298,1299],{},"0%",", so the ",[925,1302,1247],{}," will be ",[925,1305,1114],{},". For a ratio of ",[744,1308,1309],{},"1.0,",[744,1311,1295],{},[744,1313,1314],{},"100%",", i.e., the ",[925,1317,1257],{},[674,1319,1320,1321,1323,1324,1326,1327,1329],{},"For any other ratio value, the ",[925,1322,1247],{}," will lie between the ",[925,1325,1114],{}," and the ",[925,1328,1257],{},". Thus, items that are closer to the hoveredIndex will have a slightly greater value than those that are further.",[899,1331,1333],{"start":1332},5,[694,1334,1335,1336,723],{},"If any of the conditions don’t match, we simply return the ",[925,1337,1114],{},[674,1339,1340,1341,928],{},"Now, to finally calculate our scale value and translation values for items, replace ",[925,1342,1343],{},"\u002F\u002FTODO: add scale and translation calculator methods",[674,1345,1346],{},[683,1347],{"alt":1348,"src":1349},"A Flutter code snippet.","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fbuild-a-macos-inspired-dock-with-flutter\u002Fimg-013.png",[674,1351,1352],{},[711,1353,941],{"href":1354,"rel":1355},"https:\u002F\u002Framan.pieces.cloud\u002F?p=8e3246a1ca",[715],[674,1357,1358,1359,1362,1363,747,1366,1362,1369],{},"In your item’s Flutter UI code, replace the ",[925,1360,1361],{},"baseItemHeight"," with the ",[925,1364,1365],{},"getScaledSize(index)",[925,1367,1368],{},"baseTranslationY",[925,1370,1371],{},"getTranslationY(index).",[674,1373,1374],{},"Test your animations by hovering over the items! 🙌",[674,1376,729],{},[674,1378,1379],{},[683,1380],{"alt":1381,"src":1382},"The final animated emojis.","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fbuild-a-macos-inspired-dock-with-flutter\u002Fimg-014.gif",[704,1384,1386],{"id":1385},"adding-the-mac-dock","Adding the Mac Dock",[674,1388,1389,1390,1393,1394,1397],{},"The most interesting part of this design is how we size the MacOS dock. If you look at the animation carefully, then you’ll realize that the ",[744,1391,1392],{},"width of the dock is always equal to the width of the item’s row"," and its ",[744,1395,1396],{},"height is equal to the baseHeight of the item’s row when none of the items are in focus",". As the items scale, so does the width of the animated dock.",[674,1399,1400,1401,1404],{},"But, when the ",[744,1402,1403],{},"items"," are animating, we don’t know what the width of the item’s row will be at any point in the interaction. So, how can we get around this?",[674,1406,1407,1408,1411,1412,1414],{},"We’ll use our knowledge of constraints. We need to position our dock in the ",[744,1409,1410],{},"Stack"," such that the constraints passed down to it will force it to have the maximum width of the ",[744,1413,1410],{}," but limit the height to what we want.",[674,1416,1417],{},"Let’s see how we can do this!",[674,1419,1048,1420,928],{},[925,1421,1422],{},"\u002F\u002FTODO: add Dock",[674,1424,1425],{},[683,1426],{"alt":1427,"src":1428},"A Positioned Flutter widget.","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fbuild-a-macos-inspired-dock-with-flutter\u002Fimg-015.png",[674,1430,1431],{},[711,1432,941],{"href":1433,"rel":1434},"https:\u002F\u002Framan.pieces.cloud\u002F?p=18b44fb793",[715],[674,1436,1437,1438,1441,1442,1444,1445,1447,1448,1451,1452,1455,1456,1458,1459,723],{},"Welcome, ",[744,1439,1440],{},"Positioned"," widget! This Flutter widget is used to position widgets within the Stack. Here we tell the ",[744,1443,1440],{}," widget that the child should be positioned to ",[744,1446,1167],{}," from the ",[744,1449,1450],{},"left and right edges"," of the Stack and will have a ",[744,1453,1454],{},"height"," equal to ",[925,1457,1361],{},". These constraints are then passed down to the ",[744,1460,1461],{},"DecoratedBox",[674,1463,1464,1465,1467],{},"One thing to understand about ",[744,1466,1461],{}," is that it will size itself to its child’s size when the child is present and the constraints passed to it are not forced constraints.",[674,1469,1470,1471,1473,1474,1476,1477,1479],{},"Here, as the child is not present, the ",[744,1472,1461],{}," should have zero size, but our ",[744,1475,1440],{}," widget forces it to scale within the constraints we defined as the ",[744,1478,1461],{}," itself doesn’t provide any information about its size and positioning.",[674,1481,1482],{},"Hot reload the app one final time to see our complete interaction in action! 💯",[674,1484,729],{},[674,1486,1487],{},[683,1488],{"alt":1489,"src":686},"The final animation of emojis with a gradient background.",[674,1491,1492],{},"You did it! 🥳 You now have a really cool animated dock for your Flutter apps! 💙",[674,1494,1495,830,1498],{},[744,1496,1497],{},"Src Code :",[711,1499,1502],{"href":1500,"rel":1501},"https:\u002F\u002Fgithub.com\u002Frutvik110\u002FFlutter-Animations\u002Ftree\u002Fmaster\u002Flib\u002Fflutter_design_challenges\u002Fmacos_inspired_doc",[715],"MacOS Inspired Dock In Flutter",[704,1504,1506],{"id":1505},"next-steps","Next Steps",[674,1508,1509,1510,1515,1516,1521],{},"🙏 Thanks for spending your precious time reading the article. Hope you had a blast 🙌 reading and learned some cool things!‍ If you want to check out my other creations, head over to ",[711,1511,1514],{"href":1512,"rel":1513},"https:\u002F\u002Fgithub.com\u002Frutvik110\u002FFlutter-Animations",[715],"this repo",". If you're interested in learning more about Flutter animations, check out ",[711,1517,1520],{"href":1518,"rel":1519},"https:\u002F\u002Fpieces.app\u002Fblog\u002Fcreate-mind-blowing-visuals-using-shaders-in-flutter",[715],"this tutorial to build shaders","!",[674,1523,1524],{},"Have an AMAZING day and keep Fluttering! 💙",[704,1526,1528],{"id":1527},"use-pieces-to-store-your-flutter-snippets","Use Pieces to Store Your Flutter Snippets",[674,1530,1531],{},"When developing Flutter creations, you may have tons of widgets that you want to reuse later, but you just don't have them in a safe place where you can access them. You may also comb through Flutter and Dart documentation and want to save examples that come in handy when implementing a new feature or figuring out which widget to use for different circumstances.",[674,1533,1534,1536,1537,1541],{},[744,1535,8],{}," helps you save all of your useful code snippets efficiently through a desktop application and integrations. Using Pieces, you can save any code snippets from StackOverflow with the click of a button using the ",[711,1538,1540],{"href":211,"rel":1539},[715],"web extension",", have your code autosaved from locally-hosted ML algorithms that recognize your code patterns, auto-classify snippets by language, share code with others using generated links, and more! The Pieces for Developers Suite is continuously being developed, and there’s some groundbreaking stuff that is being put together to share, reuse, and save code snippets.",[674,1543,1544,1521],{},[711,1545,1548],{"href":1546,"rel":1547},"https:\u002F\u002Fpieces.app\u002Finstall",[715],"Try Pieces now for free",{"title":1550,"searchDepth":1551,"depth":1551,"links":1552},"",2,[1553,1554,1558,1562,1563,1564],{"id":706,"depth":1551,"text":707},{"id":738,"depth":1551,"text":739,"children":1555},[1556,1557],{"id":769,"depth":1200,"text":770},{"id":816,"depth":1200,"text":699},{"id":881,"depth":1551,"text":882,"children":1559},[1560,1561],{"id":915,"depth":1200,"text":916},{"id":1016,"depth":1200,"text":1017},{"id":1385,"depth":1551,"text":1386},{"id":1505,"depth":1551,"text":1506},{"id":1527,"depth":1551,"text":1528},"Software Development","2022-07-26T00:00:00.000Z","Build a beautiful Mac dock and learn about constraints, animations and design in Flutter. Then, you can add this animation to any of your other Flutter projects!",false,"md","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fbuild-a-macos-inspired-dock-with-flutter\u002Fhero.jpg","Building a macOS inspired dock.",{},"\u002Fblog\u002Fbuild-a-macos-inspired-dock-with-flutter",{"title":665,"description":1567},"blog\u002Fbuild-a-macos-inspired-dock-with-flutter","3ZajScNhOk7vu53nn2GAbpS6qKPLpPleua5_UnBExHg",{"id":1578,"title":666,"body":1579,"description":1583,"draft":1568,"extension":1569,"meta":1586,"navigation":32,"path":1587,"photo":1588,"photoAlt":668,"seo":1589,"stem":1590,"__hash__":1591},"authors\u002Fauthors\u002Frutvik-tak.md",{"type":671,"value":1580,"toc":1584},[1581],[674,1582,1583],{},"Rutvik was introduced to world of coding through animations and games. From there he loved the creative aspects of coding and solving interesting problems. At Pieces, he takes care of the Web Extension and making sure it works across all different browsers. Beside coding, he loves to help with support, dev rel content. When he's not doing either of that, you can find him working on animations, doing calisthenics or indoor rock climbing on weekends.",{"title":1550,"searchDepth":1551,"depth":1551,"links":1585},[],{},"\u002Fauthors\u002Frutvik-tak","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fauthors\u002Frutvik-tak.jpg",{"title":666,"description":1583},"authors\u002Frutvik-tak","HWkSe6txnNhDCCk74fgii1tqQGBDyeC8l7Qydvtn8ko",{"left":1593,"top":1593,"width":1594,"height":1594,"rotate":1593,"vFlip":1568,"hFlip":1568,"body":1595},0,24,"\u003Cpath fill=\"currentColor\" d=\"m7.825 13l4.9 4.9q.3.3.288.7t-.313.7q-.3.275-.7.288t-.7-.288l-6.6-6.6q-.15-.15-.213-.325T4.426 12t.063-.375t.212-.325l6.6-6.6q.275-.275.688-.275t.712.275q.3.3.3.713t-.3.712L7.825 11H19q.425 0 .713.288T20 12t-.288.713T19 13z\"\u002F>"]