[{"data":1,"prerenderedAt":246},["ShallowReactive",2],{"project-urdock-en":3,"mdc-1jdaeo-key":31},{"id":4,"title":5,"content":6,"description":7,"endDate":8,"extension":9,"image":8,"meta":10,"poster":27,"startDate":26,"stem":28,"style":19,"tags":29,"url":18,"__hash__":30},"projects_en/en/projects/urdock.yml","UrDock — Headless Docking Layouts","> Part of **UrStack**, my open-source organization for TypeScript libraries.\nSiblings: [UrColor](/projects/urcolor), [UrVis](/projects/urvis), [UrCharts](/projects/urcharts).\n\n## Overview\n\nUrDock builds IDE-style docking layouts for Vue and React: split panes, grids,\ncollapsible regions, tabs. It ships no stylesheet at all. The library owns the\ngeometry, the consumer owns every pixel.\n\nLayout state lives in a reactive store rather than in the DOM. That turns resize\nand collapse into ordinary state transitions, and it makes a whole workspace\nlayout serializable, so you can save it, restore it, or ship it between users.\n\n---\n\n## Why I built it\n\nDocking libraries almost always arrive with a theme attached, and stripping that\ntheme out is worse than writing the layout yourself. The parts genuinely worth\nreusing are the ones nobody enjoys writing twice: split geometry, resize\nconstraints, persistence.\n\nUrDock keeps those and hands back the rendering.\n\n---\n\n## Key features\n\n- No stylesheet, no theme, no CSS variables to override\n- Four layout primitives: Splitview, Gridview, Paneview, Tabview\n- A reactive store that drives resize and collapse and persists the whole\n  workspace\n- Compound components that render real DOM elements carrying `data-*` state\n  attributes, so styling is plain CSS\n- `asChild` polymorphism, rendering as any element or component you supply\n- One model behind both the Vue and React adapters\n\n---\n\n## Tech stack\n\n::tech-carousel{:tech='[\"typescript\", \"vue\", \"react\", \"vitepress\"]'}\n::\n\n- **Core**: TypeScript, reactive layout store\n- **Adapters**: Vue, React\n- **Patterns**: compound components, `asChild` polymorphism, `data-*` state\n  attributes\n- **Docs**: VitePress\n","Split, grid, and collapsible pane layouts for Vue and React that ship zero CSS. The library owns the geometry, you own every pixel.",null,"yml",{"path":11,"body":12},"/en/projects/urdock",{"title":5,"description":7,"poster":13,"url":18,"style":19,"tags":20,"startDate":26,"content":6},{"pattern":14,"gradient":15,"color":16,"bg":17},"cross","rings","#94a22f","#14160e","https://urdock.vercel.app/","projects/urdock-styles.css",[21,22,23,24,25],"UrStack","TypeScript","Vue","React","Headless UI","2026",{"pattern":14,"gradient":15,"color":16,"bg":17},"en/projects/urdock",[21,22,23,24,25],"KMzWIQIya4pmnImIS6A5nToO4o2YZ8WMkBewWh8FSbc",{"data":32,"body":33},{},{"type":34,"children":35},"root",[36,79,86,91,96,100,106,111,116,119,125,175,178,184,189],{"type":37,"tag":38,"props":39,"children":40},"element","blockquote",{},[41],{"type":37,"tag":42,"props":43,"children":44},"p",{},[45,48,53,55,62,64,70,71,77],{"type":46,"value":47},"text","Part of ",{"type":37,"tag":49,"props":50,"children":51},"strong",{},[52],{"type":46,"value":21},{"type":46,"value":54},", my open-source organization for TypeScript libraries.\nSiblings: ",{"type":37,"tag":56,"props":57,"children":59},"a",{"href":58},"/projects/urcolor",[60],{"type":46,"value":61},"UrColor",{"type":46,"value":63},", ",{"type":37,"tag":56,"props":65,"children":67},{"href":66},"/projects/urvis",[68],{"type":46,"value":69},"UrVis",{"type":46,"value":63},{"type":37,"tag":56,"props":72,"children":74},{"href":73},"/projects/urcharts",[75],{"type":46,"value":76},"UrCharts",{"type":46,"value":78},".",{"type":37,"tag":80,"props":81,"children":83},"h2",{"id":82},"overview",[84],{"type":46,"value":85},"Overview",{"type":37,"tag":42,"props":87,"children":88},{},[89],{"type":46,"value":90},"UrDock builds IDE-style docking layouts for Vue and React: split panes, grids,\ncollapsible regions, tabs. It ships no stylesheet at all. The library owns the\ngeometry, the consumer owns every pixel.",{"type":37,"tag":42,"props":92,"children":93},{},[94],{"type":46,"value":95},"Layout state lives in a reactive store rather than in the DOM. That turns resize\nand collapse into ordinary state transitions, and it makes a whole workspace\nlayout serializable, so you can save it, restore it, or ship it between users.",{"type":37,"tag":97,"props":98,"children":99},"hr",{},[],{"type":37,"tag":80,"props":101,"children":103},{"id":102},"why-i-built-it",[104],{"type":46,"value":105},"Why I built it",{"type":37,"tag":42,"props":107,"children":108},{},[109],{"type":46,"value":110},"Docking libraries almost always arrive with a theme attached, and stripping that\ntheme out is worse than writing the layout yourself. The parts genuinely worth\nreusing are the ones nobody enjoys writing twice: split geometry, resize\nconstraints, persistence.",{"type":37,"tag":42,"props":112,"children":113},{},[114],{"type":46,"value":115},"UrDock keeps those and hands back the rendering.",{"type":37,"tag":97,"props":117,"children":118},{},[],{"type":37,"tag":80,"props":120,"children":122},{"id":121},"key-features",[123],{"type":46,"value":124},"Key features",{"type":37,"tag":126,"props":127,"children":128},"ul",{},[129,135,140,145,159,170],{"type":37,"tag":130,"props":131,"children":132},"li",{},[133],{"type":46,"value":134},"No stylesheet, no theme, no CSS variables to override",{"type":37,"tag":130,"props":136,"children":137},{},[138],{"type":46,"value":139},"Four layout primitives: Splitview, Gridview, Paneview, Tabview",{"type":37,"tag":130,"props":141,"children":142},{},[143],{"type":46,"value":144},"A reactive store that drives resize and collapse and persists the whole\nworkspace",{"type":37,"tag":130,"props":146,"children":147},{},[148,150,157],{"type":46,"value":149},"Compound components that render real DOM elements carrying ",{"type":37,"tag":151,"props":152,"children":154},"code",{"className":153},[],[155],{"type":46,"value":156},"data-*",{"type":46,"value":158}," state\nattributes, so styling is plain CSS",{"type":37,"tag":130,"props":160,"children":161},{},[162,168],{"type":37,"tag":151,"props":163,"children":165},{"className":164},[],[166],{"type":46,"value":167},"asChild",{"type":46,"value":169}," polymorphism, rendering as any element or component you supply",{"type":37,"tag":130,"props":171,"children":172},{},[173],{"type":46,"value":174},"One model behind both the Vue and React adapters",{"type":37,"tag":97,"props":176,"children":177},{},[],{"type":37,"tag":80,"props":179,"children":181},{"id":180},"tech-stack",[182],{"type":46,"value":183},"Tech stack",{"type":37,"tag":185,"props":186,"children":188},"tech-carousel",{":tech":187},"[\"typescript\", \"vue\", \"react\", \"vitepress\"]",[],{"type":37,"tag":126,"props":190,"children":191},{},[192,202,212,236],{"type":37,"tag":130,"props":193,"children":194},{},[195,200],{"type":37,"tag":49,"props":196,"children":197},{},[198],{"type":46,"value":199},"Core",{"type":46,"value":201},": TypeScript, reactive layout store",{"type":37,"tag":130,"props":203,"children":204},{},[205,210],{"type":37,"tag":49,"props":206,"children":207},{},[208],{"type":46,"value":209},"Adapters",{"type":46,"value":211},": Vue, React",{"type":37,"tag":130,"props":213,"children":214},{},[215,220,222,227,229,234],{"type":37,"tag":49,"props":216,"children":217},{},[218],{"type":46,"value":219},"Patterns",{"type":46,"value":221},": compound components, ",{"type":37,"tag":151,"props":223,"children":225},{"className":224},[],[226],{"type":46,"value":167},{"type":46,"value":228}," polymorphism, ",{"type":37,"tag":151,"props":230,"children":232},{"className":231},[],[233],{"type":46,"value":156},{"type":46,"value":235}," state\nattributes",{"type":37,"tag":130,"props":237,"children":238},{},[239,244],{"type":37,"tag":49,"props":240,"children":241},{},[242],{"type":46,"value":243},"Docs",{"type":46,"value":245},": VitePress",1785819619220]