From 580ce5bcc011b9471cf3e7bab65aa461fde91356 Mon Sep 17 00:00:00 2001 From: lucaronin Date: Sat, 21 Feb 2026 17:21:49 +0100 Subject: [PATCH 1/4] design: draggable section groups wireframes Three frames showing drag interaction flow: 1. Default sidebar with grip-vertical drag handles on section headers 2. Mid-drag state with blue drop indicator line and floating section overlay 3. After-drop state showing reordered sections Order persisted as "order" property in Type document frontmatter. Co-Authored-By: Claude Opus 4.6 --- design/draggable-section-groups.pen | 1 + 1 file changed, 1 insertion(+) create mode 100644 design/draggable-section-groups.pen diff --git a/design/draggable-section-groups.pen b/design/draggable-section-groups.pen new file mode 100644 index 00000000..50622aab --- /dev/null +++ b/design/draggable-section-groups.pen @@ -0,0 +1 @@ +{"version":"2.8","children":[{"type":"frame","id":"qHhaj","x":68,"y":3385,"name":"Laputa App — Full Layout (Light)","theme":{"Mode":"Light"},"clip":true,"width":1440,"height":900,"fill":"$--background","layout":"vertical","children":[{"type":"frame","id":"yVQFF","name":"macOS Title Bar","width":"fill_container","height":38,"fill":"$--sidebar","stroke":{"align":"inside","thickness":{"bottom":1},"fill":"$--border"},"gap":12,"padding":[0,12],"alignItems":"center","children":[{"type":"frame","id":"0MCME","name":"trafficLights","gap":8,"alignItems":"center","children":[{"type":"ellipse","id":"c2AU6","name":"closeBtn","fill":"#FF5F57","width":12,"height":12},{"type":"ellipse","id":"h0zbh","name":"minimizeBtn","fill":"#FEBC2E","width":12,"height":12},{"type":"ellipse","id":"tcqbu","name":"maximizeBtn","fill":"#28C840","width":12,"height":12}]}]},{"type":"frame","id":"oHDfa","name":"Content","width":"fill_container","height":"fill_container","children":[{"type":"frame","id":"ZTOSJ","name":"Panel: Sidebar","clip":true,"width":250,"height":"fill_container","fill":"$--sidebar","stroke":{"align":"inside","thickness":0,"fill":"$--sidebar-border"},"layout":"vertical","children":[{"type":"frame","id":"4wMva","name":"Filters","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":"$--border"},"layout":"vertical","gap":1,"padding":[8,8,16,8],"children":[{"type":"frame","id":"Q78hg","name":"filterAll","width":"fill_container","fill":"#4a9eff18","cornerRadius":6,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"5ip58","name":"leftAll","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"PXpWi","name":"iconAll","width":18,"height":18,"iconFontName":"tray-fill","iconFontFamily":"phosphor","weight":700,"fill":"$--primary"},{"type":"text","id":"NWprl","name":"fAllTxt","fill":"$--primary","content":"Untagged","fontFamily":"Inter","fontSize":13,"fontWeight":"600"}]},{"type":"frame","id":"NZ9Dv","name":"countAll","height":20,"fill":"$--primary","cornerRadius":9999,"padding":[0,6],"justifyContent":"center","alignItems":"center","children":[{"type":"text","id":"mPlUV","name":"badgeAllTxt","fill":"$--primary-foreground","content":"24","fontFamily":"Inter","fontSize":10,"fontWeight":"600"}]}]},{"type":"frame","id":"YLWsY","name":"filterUntagged","width":"fill_container","cornerRadius":6,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"k7LIr","name":"leftUntagged","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"FMVlh","name":"untaggedIcon","width":18,"height":18,"iconFontName":"cardholder","iconFontFamily":"phosphor","weight":700,"fill":"$--foreground"},{"type":"text","id":"5XllD","name":"untaggedTxt","fill":"$--foreground","content":"All Notes","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"frame","id":"aSpGv","name":"countUntagged","height":20,"fill":"$--secondary","cornerRadius":9999,"padding":[0,6],"justifyContent":"center","alignItems":"center","children":[{"type":"text","id":"qZUFt","name":"untaggedBadgeTxt","fill":"$--muted-foreground","content":"6","fontFamily":"Inter","fontSize":10,"fontWeight":"600"}]}]},{"type":"frame","id":"Jahon","name":"filterTrash","width":"fill_container","cornerRadius":6,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"IOiBI","name":"leftTrash","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"X6F74","name":"trashIcon","width":18,"height":18,"iconFontName":"trash","iconFontFamily":"phosphor","weight":700,"fill":"$--foreground"},{"type":"text","id":"vRMH9","name":"trashTxt","fill":"$--foreground","content":"Archive","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"frame","id":"JMpkq","name":"countTrash","height":20,"fill":"$--secondary","cornerRadius":9999,"padding":[0,6],"justifyContent":"center","alignItems":"center","children":[{"type":"text","id":"0cKm4","name":"trashBadgeTxt","fill":"$--muted-foreground","content":"2","fontFamily":"Inter","fontSize":10,"fontWeight":"600"}]}]},{"type":"frame","id":"6RMbq","name":"filterChanges","width":"fill_container","cornerRadius":6,"gap":6,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"DpdBu","name":"leftChanges","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"VTusA","name":"iconChanges","width":18,"height":18,"iconFontName":"git-branch","iconFontFamily":"phosphor","weight":700,"fill":"$--foreground"},{"type":"text","id":"qvq5O","name":"fChangesTxt","fill":"$--foreground","content":"Changes","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"frame","id":"qAMES","name":"countChanges","height":20,"fill":"$--secondary","cornerRadius":9999,"padding":[0,6],"justifyContent":"center","alignItems":"center","children":[{"type":"text","id":"nkzVk","name":"badgeChangesTxt","fill":"$--muted-foreground","content":"3","fontFamily":"Inter","fontSize":10,"fontWeight":"600"}]}]}]},{"type":"frame","id":"SSEUP","name":"Sections","width":"fill_container","height":"fill_container","layout":"vertical","padding":[8,0],"children":[{"type":"frame","id":"nM2Cn","name":"projGroup","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":{"type":"color","color":"$--border","enabled":false}},"layout":"vertical","gap":2,"padding":[4,6,8,6],"children":[{"type":"frame","id":"ouIl9","name":"projHeader","width":"fill_container","cornerRadius":4,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"Rx1Cp","name":"leftProj","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"t5WJJ","name":"projIcon","width":18,"height":18,"iconFontName":"wrench","iconFontFamily":"phosphor","weight":700,"fill":"$--accent-red"},{"type":"text","id":"S3sGC","name":"projLabel","fill":"$--foreground","content":"Projects","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"icon_font","id":"FKwSS","name":"projChev","width":14,"height":14,"iconFontName":"chevron-down","iconFontFamily":"lucide","fill":"$--muted-foreground"}]},{"type":"frame","id":"IHzFh","name":"projItem1","width":"fill_container","fill":"$--accent-red-light","cornerRadius":6,"padding":[6,16,6,28],"alignItems":"center","children":[{"type":"text","id":"iiFcl","name":"proj1Txt","fill":"$--accent-red","content":"Laputa App","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"frame","id":"LdaU9","name":"projItem2","width":"fill_container","cornerRadius":6,"padding":[6,16,6,28],"alignItems":"center","children":[{"type":"text","id":"XRll4","name":"proj2Txt","fill":"$--muted-foreground","content":"Portfolio Rewrite","fontFamily":"Inter","fontSize":13,"fontWeight":"normal"}]},{"type":"frame","id":"Vmykd","name":"projItem3","width":"fill_container","cornerRadius":6,"padding":[6,16,6,28],"alignItems":"center","children":[{"type":"text","id":"0PqQQ","name":"proj3Txt","fill":"$--muted-foreground","content":"AI Habit Tracker","fontFamily":"Inter","fontSize":13,"fontWeight":"normal"}]}]},{"type":"frame","id":"WAQtn","name":"respGroup","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":{"type":"color","color":"$--border","enabled":false}},"layout":"vertical","gap":2,"padding":[4,6],"children":[{"type":"frame","id":"aSi3l","name":"respHeader","width":"fill_container","cornerRadius":4,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"lov6B","name":"leftResp","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"Em4ns","name":"respIcon","width":18,"height":18,"iconFontName":"medal","iconFontFamily":"phosphor","weight":700,"fill":"$--accent-purple"},{"type":"text","id":"WPRCo","name":"respLabel","fill":"$--foreground","content":"Responsibilities","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"icon_font","id":"6hDdQ","name":"respChev","width":14,"height":14,"iconFontName":"chevron-right","iconFontFamily":"lucide","fill":"$--muted-foreground"}]}]},{"type":"frame","id":"FmUu0","name":"procGroup","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":{"type":"color","color":"$--border","enabled":false}},"layout":"vertical","gap":2,"padding":[4,6],"children":[{"type":"frame","id":"Dat6o","name":"respHeader","width":"fill_container","cornerRadius":4,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"iJlgx","name":"leftResp","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"I2J1R","name":"respIcon","width":18,"height":18,"iconFontName":"arrows-clockwise","iconFontFamily":"phosphor","weight":700,"fill":"$--accent-purple"},{"type":"text","id":"AToF0","name":"Procedures","fill":"$--foreground","content":"Procedures","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"icon_font","id":"meEIL","name":"procChev","width":14,"height":14,"iconFontName":"chevron-right","iconFontFamily":"lucide","fill":"$--muted-foreground"}]}]},{"type":"frame","id":"T4NG2","name":"peopleGroup","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":{"type":"color","color":"$--border","enabled":false}},"layout":"vertical","gap":2,"padding":[4,6],"children":[{"type":"frame","id":"Q01iL","name":"peopleHeader","width":"fill_container","cornerRadius":4,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"eE6Ca","name":"leftPeople","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"jOmVa","name":"peopleIcon","width":18,"height":18,"iconFontName":"users","iconFontFamily":"phosphor","weight":700,"fill":"$--accent-yellow"},{"type":"text","id":"caelD","name":"peopleLbl","fill":"$--foreground","content":"People","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"icon_font","id":"TkuS1","name":"peopleChev","width":14,"height":14,"iconFontName":"chevron-right","iconFontFamily":"lucide","fill":"$--muted-foreground"}]}]},{"type":"frame","id":"BY1Qx","name":"eventsGroup","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":{"type":"color","color":"$--border","enabled":false}},"layout":"vertical","gap":2,"padding":[4,6],"children":[{"type":"frame","id":"v28d8","name":"eventsHeader","width":"fill_container","cornerRadius":4,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"TPyOc","name":"leftEvents","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"ELRMi","name":"eventsIcon","width":18,"height":18,"iconFontName":"calendar-blank","iconFontFamily":"phosphor","weight":700,"fill":"$--accent-yellow"},{"type":"text","id":"OlI6Q","name":"eventsLbl","fill":"$--foreground","content":"Events","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"icon_font","id":"TZwK8","name":"eventsChev","width":14,"height":14,"iconFontName":"chevron-right","iconFontFamily":"lucide","fill":"$--muted-foreground"}]}]},{"type":"frame","id":"trKNW","name":"topicsGroup","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":{"type":"color","color":"$--border","enabled":false}},"layout":"vertical","gap":2,"padding":[4,6],"children":[{"type":"frame","id":"qdbZ3","name":"eventsHeader","width":"fill_container","cornerRadius":4,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"JP83M","name":"leftEvents","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"Q57kF","name":"eventsIcon","width":18,"height":18,"iconFontName":"tag","iconFontFamily":"phosphor","weight":700,"fill":"$--accent-green"},{"type":"text","id":"DeVxP","name":"eventsLbl","fill":"$--foreground","content":"Topics","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"icon_font","id":"nzAcm","name":"topicsChev","width":14,"height":14,"iconFontName":"chevron-right","iconFontFamily":"lucide","fill":"$--muted-foreground"}]}]},{"type":"frame","id":"ZWXuk","name":"topicsGroup","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":{"type":"color","color":"$--border","enabled":false}},"layout":"vertical","gap":2,"padding":[4,6],"children":[{"type":"frame","id":"CQaLg","name":"eventsHeader","width":"fill_container","cornerRadius":4,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"2SMcN","name":"leftEvents","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"0N8UH","name":"eventsIcon","width":18,"height":18,"iconFontName":"leaf","iconFontFamily":"phosphor","weight":700,"fill":"$--accent-green"},{"type":"text","id":"6XB2H","name":"eventsLbl","fill":"$--foreground","content":"Notes","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"icon_font","id":"NmBSB","name":"topicsChev","width":14,"height":14,"iconFontName":"chevron-right","iconFontFamily":"lucide","fill":"$--muted-foreground"}]},{"type":"frame","id":"2cQBp","name":"eventsHeader","width":"fill_container","cornerRadius":4,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"0f10v","name":"leftEvents","gap":8,"padding":[8,0],"alignItems":"center","children":[{"type":"icon_font","id":"xBv1X","name":"eventsIcon","width":18,"height":18,"iconFontName":"plus","iconFontFamily":"phosphor","weight":700,"fill":"$--muted-foreground"},{"type":"text","id":"viWPL","name":"eventsLbl","fill":"$--muted-foreground","content":"Create new type","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]}]}]}]},{"type":"frame","id":"8lLHp","name":"Commit Area","width":"fill_container","stroke":{"align":"inside","thickness":{"top":1},"fill":"$--border"},"layout":"vertical","padding":12,"children":[{"type":"frame","id":"YYjuy","name":"commitBtn","width":"fill_container","fill":"$--primary","cornerRadius":6,"gap":6,"padding":[8,16],"justifyContent":"center","alignItems":"center","children":[{"type":"icon_font","id":"YF44G","name":"commitIcon","width":14,"height":14,"iconFontName":"git-commit-horizontal","iconFontFamily":"lucide","fill":"$--primary-foreground"},{"type":"text","id":"vpzJm","name":"commitTxt","fill":"$--primary-foreground","content":"Commit & Push","fontFamily":"Inter","fontSize":13,"fontWeight":"500"},{"type":"frame","id":"vhU5z","name":"commitBadge","height":18,"fill":"#ffffff40","cornerRadius":9,"padding":[0,5],"justifyContent":"center","alignItems":"center","children":[{"type":"text","id":"sdvYT","name":"commitBadgeTxt","fill":"$--white","content":"3","fontFamily":"Inter","fontSize":10,"fontWeight":"600"}]}]}]}]},{"type":"rectangle","id":"IIvWr","name":"Resize Handle","fill":"$--border","width":1,"height":"fill_container"},{"type":"frame","id":"zFIJv","name":"Panel: NoteList","clip":true,"width":300,"height":"fill_container","fill":"$--card","stroke":{"align":"inside","thickness":0,"fill":"$--border"},"layout":"vertical","children":[{"type":"frame","id":"uZJVN","name":"NoteList Header","width":"fill_container","height":45,"stroke":{"align":"inside","thickness":{"bottom":1},"fill":"$--border"},"padding":[14,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"text","id":"hmbdb","name":"nlTitle","fill":"$--foreground","content":"Laputa App","fontFamily":"Inter","fontSize":14,"fontWeight":"600"},{"type":"frame","id":"m6AeW","name":"nlActions","gap":12,"alignItems":"center","children":[{"type":"icon_font","id":"8gMXE","name":"searchIcon","width":16,"height":16,"iconFontName":"magnifying-glass","iconFontFamily":"phosphor","fill":"$--muted-foreground"},{"type":"icon_font","id":"YqvSN","name":"plusIcon","width":16,"height":16,"iconFontName":"plus","iconFontFamily":"phosphor","fill":"$--muted-foreground"}]}]},{"type":"frame","id":"0aJUm","name":"Note Items","clip":true,"width":"fill_container","height":"fill_container","layout":"vertical","children":[{"type":"frame","id":"y9y05","name":"Backlinks Group","width":"fill_container","layout":"vertical","children":[{"type":"frame","id":"tMsM4","name":"Note Item Selected","width":"fill_container","fill":"$--accent-red-light","stroke":{"align":"inside","thickness":{"bottom":1},"fill":"#E9E9E7"},"children":[{"type":"rectangle","id":"npYuc","name":"leftAccent","fill":"$--accent-red","width":3,"height":"fill_container"},{"type":"frame","id":"a33Wx","name":"noteSelContent","width":"fill_container","layout":"vertical","gap":4,"padding":[14,16],"children":[{"type":"frame","id":"AZkyx","name":"noteSelRow","width":"fill_container","gap":8,"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"j7GDJ","name":"titleGroup","width":"fill_container","gap":6,"justifyContent":"space_between","alignItems":"center","children":[{"type":"text","id":"j7o2Q","name":"noteSelTitle","fill":"$--foreground","content":"Laputa App","fontFamily":"Inter","fontSize":13,"fontWeight":"600"},{"type":"icon_font","id":"BnkTG","name":"ico","width":14,"height":14,"iconFontName":"wrench","iconFontFamily":"lucide","fill":"$--accent-red"}]}]},{"type":"text","id":"Ac5Ds","name":"noteSelSnip","fill":"$--foreground","textGrowth":"fixed-width","width":"fill_container","content":"Personal knowledge and life management desktop app...","lineHeight":1.5,"fontFamily":"Inter","fontSize":12,"fontWeight":"normal"},{"type":"text","id":"9ASsT","name":"noteSelTime","fill":"$--accent-red","content":"2m ago","fontFamily":"Inter","fontSize":11,"fontWeight":"normal"}]}]}]},{"type":"frame","id":"7G8pN","name":"Related Notes Group","width":"fill_container","layout":"vertical","children":[{"type":"frame","id":"fDxtF","name":"Related Notes Header","width":"fill_container","height":32,"fill":"$--muted","padding":[0,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"UBRdO","name":"rnLeft","gap":6,"alignItems":"center","children":[{"type":"text","id":"8Z4Wq","name":"rnLabel","fill":"$--muted-foreground","content":"RELATED NOTES","fontFamily":"IBM Plex Mono","fontSize":11},{"type":"text","id":"vpnZr","name":"rnCount","fill":"$--muted-foreground","content":"2","fontFamily":"IBM Plex Mono","fontSize":11,"fontWeight":"normal"}]},{"type":"frame","id":"X9LIR","name":"rnRight","gap":10,"alignItems":"center","children":[{"type":"icon_font","id":"fzVWu","name":"rnFilter","width":12,"height":12,"iconFontName":"funnel","iconFontFamily":"phosphor","fill":"$--muted-foreground"},{"type":"icon_font","id":"wuqsO","name":"rnPlus","width":12,"height":12,"iconFontName":"plus","iconFontFamily":"lucide","fill":"$--muted-foreground"},{"type":"icon_font","id":"SbjLq","name":"rnChev","width":12,"height":12,"iconFontName":"chevron-down","iconFontFamily":"lucide","fill":"$--muted-foreground"}]}]},{"type":"frame","id":"AsAKG","name":"Note Item","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":"$--border"},"layout":"vertical","gap":4,"padding":[14,16],"children":[{"type":"frame","id":"QX5A1","name":"note2Row","width":"fill_container","gap":8,"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"rYdta","name":"leafGroup","width":"fill_container","gap":6,"justifyContent":"space_between","alignItems":"center","children":[{"type":"text","id":"PC9XN","name":"note2Title","fill":"$--foreground","content":"Portfolio Rewrite","fontFamily":"Inter","fontSize":13,"fontWeight":"500"},{"type":"icon_font","id":"oI64Y","name":"leafIco","width":14,"height":14,"iconFontName":"leaf","iconFontFamily":"phosphor","fill":"$--accent-green"}]}]},{"type":"text","id":"S9JPj","name":"note2Snip","fill":"$--muted-foreground","textGrowth":"fixed-width","width":"fill_container","content":"Redesigning portfolio site with modern stack and updated visual language...","lineHeight":1.5,"fontFamily":"Inter","fontSize":12,"fontWeight":"normal"},{"type":"text","id":"lU75x","name":"note2Time","fill":"$--muted-foreground","content":"1h ago","fontFamily":"Inter","fontSize":11,"fontWeight":"normal"}]},{"type":"frame","id":"u6E6Z","name":"Note Item","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":"$--border"},"layout":"vertical","gap":4,"padding":[14,16],"children":[{"type":"frame","id":"ZjCz3","name":"note2Row","width":"fill_container","gap":8,"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"mxCzu","name":"leafGroup","width":"fill_container","gap":6,"justifyContent":"space_between","alignItems":"center","children":[{"type":"text","id":"INenY","name":"note2Title","fill":"$--foreground","content":"Sample note 2","fontFamily":"Inter","fontSize":13,"fontWeight":"500"},{"type":"icon_font","id":"gz6qS","name":"leafIco","width":14,"height":14,"iconFontName":"leaf","iconFontFamily":"phosphor","fill":"$--accent-green"}]}]},{"type":"text","id":"s141z","name":"note2Snip","fill":"$--muted-foreground","textGrowth":"fixed-width","width":"fill_container","content":"Lorem ipsum dolor sit amet consequetur with modern stack and updated language...","lineHeight":1.5,"fontFamily":"Inter","fontSize":12,"fontWeight":"normal"},{"type":"text","id":"SvGnt","name":"note2Time","fill":"$--muted-foreground","content":"1h ago","fontFamily":"Inter","fontSize":11,"fontWeight":"normal"}]}]},{"type":"frame","id":"1GwHB","name":"Events Group","width":"fill_container","layout":"vertical","children":[{"type":"frame","id":"fp4xI","name":"Events Header","width":"fill_container","height":32,"fill":"$--muted","padding":[0,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"MNNuU","name":"evLeft","gap":6,"alignItems":"center","children":[{"type":"text","id":"BNxZp","name":"evLabel","fill":"$--muted-foreground","content":"EVENTS","fontFamily":"IBM Plex Mono","fontSize":11},{"type":"text","id":"qcEvw","name":"evCount","fill":"$--muted-foreground","content":"2","fontFamily":"IBM Plex Sans","fontSize":11,"fontWeight":"normal"}]},{"type":"frame","id":"WCyfc","name":"evRight","gap":10,"alignItems":"center","children":[{"type":"icon_font","id":"SpCoO","name":"evFilter","width":12,"height":12,"iconFontName":"funnel","iconFontFamily":"phosphor","fill":"$--muted-foreground"},{"type":"icon_font","id":"G1DCl","name":"evPlus","width":12,"height":12,"iconFontName":"plus","iconFontFamily":"lucide","fill":"$--muted-foreground"},{"type":"icon_font","id":"sAalN","name":"evChev","width":12,"height":12,"iconFontName":"chevron-down","iconFontFamily":"lucide","fill":"$--muted-foreground"}]}]},{"type":"frame","id":"k7CjA","name":"Note Item 2","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":"$--border"},"layout":"vertical","gap":4,"padding":[14,16],"children":[{"type":"frame","id":"og5Gz","name":"note3Row","width":"fill_container","gap":8,"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"ttBdk","name":"calGroup","width":"fill_container","gap":6,"justifyContent":"space_between","alignItems":"center","children":[{"type":"text","id":"KI8Bf","name":"note3Title","fill":"$--foreground","content":"Meeting with Grant","fontFamily":"Inter","fontSize":13,"fontWeight":"500"},{"type":"icon_font","id":"LdRjU","name":"calIco","width":14,"height":14,"iconFontName":"calendar","iconFontFamily":"lucide","fill":"$--accent-yellow"}]}]},{"type":"text","id":"FfPXa","name":"note3Snip","fill":"$--muted-foreground","textGrowth":"fixed-width","width":"fill_container","content":"Discussed Q1 goals and hiring priorities with the engineering team leads...","lineHeight":1.5,"fontFamily":"Inter","fontSize":12,"fontWeight":"normal"},{"type":"text","id":"BHh4Z","name":"note3Time","fill":"$--muted-foreground","content":"Yesterday","fontFamily":"Inter","fontSize":11,"fontWeight":"normal"}]},{"type":"frame","id":"AQ51u","name":"Note Item 2","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":"$--border"},"layout":"vertical","gap":4,"padding":[14,16],"children":[{"type":"frame","id":"SHgK3","name":"note3Row","width":"fill_container","gap":8,"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"3rIet","name":"calGroup","width":"fill_container","gap":6,"justifyContent":"space_between","alignItems":"center","children":[{"type":"text","id":"dCwzu","name":"note3Title","fill":"$--foreground","content":"Meeting with Matteo","fontFamily":"Inter","fontSize":13,"fontWeight":"500"},{"type":"icon_font","id":"l8O2I","name":"calIco","width":14,"height":14,"iconFontName":"calendar","iconFontFamily":"lucide","fill":"$--accent-yellow"}]}]},{"type":"text","id":"1L4oo","name":"note3Snip","fill":"$--muted-foreground","textGrowth":"fixed-width","width":"fill_container","content":"Discussed Q1 goals and hiring priorities with the engineering team leads...","lineHeight":1.5,"fontFamily":"Inter","fontSize":12,"fontWeight":"normal"},{"type":"text","id":"3oBam","name":"note3Time","fill":"$--muted-foreground","content":"Yesterday","fontFamily":"Inter","fontSize":11,"fontWeight":"normal"}]}]}]}]},{"type":"rectangle","id":"MeqjO","name":"Resize Handle 2","fill":"$--border","width":1,"height":"fill_container"},{"type":"frame","id":"zAbPt","name":"Panel: Editor","clip":true,"width":"fill_container","height":"fill_container","fill":"$--background","layout":"vertical","children":[{"type":"frame","id":"NdYcO","name":"Tab Bar","width":"fill_container","height":45,"fill":"$--sidebar","stroke":{"align":"inside","thickness":{"bottom":1},"fill":"$--sidebar-border"},"alignItems":"center","children":[{"type":"frame","id":"nVUGr","name":"Tab Active","height":"fill_container","fill":"$--background","stroke":{"align":"inside","thickness":{"right":1},"fill":"$--border"},"gap":6,"padding":[0,14],"alignItems":"center","children":[{"type":"text","id":"kBpGX","name":"tab1Txt","fill":"$--foreground","content":"Laputa App","fontFamily":"Inter","fontSize":12,"fontWeight":"500"},{"type":"icon_font","id":"Bb2AE","name":"tab1Close","width":14,"height":14,"iconFontName":"x","iconFontFamily":"lucide","fill":"$--muted-foreground"}]},{"type":"frame","id":"GYeyL","name":"Tab Inactive","height":"fill_container","stroke":{"align":"inside","thickness":{"right":1,"bottom":1},"fill":"$--sidebar-border"},"gap":6,"padding":[0,14],"alignItems":"center","children":[{"type":"text","id":"kZ1bn","name":"tab2Txt","fill":"$--muted-foreground","content":"Portfolio Rewrite","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"},{"type":"icon_font","id":"RwyYI","name":"tab2Close","opacity":0,"width":14,"height":14,"iconFontName":"x","iconFontFamily":"lucide","fill":"$--muted-foreground"}]},{"type":"frame","id":"sbpmq","name":"tabSpacer","width":"fill_container","height":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":"$--border"}},{"type":"frame","id":"WF97k","name":"tabControls","height":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1,"left":1},"fill":"$--border"},"gap":12,"padding":[0,12],"justifyContent":"space_around","alignItems":"center","children":[{"type":"icon_font","id":"rfSoS","name":"iconPlus","width":16,"height":16,"iconFontName":"plus","iconFontFamily":"phosphor","fill":"$--muted-foreground"},{"type":"icon_font","id":"t0u6z","name":"iconSplit","width":16,"height":16,"iconFontName":"columns","iconFontFamily":"phosphor","fill":"$--muted-foreground"},{"type":"icon_font","id":"kbe1P","name":"iconExpand","width":16,"height":16,"iconFontName":"arrows-out-simple","iconFontFamily":"phosphor","fill":"$--muted-foreground"}]}]},{"type":"frame","id":"rTdKS","name":"Editor Body","width":"fill_container","height":"fill_container","children":[{"type":"frame","id":"NfyTF","name":"Editor Left","width":"fill_container","height":"fill_container","layout":"vertical","children":[{"type":"frame","id":"hvoFh","name":"Info Bar","width":"fill_container","height":45,"fill":"$--background","stroke":{"align":"inside","thickness":{"bottom":1},"fill":"$--border"},"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"bTP0I","name":"infoLeft","gap":6,"alignItems":"center","children":[{"type":"text","id":"Msj7v","name":"breadcrumbType","fill":"$--muted-foreground","content":"Project","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"},{"type":"text","id":"wqdMG","name":"breadcrumbSep","fill":"$--muted-foreground","content":"›","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"},{"type":"text","id":"FzENd","name":"breadcrumbName","fill":"$--foreground","content":"Laputa App","fontFamily":"Inter","fontSize":12,"fontWeight":"500"},{"type":"text","id":"pvTmc","name":"dotSep","fill":"$--muted-foreground","content":"·","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"},{"type":"text","id":"9ga1R","name":"modifiedTxt","fill":"$--accent-yellow","content":"M","fontFamily":"Inter","fontSize":12,"fontWeight":"600"}]},{"type":"frame","id":"3bzDp","name":"infoRight","gap":12,"alignItems":"center","children":[{"type":"icon_font","id":"9Ctb0","name":"iconSearch","width":16,"height":16,"iconFontName":"magnifying-glass","iconFontFamily":"phosphor","fill":"$--muted-foreground"},{"type":"icon_font","id":"csHzz","name":"iconSearch","width":16,"height":16,"iconFontName":"git-branch","iconFontFamily":"phosphor","fill":"$--muted-foreground"},{"type":"icon_font","id":"2s6Of","name":"iconSearch","width":16,"height":16,"iconFontName":"cursor-text","iconFontFamily":"phosphor","fill":"$--muted-foreground"},{"type":"icon_font","id":"JVSlj","name":"iconAI","width":16,"height":16,"iconFontName":"sparkle","iconFontFamily":"phosphor","fill":"$--muted-foreground"},{"type":"icon_font","id":"k3AiV","name":"iconMore","width":16,"height":16,"iconFontName":"dots-three","iconFontFamily":"phosphor","fill":"$--muted-foreground"}]}]},{"type":"frame","id":"vvETz","name":"Editor Content","width":"fill_container","height":"fill_container","layout":"vertical","gap":16,"padding":[32,64],"children":[{"type":"text","id":"b6up3","name":"editorP1","fill":"$--foreground","textGrowth":"fixed-width","width":"fill_container","content":"Personal knowledge and life management desktop app, built with Tauri v2 + React + TypeScript + CodeMirror 6. It reads a vault of markdown files with YAML frontmatter and presents them in a four-panel UI inspired by Bear Notes.","lineHeight":1.6,"fontFamily":"Inter","fontSize":16,"fontWeight":"normal"},{"type":"text","id":"a2S43","name":"editorH2","fill":"$--foreground","content":"Architecture","lineHeight":1.3,"fontFamily":"Inter","fontSize":24,"fontWeight":"600"},{"type":"text","id":"wgvQa","name":"editorP2","fill":"$--foreground","textGrowth":"fixed-width","width":"fill_container","content":"The app uses a four-panel layout: Sidebar for navigation, NoteList for browsing, Editor for content, and Inspector for metadata. All data lives in markdown files with YAML frontmatter, git-versioned.","lineHeight":1.6,"fontFamily":"Inter","fontSize":16,"fontWeight":"normal"}]}]},{"type":"frame","id":"GGP97","name":"Inspector","clip":true,"width":260,"height":"fill_container","fill":"$--background","stroke":{"align":"inside","thickness":{"left":1},"fill":"$--border"},"layout":"vertical","children":[{"type":"frame","id":"FbHy7","name":"Inspector Header","width":"fill_container","height":45,"stroke":{"align":"inside","thickness":{"bottom":1},"fill":"$--border"},"gap":8,"padding":[0,12],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"sA7Dx","name":"leftGroup","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"0ccF1","name":"propIcon","width":16,"height":16,"iconFontName":"sliders-horizontal","iconFontFamily":"phosphor","fill":"$--muted-foreground"},{"type":"text","id":"T2vTZ","name":"inspTitle","fill":"$--muted-foreground","content":"Properties","fontFamily":"Inter","fontSize":13,"fontWeight":"600"}]},{"type":"icon_font","id":"NQOhZ","name":"sidebarIcon","width":16,"height":16,"iconFontName":"x","iconFontFamily":"phosphor","fill":"$--muted-foreground"}]},{"type":"frame","id":"LYFki","name":"Inspector Body","clip":true,"width":"fill_container","height":"fill_container","layout":"vertical","gap":16,"padding":12,"children":[{"type":"frame","id":"8g61y","name":"Properties Section","width":"fill_container","layout":"vertical","gap":8,"children":[{"type":"frame","id":"VhH4P","name":"addPropBtn","width":"fill_container","cornerRadius":6,"stroke":{"align":"inside","thickness":1,"fill":"$--border"},"padding":[6,12],"justifyContent":"center","alignItems":"center","children":[{"type":"text","id":"Q9z8F","name":"addPropTxt","fill":"$--muted-foreground","content":"+ Add property","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"}]},{"type":"frame","id":"6PwTH","name":"propType","width":"fill_container","justifyContent":"space_between","alignItems":"center","children":[{"type":"text","id":"Vt2BC","name":"propTypeLbl","fill":"$--muted-foreground","content":"TYPE","fontFamily":"IBM Plex Mono","fontSize":10,"fontWeight":"normal"},{"type":"text","id":"uvBiY","name":"propTypeVal","fill":"$--foreground","content":"Project","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"}]},{"type":"frame","id":"FDbay","name":"propStatus","width":"fill_container","justifyContent":"space_between","alignItems":"center","children":[{"type":"text","id":"e426F","name":"propStatusLbl","fill":"$--muted-foreground","content":"STATUS","fontFamily":"IBM Plex Mono","fontSize":10,"fontWeight":"normal"},{"type":"frame","id":"o2rZM","name":"propStatusBadge","fill":"$--accent-green-light","cornerRadius":16,"stroke":{"align":"inside","thickness":1,"fill":"transparent"},"gap":8,"padding":[1,6],"justifyContent":"center","alignItems":"center","children":[{"type":"text","id":"QM7L3","name":"Badge Text","fill":"$--accent-green","content":"ACTIVE","lineHeight":1.33,"textAlign":"center","textAlignVertical":"middle","fontFamily":"IBM Plex Mono","fontSize":10,"fontWeight":"600","letterSpacing":1.2}]}]}]},{"type":"frame","id":"NmRLv","name":"Relationships Section","width":"fill_container","layout":"vertical","gap":16,"children":[{"type":"frame","id":"WFVAr","name":"relGroup1","width":"fill_container","layout":"vertical","gap":4,"children":[{"type":"text","id":"0N729","name":"relGrp1Title","fill":"$--muted-foreground","content":"BELONGS TO","fontFamily":"IBM Plex Mono","fontSize":10},{"type":"frame","id":"zLl8F","name":"relLaputaBtn","width":"fill_container","fill":"$--accent-green-light","cornerRadius":6,"padding":[6,10],"justifyContent":"space_between","alignItems":"center","children":[{"type":"text","id":"kw9vC","name":"laputaTxt","fill":"$--accent-green","content":"Laputa","fontFamily":"Inter","fontSize":12,"fontWeight":"500"},{"type":"icon_font","id":"RFvoz","name":"topicIcon","opacity":0.5,"width":14,"height":14,"iconFontName":"tag","iconFontFamily":"phosphor","fill":"$--accent-green"}]},{"type":"frame","id":"ybi8Q","name":"relLaputaBtn","width":"fill_container","fill":"$--accent-green-light","cornerRadius":6,"padding":[6,10],"justifyContent":"space_between","alignItems":"center","children":[{"type":"text","id":"VNcmt","name":"laputaTxt","fill":"$--accent-green","content":"Building","fontFamily":"Inter","fontSize":12,"fontWeight":"500"},{"type":"icon_font","id":"UVPwc","name":"topicIcon","opacity":0.5,"width":14,"height":14,"iconFontName":"tag","iconFontFamily":"phosphor","fill":"$--accent-green"}]},{"type":"frame","id":"L6knW","name":"linkExisting","width":"fill_container","cornerRadius":6,"stroke":{"align":"inside","thickness":1,"fill":"$--border"},"padding":[6,10],"justifyContent":"space_between","alignItems":"center","children":[{"type":"text","id":"jwU3Z","name":"laputaTxt","fill":"$--muted-foreground","content":"+ Link existing","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"}]}]},{"type":"frame","id":"laPFL","name":"relGroup2","width":"fill_container","layout":"vertical","gap":4,"children":[{"type":"text","id":"LOXUL","name":"relGrp2Title","fill":"$--muted-foreground","content":"RELATED TO","fontFamily":"IBM Plex Mono","fontSize":10},{"type":"frame","id":"qLTYD","name":"relMigrationBtn","width":"fill_container","fill":"$--accent-red-light","cornerRadius":6,"padding":[6,10],"justifyContent":"space_between","alignItems":"center","children":[{"type":"text","id":"GBk2u","name":"migrationTxt","fill":"$--accent-red","content":"Shadcn Migration","fontFamily":"Inter","fontSize":12,"fontWeight":"500"},{"type":"icon_font","id":"Sy14T","name":"expIcon","opacity":0.5,"width":14,"height":14,"iconFontName":"flask","iconFontFamily":"phosphor","fill":"$--accent-red"}]},{"type":"frame","id":"u8ijV","name":"linkExisting","width":"fill_container","cornerRadius":6,"stroke":{"align":"inside","thickness":1,"fill":"$--border"},"padding":[6,10],"justifyContent":"space_between","alignItems":"center","children":[{"type":"text","id":"PUXx5","name":"laputaTxt","fill":"$--muted-foreground","content":"+ Link existing","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"}]}]}]},{"type":"frame","id":"6PUnO","name":"Backlinks Section","width":"fill_container","layout":"vertical","gap":8,"children":[{"type":"frame","id":"PllIu","name":"blTitle","gap":4,"alignItems":"center","children":[{"type":"text","id":"ZbgbI","name":"blTitleTxt","rotation":-0.5285936385085725,"fill":"$--muted-foreground","content":"BACKLINKS","fontFamily":"IBM Plex Mono","fontSize":10}]},{"type":"text","id":"eRoDO","name":"blItem1","fill":"$--primary","content":"Portfolio Rewrite","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"},{"type":"text","id":"u1olR","name":"blItem2","fill":"$--primary","content":"Meeting with Grant","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"},{"type":"text","id":"oUd9s","name":"blItem3","fill":"$--primary","content":"Q1 Planning","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"}]},{"type":"frame","id":"yf0wj","name":"History Section","width":"fill_container","layout":"vertical","gap":8,"children":[{"type":"text","id":"dG7rj","name":"histTitle","fill":"$--muted-foreground","content":"HISTORY","fontFamily":"IBM Plex Mono","fontSize":10},{"type":"frame","id":"z2Mdy","name":"histItem1","width":"fill_container","stroke":{"align":"inside","thickness":{"left":2},"fill":"$--border"},"layout":"vertical","gap":2,"padding":[0,0,0,10],"children":[{"type":"text","id":"AsiWz","name":"histItem1Hash","fill":"$--accent-blue","content":"a089f44 · feat: migrate to shadcn/ui","fontFamily":"Inter","fontSize":11,"fontWeight":"normal"},{"type":"text","id":"BdVhi","name":"histItem1Date","fill":"$--muted-foreground","content":"Feb 16, 2026","fontFamily":"Inter","fontSize":10,"fontWeight":"normal"}]},{"type":"frame","id":"piJNC","name":"histItem2","width":"fill_container","stroke":{"align":"inside","thickness":{"left":2},"fill":"$--border"},"layout":"vertical","gap":2,"padding":[0,0,0,10],"children":[{"type":"text","id":"0PWoX","name":"histItem2Hash","fill":"$--accent-blue","content":"5a4b4ac · feat: emoji favicon","fontFamily":"Inter","fontSize":11,"fontWeight":"normal"},{"type":"text","id":"xySNW","name":"histItem2Date","fill":"$--muted-foreground","content":"Feb 15, 2026","fontFamily":"Inter","fontSize":10,"fontWeight":"normal"}]}]}]}]}]}]}]},{"type":"frame","id":"x1AHT","name":"lightStatusBar","width":"fill_container","height":30,"fill":"$--sidebar","stroke":{"align":"inside","thickness":{"top":1},"fill":"$--border"},"padding":[0,8],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"e2UzJ","name":"Status Left","height":"fill_container","gap":12,"alignItems":"center","children":[{"type":"icon_font","id":"mlD58","name":"versionIcon","width":14,"height":14,"iconFontName":"box","iconFontFamily":"lucide","fill":"$--muted-foreground"},{"type":"text","id":"hRBRa","name":"versionText","fill":"$--muted-foreground","content":"v0.4.2","fontFamily":"Inter","fontSize":11,"fontWeight":"500"},{"type":"text","id":"bFwrw","name":"sep1","fill":"$--border","content":"|","fontFamily":"Inter","fontSize":11,"fontWeight":"normal"},{"type":"icon_font","id":"ey3Gr","name":"branchIcon","width":14,"height":14,"iconFontName":"git-branch","iconFontFamily":"lucide","fill":"$--muted-foreground"},{"type":"text","id":"Kz0sS","name":"branchText","fill":"$--muted-foreground","content":"main","fontFamily":"Inter","fontSize":11,"fontWeight":"normal"},{"type":"text","id":"6IY1E","name":"sep2","fill":"$--border","content":"|","fontFamily":"Inter","fontSize":11,"fontWeight":"normal"},{"type":"icon_font","id":"IjEG1","name":"syncIcon","width":13,"height":13,"iconFontName":"refresh-cw","iconFontFamily":"lucide","fill":"$--accent-green"},{"type":"text","id":"srxkr","name":"syncText","fill":"$--muted-foreground","content":"Synced 2m ago","fontFamily":"Inter","fontSize":11,"fontWeight":"normal"}]},{"type":"frame","id":"4jgQF","name":"Status Right","height":"fill_container","gap":12,"alignItems":"center","children":[{"type":"icon_font","id":"3RPmA","name":"aiIcon","width":13,"height":13,"iconFontName":"sparkles","iconFontFamily":"lucide","fill":"$--accent-purple"},{"type":"text","id":"t0NOA","name":"aiText","fill":"$--muted-foreground","content":"Claude Sonnet 4","fontFamily":"Inter","fontSize":11,"fontWeight":"normal"},{"type":"text","id":"16V7i","name":"sep3","fill":"$--border","content":"|","fontFamily":"Inter","fontSize":11,"fontWeight":"normal"},{"type":"icon_font","id":"PXVrd","name":"notesCount","width":13,"height":13,"iconFontName":"file-text","iconFontFamily":"lucide","fill":"$--muted-foreground"},{"type":"text","id":"2FxCi","name":"notesText","fill":"$--muted-foreground","content":"1,247 notes","fontFamily":"Inter","fontSize":11,"fontWeight":"normal"},{"type":"text","id":"pB6ds","name":"sep4","fill":"$--border","content":"|","fontFamily":"Inter","fontSize":11,"fontWeight":"normal"},{"type":"icon_font","id":"fRHKs","name":"bellIcon","width":13,"height":13,"iconFontName":"bell","iconFontFamily":"lucide","fill":"$--muted-foreground"},{"type":"icon_font","id":"2sEBS","name":"settingsIcon","width":13,"height":13,"iconFontName":"settings","iconFontFamily":"lucide","fill":"$--muted-foreground"}]}]}]},{"type":"frame","id":"mOf4J","x":0,"y":4457,"name":"Color Palette — shadcn/ui Theme (Light)","theme":{"Mode":"Light"},"width":1440,"fill":"$--background","layout":"vertical","gap":32,"padding":40,"children":[{"type":"text","id":"rmJdn","name":"cTitle","fill":"$--foreground","content":"Color Palette — shadcn/ui Theme Variables (Light)","fontFamily":"Inter","fontSize":28,"fontWeight":"700","letterSpacing":-0.5},{"type":"text","id":"V79Zu","name":"cSub","fill":"$--muted-foreground","textGrowth":"fixed-width","width":"fill_container","content":"All colors from src/index.css. Variables support light/dark mode via .dark class.","lineHeight":1.5,"fontFamily":"Inter","fontSize":14,"fontWeight":"normal"},{"type":"text","id":"Xbdzq","name":"primLbl","fill":"$--foreground","content":"Primary Colors","fontFamily":"Inter","fontSize":18,"fontWeight":"600"},{"type":"frame","id":"NyoC7","name":"primRow","width":"fill_container","gap":16,"children":[{"type":"frame","id":"Inb1x","name":"sw1","width":"fill_container","layout":"vertical","gap":8,"children":[{"type":"rectangle","cornerRadius":8,"id":"HRsVC","name":"sw1b","fill":"$--background","width":"fill_container","height":60,"stroke":{"align":"inside","thickness":1,"fill":"$--border"}},{"type":"text","id":"jV89s","name":"sw1n","fill":"$--foreground","content":"--background","fontFamily":"Inter","fontSize":12,"fontWeight":"500"},{"type":"text","id":"qOUUY","name":"sw1v","fill":"$--muted-foreground","content":"L: #FFFFFF / D: #0f0f1a","fontFamily":"Inter","fontSize":11,"fontWeight":"normal"}]},{"type":"frame","id":"QytAQ","name":"sw2","width":"fill_container","layout":"vertical","gap":8,"children":[{"type":"rectangle","cornerRadius":8,"id":"TMuHH","name":"sw2b","fill":"$--foreground","width":"fill_container","height":60},{"type":"text","id":"k9qK4","name":"sw2n","fill":"$--foreground","content":"--foreground","fontFamily":"Inter","fontSize":12,"fontWeight":"500"},{"type":"text","id":"BfEn7","name":"sw2v","fill":"$--muted-foreground","content":"L: #37352F / D: #e0e0e0","fontFamily":"Inter","fontSize":11,"fontWeight":"normal"}]},{"type":"frame","id":"gJZtB","name":"sw3","width":"fill_container","layout":"vertical","gap":8,"children":[{"type":"rectangle","cornerRadius":8,"id":"RRsQg","name":"sw3b","fill":"$--primary","width":"fill_container","height":60},{"type":"text","id":"CtJe4","name":"sw3n","fill":"$--foreground","content":"--primary","fontFamily":"Inter","fontSize":12,"fontWeight":"500"},{"type":"text","id":"1iFr6","name":"sw3v","fill":"$--muted-foreground","content":"#155DFF","fontFamily":"Inter","fontSize":11,"fontWeight":"normal"}]},{"type":"frame","id":"mbvua","name":"sw4","width":"fill_container","layout":"vertical","gap":8,"children":[{"type":"rectangle","cornerRadius":8,"id":"fajNZ","name":"sw4b","fill":"$--primary-foreground","width":"fill_container","height":60,"stroke":{"align":"inside","thickness":1,"fill":"$--border"}},{"type":"text","id":"wVJ7z","name":"sw4n","fill":"$--foreground","content":"--primary-foreground","fontFamily":"Inter","fontSize":12,"fontWeight":"500"},{"type":"text","id":"Oum5Q","name":"sw4v","fill":"$--muted-foreground","content":"L: #FFFFFF / D: #ffffff","fontFamily":"Inter","fontSize":11,"fontWeight":"normal"}]}]},{"type":"text","id":"UvI4d","name":"accLbl","fill":"$--foreground","content":"Accent & Semantic Colors","fontFamily":"Inter","fontSize":18,"fontWeight":"600"},{"type":"frame","id":"jOmo7","name":"accRow","width":"fill_container","gap":16,"children":[{"type":"frame","id":"uFXJ3","name":"a1","width":"fill_container","layout":"vertical","gap":8,"children":[{"type":"rectangle","cornerRadius":8,"id":"NRr0w","name":"a1b","fill":"$--accent-blue","width":"fill_container","height":60},{"type":"text","id":"ECVqk","name":"a1n","fill":"$--foreground","content":"--accent-blue","fontFamily":"Inter","fontSize":12,"fontWeight":"500"}]},{"type":"frame","id":"csKEt","name":"a2","width":"fill_container","layout":"vertical","gap":8,"children":[{"type":"rectangle","cornerRadius":8,"id":"5IiT2","name":"a2b","fill":"$--accent-green","width":"fill_container","height":60},{"type":"text","id":"aCPba","name":"a2n","fill":"$--foreground","content":"--accent-green","fontFamily":"Inter","fontSize":12,"fontWeight":"500"}]},{"type":"frame","id":"XbY7C","name":"a3","width":"fill_container","layout":"vertical","gap":8,"children":[{"type":"rectangle","cornerRadius":8,"id":"I9qCz","name":"a3b","fill":"$--accent-yellow","width":"fill_container","height":60},{"type":"text","id":"DfZVh","name":"a3n","fill":"$--foreground","content":"--accent-yellow","fontFamily":"Inter","fontSize":12,"fontWeight":"500"}]},{"type":"frame","id":"nROw3","name":"a4","width":"fill_container","layout":"vertical","gap":8,"children":[{"type":"rectangle","cornerRadius":8,"id":"IcIoP","name":"a4b","fill":"$--accent-red","width":"fill_container","height":60},{"type":"text","id":"eGgz6","name":"a4n","fill":"$--foreground","content":"--destructive","fontFamily":"Inter","fontSize":12,"fontWeight":"500"}]},{"type":"frame","id":"J95fv","name":"a5","width":"fill_container","layout":"vertical","gap":8,"children":[{"type":"rectangle","cornerRadius":8,"id":"o03fQ","name":"a5b","fill":"$--accent-purple","width":"fill_container","height":60},{"type":"text","id":"H9VWy","name":"a5n","fill":"$--foreground","content":"--accent-purple","fontFamily":"Inter","fontSize":12,"fontWeight":"500"}]}]},{"type":"text","id":"GcYle","name":"lightLightLbl","fill":"$--foreground","content":"Accent Light Backgrounds","fontFamily":"Inter","fontSize":18,"fontWeight":"600"},{"type":"frame","id":"Ju2xp","name":"accLightRow","width":"fill_container","gap":16,"children":[{"type":"frame","id":"5dnn5","name":"al1","width":"fill_container","layout":"vertical","gap":8,"children":[{"type":"rectangle","cornerRadius":8,"id":"7kcqW","name":"ll1b","fill":"$--accent-blue-light","width":"fill_container","height":60,"stroke":{"align":"inside","thickness":1,"fill":"$--border"}},{"type":"text","id":"dBCbF","name":"ll1n","fill":"$--foreground","content":"--accent-blue-light","fontFamily":"Inter","fontSize":12,"fontWeight":"500"}]},{"type":"frame","id":"W0t0j","name":"al2","width":"fill_container","layout":"vertical","gap":8,"children":[{"type":"rectangle","cornerRadius":8,"id":"1vepp","name":"ll2b","fill":"$--accent-green-light","width":"fill_container","height":60,"stroke":{"align":"inside","thickness":1,"fill":"$--border"}},{"type":"text","id":"6kUyf","name":"ll2n","fill":"$--foreground","content":"--accent-green-light","fontFamily":"Inter","fontSize":12,"fontWeight":"500"}]},{"type":"frame","id":"zyV1j","name":"al3","width":"fill_container","layout":"vertical","gap":8,"children":[{"type":"rectangle","cornerRadius":8,"id":"yUDBN","name":"ll3b","fill":"$--accent-yellow-light","width":"fill_container","height":60,"stroke":{"align":"inside","thickness":1,"fill":"$--border"}},{"type":"text","id":"dmfZ4","name":"ll3n","fill":"$--foreground","content":"--accent-yellow-light","fontFamily":"Inter","fontSize":12,"fontWeight":"500"}]},{"type":"frame","id":"yGmmo","name":"al4","width":"fill_container","layout":"vertical","gap":8,"children":[{"type":"rectangle","cornerRadius":8,"id":"eLu8o","name":"ll4b","fill":"$--accent-red-light","width":"fill_container","height":60,"stroke":{"align":"inside","thickness":1,"fill":"$--border"}},{"type":"text","id":"PVLwR","name":"ll4n","fill":"$--foreground","content":"--accent-red-light","fontFamily":"Inter","fontSize":12,"fontWeight":"500"}]},{"type":"frame","id":"0BO2b","name":"al5","width":"fill_container","layout":"vertical","gap":8,"children":[{"type":"rectangle","cornerRadius":8,"id":"6FBws","name":"ll5b","fill":"$--accent-purple-light","width":"fill_container","height":60,"stroke":{"align":"inside","thickness":1,"fill":"$--border"}},{"type":"text","id":"i2DfV","name":"ll5n","fill":"$--foreground","content":"--accent-purple-light","fontFamily":"Inter","fontSize":12,"fontWeight":"500"}]}]},{"type":"text","id":"JFocf","name":"surfLbl","fill":"$--foreground","content":"Surface & Border Colors","fontFamily":"Inter","fontSize":18,"fontWeight":"600"},{"type":"frame","id":"YAJLW","name":"surfRow","width":"fill_container","gap":16,"children":[{"type":"frame","id":"JHS3j","name":"s1","width":"fill_container","layout":"vertical","gap":8,"children":[{"type":"rectangle","cornerRadius":8,"id":"9Bj41","name":"s1b","fill":"$--card","width":"fill_container","height":60,"stroke":{"align":"inside","thickness":1,"fill":"$--border"}},{"type":"text","id":"wn4ua","name":"s1n","fill":"$--foreground","content":"--card","fontFamily":"Inter","fontSize":12,"fontWeight":"500"}]},{"type":"frame","id":"Fyvfd","name":"s2","width":"fill_container","layout":"vertical","gap":8,"children":[{"type":"rectangle","cornerRadius":8,"id":"UFLw5","name":"s2b","fill":"$--sidebar","width":"fill_container","height":60,"stroke":{"align":"inside","thickness":1,"fill":"$--sidebar-border"}},{"type":"text","id":"gngfL","name":"s2n","fill":"$--foreground","content":"--sidebar","fontFamily":"Inter","fontSize":12,"fontWeight":"500"}]},{"type":"frame","id":"zbyEJ","name":"s3","width":"fill_container","layout":"vertical","gap":8,"children":[{"type":"rectangle","cornerRadius":8,"id":"WnmQD","name":"s3b","fill":"$--secondary","width":"fill_container","height":60},{"type":"text","id":"wnkxR","name":"s3n","fill":"$--foreground","content":"--secondary","fontFamily":"Inter","fontSize":12,"fontWeight":"500"}]},{"type":"frame","id":"Z2FuK","name":"s4","width":"fill_container","layout":"vertical","gap":8,"children":[{"type":"rectangle","cornerRadius":8,"id":"lNPnc","name":"s4b","fill":"$--border","width":"fill_container","height":60},{"type":"text","id":"x9aeh","name":"s4n","fill":"$--foreground","content":"--border / --input","fontFamily":"Inter","fontSize":12,"fontWeight":"500"}]},{"type":"frame","id":"TDDQ0","name":"s5","width":"fill_container","layout":"vertical","gap":8,"children":[{"type":"rectangle","cornerRadius":8,"id":"MwHOe","name":"s5b","fill":"$--muted-foreground","width":"fill_container","height":60},{"type":"text","id":"dHZj5","name":"s5n","fill":"$--foreground","content":"--muted-foreground","fontFamily":"Inter","fontSize":12,"fontWeight":"500"}]}]}]},{"type":"frame","id":"HZonq","x":0,"y":5252,"name":"Typography & Spacing Specs (Light)","theme":{"Mode":"Light"},"width":1440,"fill":"$--background","layout":"vertical","gap":32,"padding":40,"children":[{"type":"text","id":"nGLlU","name":"tTitle","fill":"$--foreground","content":"Typography Scale (Light)","fontFamily":"Inter","fontSize":28,"fontWeight":"700","letterSpacing":-0.5},{"type":"text","id":"gkQqO","name":"tSub","fill":"$--muted-foreground","textGrowth":"fixed-width","width":"fill_container","content":"Fonts: Inter, IBM Plex Mono. Base: 14px. System fallback: -apple-system, BlinkMacSystemFont, sans-serif.","lineHeight":1.5,"fontFamily":"Inter","fontSize":14,"fontWeight":"normal"},{"type":"frame","id":"QL9fK","name":"t1","width":"fill_container","gap":24,"alignItems":"center","children":[{"type":"text","id":"px1l7","name":"t1s","fill":"$--foreground","content":"Heading 1","lineHeight":1.2,"fontFamily":"Inter","fontSize":32,"fontWeight":"700"},{"type":"text","id":"3UWKu","name":"t1d","fill":"$--muted-foreground","content":"32px / Bold / lh 1.2 — Editor H1","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"}]},{"type":"frame","id":"Yjhit","name":"t2","width":"fill_container","gap":24,"alignItems":"center","children":[{"type":"text","id":"iFzl0","name":"t2s","fill":"$--foreground","content":"Heading 2","lineHeight":1.3,"fontFamily":"Inter","fontSize":24,"fontWeight":"600"},{"type":"text","id":"cF55I","name":"t2d","fill":"$--muted-foreground","content":"24px / Semibold / lh 1.3 — Editor H2","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"}]},{"type":"frame","id":"bBHMa","name":"t3","width":"fill_container","gap":24,"alignItems":"center","children":[{"type":"text","id":"kpSyr","name":"t3s","fill":"$--foreground","content":"App Title","fontFamily":"Inter","fontSize":17,"fontWeight":"700","letterSpacing":-0.3},{"type":"text","id":"xUuNz","name":"t3d","fill":"$--muted-foreground","content":"17px / Bold / ls -0.3 — Sidebar header","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"}]},{"type":"frame","id":"Lsh7F","name":"t4","width":"fill_container","gap":24,"alignItems":"center","children":[{"type":"text","id":"vTRSs","name":"t4s","fill":"$--foreground","content":"Body Text","lineHeight":1.6,"fontFamily":"Inter","fontSize":16,"fontWeight":"normal"},{"type":"text","id":"fKa3p","name":"t4d","fill":"$--muted-foreground","content":"16px / Regular / lh 1.6 — Editor paragraphs","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"}]},{"type":"frame","id":"rpOTz","name":"t5","width":"fill_container","gap":24,"alignItems":"center","children":[{"type":"text","id":"VXY3Z","name":"t5s","fill":"$--foreground","content":"UI Label / Button","lineHeight":1.43,"fontFamily":"Inter","fontSize":14,"fontWeight":"500"},{"type":"text","id":"F6GQz","name":"t5d","fill":"$--muted-foreground","content":"14px / Medium / lh 1.43 — Buttons, NoteList header, Inspector labels","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"}]},{"type":"frame","id":"H6Rgt","name":"t6","width":"fill_container","gap":24,"alignItems":"center","children":[{"type":"text","id":"xWvbj","name":"t6s","fill":"$--foreground","content":"Sidebar Item","fontFamily":"Inter","fontSize":13,"fontWeight":"500"},{"type":"text","id":"bvBBm","name":"t6d","fill":"$--muted-foreground","content":"13px / Medium — Sidebar nav items, filter items, search","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"}]},{"type":"frame","id":"GrFAq","name":"t7","width":"fill_container","gap":24,"alignItems":"center","children":[{"type":"text","id":"vY8j4","name":"t7s","fill":"$--muted-foreground","content":"SECTION HEADER","fontFamily":"Inter","fontSize":11,"fontWeight":"600","letterSpacing":0.5},{"type":"text","id":"okws6","name":"t7d","fill":"$--muted-foreground","content":"11px / Semibold / ls 0.5 — Sidebar sections, type pills","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"}]},{"type":"frame","id":"awxls","name":"t8","width":"fill_container","gap":24,"alignItems":"center","children":[{"type":"text","id":"mD3f5","name":"t8s","fill":"$--foreground","content":"ALL-CAPS LABEL","fontFamily":"IBM Plex Mono","fontSize":11,"fontWeight":"600","letterSpacing":1.2},{"type":"text","id":"jFpLw","name":"t8d","fill":"$--muted-foreground","content":"11px / Semibold / ls 1.2 / IBM Plex Mono — Section labels, metadata tags","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"}]},{"type":"frame","id":"ToLzL","name":"t9","width":"fill_container","gap":24,"alignItems":"center","children":[{"type":"text","id":"LEsxW","name":"t9s","fill":"$--muted-foreground","content":"OVERLINE TEXT","fontFamily":"IBM Plex Mono","fontSize":10,"fontWeight":"500","letterSpacing":1.5},{"type":"text","id":"HQ3Df","name":"t9d","fill":"$--muted-foreground","content":"10px / Medium / ls 1.5 / IBM Plex Mono — Overlines, category labels, timestamps","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"}]},{"type":"rectangle","id":"3tiJ7","name":"div1","fill":"$--border","width":"fill_container","height":1},{"type":"text","id":"b2Mt9","name":"spTitle","fill":"$--foreground","content":"Spacing & Layout Reference","fontFamily":"Inter","fontSize":28,"fontWeight":"700","letterSpacing":-0.5},{"type":"frame","id":"o6ETJ","name":"pnlRow","width":"fill_container","gap":16,"children":[{"type":"frame","id":"HhbOn","name":"p1","width":"fill_container","cornerRadius":8,"stroke":{"align":"inside","thickness":1,"fill":"$--border"},"layout":"vertical","gap":6,"padding":16,"children":[{"type":"text","id":"YBekR","name":"p1t","fill":"$--foreground","content":"Sidebar: 250px","fontFamily":"Inter","fontSize":14,"fontWeight":"600"},{"type":"text","id":"dT8Xe","name":"p1d","fill":"$--muted-foreground","textGrowth":"fixed-width","width":"fill_container","content":"bg: --sidebar | padding: 8px container, 12px 16px header, 6px 16px items","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"}]},{"type":"frame","id":"aYkMZ","name":"p2","width":"fill_container","cornerRadius":8,"stroke":{"align":"inside","thickness":1,"fill":"$--border"},"layout":"vertical","gap":6,"padding":16,"children":[{"type":"text","id":"Eycne","name":"p2t","fill":"$--foreground","content":"NoteList: 300px","fontFamily":"Inter","fontSize":14,"fontWeight":"600"},{"type":"text","id":"lyTZN","name":"p2d","fill":"$--muted-foreground","textGrowth":"fixed-width","width":"fill_container","content":"bg: --card | padding: 14px 16px header, 8px 12px search/pills, 10px 16px items","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"}]},{"type":"frame","id":"E6G3g","name":"p3","width":"fill_container","cornerRadius":8,"stroke":{"align":"inside","thickness":1,"fill":"$--border"},"layout":"vertical","gap":6,"padding":16,"children":[{"type":"text","id":"Xy5Gl","name":"p3t","fill":"$--foreground","content":"Editor: flexible","fontFamily":"Inter","fontSize":14,"fontWeight":"600"},{"type":"text","id":"y4svr","name":"p3d","fill":"$--muted-foreground","textGrowth":"fixed-width","width":"fill_container","content":"bg: --background | padding: 32px 64px content, 7px 14px tabs, gap: 16px","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"}]},{"type":"frame","id":"RBPav","name":"p4","width":"fill_container","cornerRadius":8,"stroke":{"align":"inside","thickness":1,"fill":"$--border"},"layout":"vertical","gap":6,"padding":16,"children":[{"type":"text","id":"xKUWC","name":"p4t","fill":"$--foreground","content":"Inspector: 280px","fontFamily":"Inter","fontSize":14,"fontWeight":"600"},{"type":"text","id":"u81W5","name":"p4d","fill":"$--muted-foreground","textGrowth":"fixed-width","width":"fill_container","content":"bg: --sidebar | padding: 14px 12px header, 12px body, 16px section gap, 8px prop gap","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"}]}]},{"type":"text","id":"VvZyF","name":"radLbl","fill":"$--foreground","content":"Border Radius","fontFamily":"Inter","fontSize":18,"fontWeight":"600"},{"type":"frame","id":"OwJH7","name":"radRow","width":"fill_container","gap":16,"children":[{"type":"frame","id":"DHrzV","name":"r1","width":"fill_container","layout":"vertical","gap":8,"alignItems":"center","children":[{"type":"rectangle","cornerRadius":4,"id":"V35oi","name":"r1b","fill":"$--secondary","width":80,"height":60,"stroke":{"align":"inside","thickness":1,"fill":"$--border"}},{"type":"text","id":"HVQpq","name":"r1n","fill":"$--foreground","content":"4px (sm) — chips","fontFamily":"Inter","fontSize":12,"fontWeight":"500"}]},{"type":"frame","id":"wp350","name":"r2","width":"fill_container","layout":"vertical","gap":8,"alignItems":"center","children":[{"type":"rectangle","cornerRadius":6,"id":"E031z","name":"r2b","fill":"$--secondary","width":80,"height":60,"stroke":{"align":"inside","thickness":1,"fill":"$--border"}},{"type":"text","id":"rDLff","name":"r2n","fill":"$--foreground","content":"6px (md) — buttons, inputs","fontFamily":"Inter","fontSize":12,"fontWeight":"500"}]},{"type":"frame","id":"d6tJt","name":"r3","width":"fill_container","layout":"vertical","gap":8,"alignItems":"center","children":[{"type":"rectangle","cornerRadius":8,"id":"PNkS4","name":"r3b","fill":"$--secondary","width":80,"height":60,"stroke":{"align":"inside","thickness":1,"fill":"$--border"}},{"type":"text","id":"rZGXb","name":"r3n","fill":"$--foreground","content":"8px (lg) — cards, dialogs","fontFamily":"Inter","fontSize":12,"fontWeight":"500"}]},{"type":"frame","id":"UAZ8u","name":"r4","width":"fill_container","layout":"vertical","gap":8,"alignItems":"center","children":[{"type":"rectangle","cornerRadius":16,"id":"wgMVG","name":"r4b","fill":"$--secondary","width":80,"height":60,"stroke":{"align":"inside","thickness":1,"fill":"$--border"}},{"type":"text","id":"zw3RY","name":"r4n","fill":"$--foreground","content":"16px — badges","fontFamily":"Inter","fontSize":12,"fontWeight":"500"}]}]},{"type":"rectangle","id":"kIrXE","name":"div2","fill":"$--border","width":"fill_container","height":1},{"type":"text","id":"FYw8k","name":"compTitle","fill":"$--foreground","content":"shadcn/ui Component Inventory","fontFamily":"Inter","fontSize":28,"fontWeight":"700","letterSpacing":-0.5},{"type":"frame","id":"7Q1Fi","name":"compRow","width":"fill_container","gap":16,"children":[{"type":"frame","id":"XfUwj","name":"cg1","width":"fill_container","fill":"$--card","cornerRadius":8,"stroke":{"align":"inside","thickness":1,"fill":"$--border"},"layout":"vertical","gap":12,"padding":16,"children":[{"type":"text","id":"ly7m0","name":"cg1t","fill":"$--accent-green","content":"In Use","fontFamily":"Inter","fontSize":14,"fontWeight":"600"},{"type":"text","id":"Re89a","name":"cg1r1","fill":"$--foreground","textGrowth":"fixed-width","width":"fill_container","content":"Button — 5 variants (Default, Secondary, Outline, Ghost, Destructive)","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"},{"type":"text","id":"ILbjW","name":"cg1r2","fill":"$--foreground","textGrowth":"fixed-width","width":"fill_container","content":"Input — Default text input with label group","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"},{"type":"text","id":"eurqS","name":"cg1r3","fill":"$--foreground","textGrowth":"fixed-width","width":"fill_container","content":"Dialog — Modal overlay (CreateNote, Commit)","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"},{"type":"text","id":"AZyZP","name":"cg1r4","fill":"$--foreground","textGrowth":"fixed-width","width":"fill_container","content":"Badge — 4 variants (Default, Secondary, Outline, Destructive)","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"}]},{"type":"frame","id":"WtehQ","name":"cg2","width":"fill_container","fill":"$--card","cornerRadius":8,"stroke":{"align":"inside","thickness":1,"fill":"$--border"},"layout":"vertical","gap":12,"padding":16,"children":[{"type":"text","id":"KaMZ9","name":"cg2t","fill":"$--accent-yellow","content":"Available (Not Yet Used)","fontFamily":"Inter","fontSize":14,"fontWeight":"600"},{"type":"text","id":"F8wam","name":"cg2r1","fill":"$--foreground","textGrowth":"fixed-width","width":"fill_container","content":"DropdownMenu — Context / dropdown menus","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"},{"type":"text","id":"Nl1aV","name":"cg2r2","fill":"$--foreground","textGrowth":"fixed-width","width":"fill_container","content":"Tabs — Tab navigation component","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"},{"type":"text","id":"0sBwH","name":"cg2r3","fill":"$--foreground","textGrowth":"fixed-width","width":"fill_container","content":"Tooltip, Select, Card, Separator, ScrollArea","fontFamily":"Inter","fontSize":12,"fontWeight":"normal"}]}]}]},{"type":"frame","id":"dsg01a","name":"Sidebar — Drag Handles Visible","x":68,"y":6400,"width":330,"height":680,"fill":"$--background","layout":"vertical","padding":[16],"theme":{"Mode":"Light"},"children":[{"type":"text","id":"dsg01b","name":"frame1Title","content":"Drag handles appear on section headers","fontFamily":"Inter","fontSize":14,"fontWeight":"600","fill":"$--foreground"},{"type":"text","id":"dsg01c","name":"frame1Desc","content":"Grip icon shown left of section icon. Cursor changes to grab on hover.","fontFamily":"Inter","fontSize":11,"fontWeight":"normal","fill":"$--muted-foreground"},{"type":"frame","id":"dsg01d","height":12},{"type":"frame","id":"dsg01e","name":"sidebarDefault","width":250,"height":600,"fill":"$--sidebar","layout":"vertical","clip":true,"children":[{"type":"frame","id":"dsg01f","name":"filters","width":"fill_container","layout":"vertical","gap":2,"padding":[8,6],"children":[{"type":"frame","id":"dsg01g","name":"allNotesRow","width":"fill_container","cornerRadius":4,"padding":[6,16],"gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"dsg01h","width":18,"height":18,"iconFontName":"file-text","iconFontFamily":"lucide","fill":"$--muted-foreground"},{"type":"text","id":"dsg01i","fill":"$--foreground","content":"All Notes","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"frame","id":"dsg01j","name":"favRow","width":"fill_container","cornerRadius":4,"padding":[6,16],"gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"dsg01k","width":18,"height":18,"iconFontName":"star","iconFontFamily":"lucide","fill":"$--muted-foreground"},{"type":"text","id":"dsg01l","fill":"$--muted-foreground","content":"Favorites","fontFamily":"Inter","fontSize":13,"fontWeight":"normal"}]}]},{"type":"frame","id":"dsg01m","name":"sectionsWrap","width":"fill_container","height":"fill_container","layout":"vertical","children":[{"type":"frame","id":"dsg00a","name":"projGroup","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":{"type":"color","color":"$--border","enabled":false}},"layout":"vertical","gap":2,"padding":[4,6,8,6],"children":[{"type":"frame","id":"dsg005","name":"projHeader","width":"fill_container","cornerRadius":4,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"dsg001","name":"projLeft","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"dsg000","name":"projDrag","width":14,"height":14,"iconFontName":"grip-vertical","iconFontFamily":"lucide","fill":"$--muted-foreground","opacity":0.5},{"type":"icon_font","id":"dsg002","name":"projIcon","width":18,"height":18,"iconFontName":"wrench","iconFontFamily":"phosphor","weight":700,"fill":"$--accent-red"},{"type":"text","id":"dsg003","name":"projLabel","fill":"$--foreground","content":"Projects","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"icon_font","id":"dsg004","name":"projChev","width":14,"height":14,"iconFontName":"chevron-down","iconFontFamily":"lucide","fill":"$--muted-foreground"}]},{"type":"frame","id":"dsg006","name":"projItem0","width":"fill_container","cornerRadius":6,"padding":[6,16,6,28],"alignItems":"center","fill":"$--accent-red-light","children":[{"type":"text","id":"dsg007","name":"projItemTxt0","fill":"$--accent-red","content":"Laputa App","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"frame","id":"dsg008","name":"projItem1","width":"fill_container","cornerRadius":6,"padding":[6,16,6,28],"alignItems":"center","children":[{"type":"text","id":"dsg009","name":"projItemTxt1","fill":"$--muted-foreground","content":"Portfolio Rewrite","fontFamily":"Inter","fontSize":13,"fontWeight":"normal"}]}]},{"type":"frame","id":"dsg00h","name":"respGroup","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":{"type":"color","color":"$--border","enabled":false}},"layout":"vertical","gap":2,"padding":[4,6],"children":[{"type":"frame","id":"dsg00g","name":"respHeader","width":"fill_container","cornerRadius":4,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"dsg00c","name":"respLeft","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"dsg00b","name":"respDrag","width":14,"height":14,"iconFontName":"grip-vertical","iconFontFamily":"lucide","fill":"$--muted-foreground","opacity":0.5},{"type":"icon_font","id":"dsg00d","name":"respIcon","width":18,"height":18,"iconFontName":"medal","iconFontFamily":"phosphor","weight":700,"fill":"$--accent-purple"},{"type":"text","id":"dsg00e","name":"respLabel","fill":"$--foreground","content":"Responsibilities","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"icon_font","id":"dsg00f","name":"respChev","width":14,"height":14,"iconFontName":"chevron-right","iconFontFamily":"lucide","fill":"$--muted-foreground"}]}]},{"type":"frame","id":"dsg00o","name":"procGroup","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":{"type":"color","color":"$--border","enabled":false}},"layout":"vertical","gap":2,"padding":[4,6],"children":[{"type":"frame","id":"dsg00n","name":"procHeader","width":"fill_container","cornerRadius":4,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"dsg00j","name":"procLeft","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"dsg00i","name":"procDrag","width":14,"height":14,"iconFontName":"grip-vertical","iconFontFamily":"lucide","fill":"$--muted-foreground","opacity":0.5},{"type":"icon_font","id":"dsg00k","name":"procIcon","width":18,"height":18,"iconFontName":"arrows-clockwise","iconFontFamily":"phosphor","weight":700,"fill":"$--accent-purple"},{"type":"text","id":"dsg00l","name":"procLabel","fill":"$--foreground","content":"Procedures","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"icon_font","id":"dsg00m","name":"procChev","width":14,"height":14,"iconFontName":"chevron-right","iconFontFamily":"lucide","fill":"$--muted-foreground"}]}]},{"type":"frame","id":"dsg00v","name":"peopleGroup","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":{"type":"color","color":"$--border","enabled":false}},"layout":"vertical","gap":2,"padding":[4,6],"children":[{"type":"frame","id":"dsg00u","name":"peopleHeader","width":"fill_container","cornerRadius":4,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"dsg00q","name":"peopleLeft","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"dsg00p","name":"peopleDrag","width":14,"height":14,"iconFontName":"grip-vertical","iconFontFamily":"lucide","fill":"$--muted-foreground","opacity":0.5},{"type":"icon_font","id":"dsg00r","name":"peopleIcon","width":18,"height":18,"iconFontName":"leaf","iconFontFamily":"phosphor","weight":700,"fill":"$--accent-yellow"},{"type":"text","id":"dsg00s","name":"peopleLabel","fill":"$--foreground","content":"People","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"icon_font","id":"dsg00t","name":"peopleChev","width":14,"height":14,"iconFontName":"chevron-right","iconFontFamily":"lucide","fill":"$--muted-foreground"}]}]},{"type":"frame","id":"dsg012","name":"eventsGroup","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":{"type":"color","color":"$--border","enabled":false}},"layout":"vertical","gap":2,"padding":[4,6],"children":[{"type":"frame","id":"dsg011","name":"eventsHeader","width":"fill_container","cornerRadius":4,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"dsg00x","name":"eventsLeft","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"dsg00w","name":"eventsDrag","width":14,"height":14,"iconFontName":"grip-vertical","iconFontFamily":"lucide","fill":"$--muted-foreground","opacity":0.5},{"type":"icon_font","id":"dsg00y","name":"eventsIcon","width":18,"height":18,"iconFontName":"cardholder","iconFontFamily":"phosphor","weight":700,"fill":"$--accent-yellow"},{"type":"text","id":"dsg00z","name":"eventsLabel","fill":"$--foreground","content":"Events","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"icon_font","id":"dsg010","name":"eventsChev","width":14,"height":14,"iconFontName":"chevron-right","iconFontFamily":"lucide","fill":"$--muted-foreground"}]}]},{"type":"frame","id":"dsg019","name":"topicsGroup","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":{"type":"color","color":"$--border","enabled":false}},"layout":"vertical","gap":2,"padding":[4,6],"children":[{"type":"frame","id":"dsg018","name":"topicsHeader","width":"fill_container","cornerRadius":4,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"dsg014","name":"topicsLeft","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"dsg013","name":"topicsDrag","width":14,"height":14,"iconFontName":"grip-vertical","iconFontFamily":"lucide","fill":"$--muted-foreground","opacity":0.5},{"type":"icon_font","id":"dsg015","name":"topicsIcon","width":18,"height":18,"iconFontName":"tag","iconFontFamily":"phosphor","weight":700,"fill":"$--accent-green"},{"type":"text","id":"dsg016","name":"topicsLabel","fill":"$--foreground","content":"Topics","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"icon_font","id":"dsg017","name":"topicsChev","width":14,"height":14,"iconFontName":"chevron-right","iconFontFamily":"lucide","fill":"$--muted-foreground"}]}]}]}]}]},{"type":"frame","id":"dsg02w","name":"Sidebar — Section Being Dragged","x":420,"y":6400,"width":330,"height":680,"fill":"$--background","layout":"vertical","padding":[16],"theme":{"Mode":"Light"},"children":[{"type":"text","id":"dsg02x","name":"frame2Title","content":"Dragging \"People\" above \"Responsibilities\"","fontFamily":"Inter","fontSize":14,"fontWeight":"600","fill":"$--foreground"},{"type":"text","id":"dsg02y","name":"frame2Desc","content":"Blue drop indicator line shows insertion point. Dragged section floats with blue border.","fontFamily":"Inter","fontSize":11,"fontWeight":"normal","fill":"$--muted-foreground"},{"type":"frame","id":"dsg02z","height":12},{"type":"frame","id":"dsg030","name":"sidebarDragging","width":250,"height":600,"fill":"$--sidebar","layout":"vertical","clip":true,"children":[{"type":"frame","id":"dsg031","name":"filters","width":"fill_container","layout":"vertical","gap":2,"padding":[8,6],"children":[{"type":"frame","id":"dsg032","name":"allNotesRow","width":"fill_container","cornerRadius":4,"padding":[6,16],"gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"dsg033","width":18,"height":18,"iconFontName":"file-text","iconFontFamily":"lucide","fill":"$--muted-foreground"},{"type":"text","id":"dsg034","fill":"$--foreground","content":"All Notes","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"frame","id":"dsg035","name":"favRow","width":"fill_container","cornerRadius":4,"padding":[6,16],"gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"dsg036","width":18,"height":18,"iconFontName":"star","iconFontFamily":"lucide","fill":"$--muted-foreground"},{"type":"text","id":"dsg037","fill":"$--muted-foreground","content":"Favorites","fontFamily":"Inter","fontSize":13,"fontWeight":"normal"}]}]},{"type":"frame","id":"dsg038","name":"sectionsWrap","width":"fill_container","height":"fill_container","layout":"vertical","children":[{"type":"frame","id":"dsg01x","name":"proj2Group","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":{"type":"color","color":"$--border","enabled":false}},"layout":"vertical","gap":2,"padding":[4,6,8,6],"children":[{"type":"frame","id":"dsg01s","name":"proj2Header","width":"fill_container","cornerRadius":4,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"dsg01o","name":"proj2Left","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"dsg01n","name":"proj2Drag","width":14,"height":14,"iconFontName":"grip-vertical","iconFontFamily":"lucide","fill":"$--muted-foreground","opacity":0.5},{"type":"icon_font","id":"dsg01p","name":"proj2Icon","width":18,"height":18,"iconFontName":"wrench","iconFontFamily":"phosphor","weight":700,"fill":"$--accent-red"},{"type":"text","id":"dsg01q","name":"proj2Label","fill":"$--foreground","content":"Projects","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"icon_font","id":"dsg01r","name":"proj2Chev","width":14,"height":14,"iconFontName":"chevron-down","iconFontFamily":"lucide","fill":"$--muted-foreground"}]},{"type":"frame","id":"dsg01t","name":"proj2Item0","width":"fill_container","cornerRadius":6,"padding":[6,16,6,28],"alignItems":"center","fill":"$--accent-red-light","children":[{"type":"text","id":"dsg01u","name":"proj2ItemTxt0","fill":"$--accent-red","content":"Laputa App","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"frame","id":"dsg01v","name":"proj2Item1","width":"fill_container","cornerRadius":6,"padding":[6,16,6,28],"alignItems":"center","children":[{"type":"text","id":"dsg01w","name":"proj2ItemTxt1","fill":"$--muted-foreground","content":"Portfolio Rewrite","fontFamily":"Inter","fontSize":13,"fontWeight":"normal"}]}]},{"type":"frame","id":"dsg01y","name":"dropIndicator","width":"fill_container","height":2,"fill":"$--accent-blue","cornerRadius":1},{"type":"frame","id":"dsg025","name":"resp2Group","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":{"type":"color","color":"$--border","enabled":false}},"layout":"vertical","gap":2,"padding":[4,6],"children":[{"type":"frame","id":"dsg024","name":"resp2Header","width":"fill_container","cornerRadius":4,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"dsg020","name":"resp2Left","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"dsg01z","name":"resp2Drag","width":14,"height":14,"iconFontName":"grip-vertical","iconFontFamily":"lucide","fill":"$--muted-foreground","opacity":0.5},{"type":"icon_font","id":"dsg021","name":"resp2Icon","width":18,"height":18,"iconFontName":"medal","iconFontFamily":"phosphor","weight":700,"fill":"$--accent-purple"},{"type":"text","id":"dsg022","name":"resp2Label","fill":"$--foreground","content":"Responsibilities","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"icon_font","id":"dsg023","name":"resp2Chev","width":14,"height":14,"iconFontName":"chevron-right","iconFontFamily":"lucide","fill":"$--muted-foreground"}]}]},{"type":"frame","id":"dsg02c","name":"proc2Group","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":{"type":"color","color":"$--border","enabled":false}},"layout":"vertical","gap":2,"padding":[4,6],"children":[{"type":"frame","id":"dsg02b","name":"proc2Header","width":"fill_container","cornerRadius":4,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"dsg027","name":"proc2Left","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"dsg026","name":"proc2Drag","width":14,"height":14,"iconFontName":"grip-vertical","iconFontFamily":"lucide","fill":"$--muted-foreground","opacity":0.5},{"type":"icon_font","id":"dsg028","name":"proc2Icon","width":18,"height":18,"iconFontName":"arrows-clockwise","iconFontFamily":"phosphor","weight":700,"fill":"$--accent-purple"},{"type":"text","id":"dsg029","name":"proc2Label","fill":"$--foreground","content":"Procedures","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"icon_font","id":"dsg02a","name":"proc2Chev","width":14,"height":14,"iconFontName":"chevron-right","iconFontFamily":"lucide","fill":"$--muted-foreground"}]}]},{"type":"frame","id":"dsg02j","name":"events2Group","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":{"type":"color","color":"$--border","enabled":false}},"layout":"vertical","gap":2,"padding":[4,6],"children":[{"type":"frame","id":"dsg02i","name":"events2Header","width":"fill_container","cornerRadius":4,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"dsg02e","name":"events2Left","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"dsg02d","name":"events2Drag","width":14,"height":14,"iconFontName":"grip-vertical","iconFontFamily":"lucide","fill":"$--muted-foreground","opacity":0.5},{"type":"icon_font","id":"dsg02f","name":"events2Icon","width":18,"height":18,"iconFontName":"cardholder","iconFontFamily":"phosphor","weight":700,"fill":"$--accent-yellow"},{"type":"text","id":"dsg02g","name":"events2Label","fill":"$--foreground","content":"Events","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"icon_font","id":"dsg02h","name":"events2Chev","width":14,"height":14,"iconFontName":"chevron-right","iconFontFamily":"lucide","fill":"$--muted-foreground"}]}]},{"type":"frame","id":"dsg02q","name":"topics2Group","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":{"type":"color","color":"$--border","enabled":false}},"layout":"vertical","gap":2,"padding":[4,6],"children":[{"type":"frame","id":"dsg02p","name":"topics2Header","width":"fill_container","cornerRadius":4,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"dsg02l","name":"topics2Left","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"dsg02k","name":"topics2Drag","width":14,"height":14,"iconFontName":"grip-vertical","iconFontFamily":"lucide","fill":"$--muted-foreground","opacity":0.5},{"type":"icon_font","id":"dsg02m","name":"topics2Icon","width":18,"height":18,"iconFontName":"tag","iconFontFamily":"phosphor","weight":700,"fill":"$--accent-green"},{"type":"text","id":"dsg02n","name":"topics2Label","fill":"$--foreground","content":"Topics","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"icon_font","id":"dsg02o","name":"topics2Chev","width":14,"height":14,"iconFontName":"chevron-right","iconFontFamily":"lucide","fill":"$--muted-foreground"}]}]}]}]},{"type":"frame","id":"dsg02r","name":"draggedSection","x":8,"y":160,"width":234,"fill":"$--sidebar","cornerRadius":6,"stroke":{"align":"outside","thickness":1,"fill":{"type":"color","color":"$--accent-blue"}},"opacity":0.9,"layout":"vertical","padding":[4,6],"children":[{"type":"frame","id":"dsg02s","name":"draggedHeader","width":"fill_container","cornerRadius":4,"gap":8,"padding":[6,16],"alignItems":"center","children":[{"type":"icon_font","id":"dsg02t","width":14,"height":14,"iconFontName":"grip-vertical","iconFontFamily":"lucide","fill":"$--accent-blue","opacity":0.8},{"type":"icon_font","id":"dsg02u","width":18,"height":18,"iconFontName":"leaf","iconFontFamily":"phosphor","weight":700,"fill":"$--accent-yellow"},{"type":"text","id":"dsg02v","fill":"$--foreground","content":"People","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]}]}]},{"type":"frame","id":"dsg04j","name":"Sidebar — After Reorder (People Moved Up)","x":772,"y":6400,"width":330,"height":680,"fill":"$--background","layout":"vertical","padding":[16],"theme":{"Mode":"Light"},"children":[{"type":"text","id":"dsg04k","name":"frame3Title","content":"After drop — People now second section","fontFamily":"Inter","fontSize":14,"fontWeight":"600","fill":"$--foreground"},{"type":"text","id":"dsg04l","name":"frame3Desc","content":"Order persisted as \"order\" property in each Type document frontmatter (e.g. order: 2).","fontFamily":"Inter","fontSize":11,"fontWeight":"normal","fill":"$--muted-foreground"},{"type":"frame","id":"dsg04m","height":12},{"type":"frame","id":"dsg04n","name":"sidebarReordered","width":250,"height":600,"fill":"$--sidebar","layout":"vertical","clip":true,"children":[{"type":"frame","id":"dsg04o","name":"filters","width":"fill_container","layout":"vertical","gap":2,"padding":[8,6],"children":[{"type":"frame","id":"dsg04p","name":"allNotesRow","width":"fill_container","cornerRadius":4,"padding":[6,16],"gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"dsg04q","width":18,"height":18,"iconFontName":"file-text","iconFontFamily":"lucide","fill":"$--muted-foreground"},{"type":"text","id":"dsg04r","fill":"$--foreground","content":"All Notes","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"frame","id":"dsg04s","name":"favRow","width":"fill_container","cornerRadius":4,"padding":[6,16],"gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"dsg04t","width":18,"height":18,"iconFontName":"star","iconFontFamily":"lucide","fill":"$--muted-foreground"},{"type":"text","id":"dsg04u","fill":"$--muted-foreground","content":"Favorites","fontFamily":"Inter","fontSize":13,"fontWeight":"normal"}]}]},{"type":"frame","id":"dsg04v","name":"sectionsWrap","width":"fill_container","height":"fill_container","layout":"vertical","children":[{"type":"frame","id":"dsg03j","name":"proj3Group","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":{"type":"color","color":"$--border","enabled":false}},"layout":"vertical","gap":2,"padding":[4,6,8,6],"children":[{"type":"frame","id":"dsg03e","name":"proj3Header","width":"fill_container","cornerRadius":4,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"dsg03a","name":"proj3Left","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"dsg039","name":"proj3Drag","width":14,"height":14,"iconFontName":"grip-vertical","iconFontFamily":"lucide","fill":"$--muted-foreground","opacity":0.5},{"type":"icon_font","id":"dsg03b","name":"proj3Icon","width":18,"height":18,"iconFontName":"wrench","iconFontFamily":"phosphor","weight":700,"fill":"$--accent-red"},{"type":"text","id":"dsg03c","name":"proj3Label","fill":"$--foreground","content":"Projects","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"icon_font","id":"dsg03d","name":"proj3Chev","width":14,"height":14,"iconFontName":"chevron-down","iconFontFamily":"lucide","fill":"$--muted-foreground"}]},{"type":"frame","id":"dsg03f","name":"proj3Item0","width":"fill_container","cornerRadius":6,"padding":[6,16,6,28],"alignItems":"center","fill":"$--accent-red-light","children":[{"type":"text","id":"dsg03g","name":"proj3ItemTxt0","fill":"$--accent-red","content":"Laputa App","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"frame","id":"dsg03h","name":"proj3Item1","width":"fill_container","cornerRadius":6,"padding":[6,16,6,28],"alignItems":"center","children":[{"type":"text","id":"dsg03i","name":"proj3ItemTxt1","fill":"$--muted-foreground","content":"Portfolio Rewrite","fontFamily":"Inter","fontSize":13,"fontWeight":"normal"}]}]},{"type":"frame","id":"dsg03q","name":"people3Group","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":{"type":"color","color":"$--border","enabled":false}},"layout":"vertical","gap":2,"padding":[4,6],"children":[{"type":"frame","id":"dsg03p","name":"people3Header","width":"fill_container","cornerRadius":4,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"dsg03l","name":"people3Left","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"dsg03k","name":"people3Drag","width":14,"height":14,"iconFontName":"grip-vertical","iconFontFamily":"lucide","fill":"$--muted-foreground","opacity":0.5},{"type":"icon_font","id":"dsg03m","name":"people3Icon","width":18,"height":18,"iconFontName":"leaf","iconFontFamily":"phosphor","weight":700,"fill":"$--accent-yellow"},{"type":"text","id":"dsg03n","name":"people3Label","fill":"$--foreground","content":"People","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"icon_font","id":"dsg03o","name":"people3Chev","width":14,"height":14,"iconFontName":"chevron-right","iconFontFamily":"lucide","fill":"$--muted-foreground"}]}]},{"type":"frame","id":"dsg03x","name":"resp3Group","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":{"type":"color","color":"$--border","enabled":false}},"layout":"vertical","gap":2,"padding":[4,6],"children":[{"type":"frame","id":"dsg03w","name":"resp3Header","width":"fill_container","cornerRadius":4,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"dsg03s","name":"resp3Left","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"dsg03r","name":"resp3Drag","width":14,"height":14,"iconFontName":"grip-vertical","iconFontFamily":"lucide","fill":"$--muted-foreground","opacity":0.5},{"type":"icon_font","id":"dsg03t","name":"resp3Icon","width":18,"height":18,"iconFontName":"medal","iconFontFamily":"phosphor","weight":700,"fill":"$--accent-purple"},{"type":"text","id":"dsg03u","name":"resp3Label","fill":"$--foreground","content":"Responsibilities","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"icon_font","id":"dsg03v","name":"resp3Chev","width":14,"height":14,"iconFontName":"chevron-right","iconFontFamily":"lucide","fill":"$--muted-foreground"}]}]},{"type":"frame","id":"dsg044","name":"proc3Group","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":{"type":"color","color":"$--border","enabled":false}},"layout":"vertical","gap":2,"padding":[4,6],"children":[{"type":"frame","id":"dsg043","name":"proc3Header","width":"fill_container","cornerRadius":4,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"dsg03z","name":"proc3Left","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"dsg03y","name":"proc3Drag","width":14,"height":14,"iconFontName":"grip-vertical","iconFontFamily":"lucide","fill":"$--muted-foreground","opacity":0.5},{"type":"icon_font","id":"dsg040","name":"proc3Icon","width":18,"height":18,"iconFontName":"arrows-clockwise","iconFontFamily":"phosphor","weight":700,"fill":"$--accent-purple"},{"type":"text","id":"dsg041","name":"proc3Label","fill":"$--foreground","content":"Procedures","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"icon_font","id":"dsg042","name":"proc3Chev","width":14,"height":14,"iconFontName":"chevron-right","iconFontFamily":"lucide","fill":"$--muted-foreground"}]}]},{"type":"frame","id":"dsg04b","name":"events3Group","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":{"type":"color","color":"$--border","enabled":false}},"layout":"vertical","gap":2,"padding":[4,6],"children":[{"type":"frame","id":"dsg04a","name":"events3Header","width":"fill_container","cornerRadius":4,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"dsg046","name":"events3Left","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"dsg045","name":"events3Drag","width":14,"height":14,"iconFontName":"grip-vertical","iconFontFamily":"lucide","fill":"$--muted-foreground","opacity":0.5},{"type":"icon_font","id":"dsg047","name":"events3Icon","width":18,"height":18,"iconFontName":"cardholder","iconFontFamily":"phosphor","weight":700,"fill":"$--accent-yellow"},{"type":"text","id":"dsg048","name":"events3Label","fill":"$--foreground","content":"Events","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"icon_font","id":"dsg049","name":"events3Chev","width":14,"height":14,"iconFontName":"chevron-right","iconFontFamily":"lucide","fill":"$--muted-foreground"}]}]},{"type":"frame","id":"dsg04i","name":"topics3Group","width":"fill_container","stroke":{"align":"inside","thickness":{"bottom":1},"fill":{"type":"color","color":"$--border","enabled":false}},"layout":"vertical","gap":2,"padding":[4,6],"children":[{"type":"frame","id":"dsg04h","name":"topics3Header","width":"fill_container","cornerRadius":4,"gap":8,"padding":[6,16],"justifyContent":"space_between","alignItems":"center","children":[{"type":"frame","id":"dsg04d","name":"topics3Left","gap":8,"alignItems":"center","children":[{"type":"icon_font","id":"dsg04c","name":"topics3Drag","width":14,"height":14,"iconFontName":"grip-vertical","iconFontFamily":"lucide","fill":"$--muted-foreground","opacity":0.5},{"type":"icon_font","id":"dsg04e","name":"topics3Icon","width":18,"height":18,"iconFontName":"tag","iconFontFamily":"phosphor","weight":700,"fill":"$--accent-green"},{"type":"text","id":"dsg04f","name":"topics3Label","fill":"$--foreground","content":"Topics","fontFamily":"Inter","fontSize":13,"fontWeight":"500"}]},{"type":"icon_font","id":"dsg04g","name":"topics3Chev","width":14,"height":14,"iconFontName":"chevron-right","iconFontFamily":"lucide","fill":"$--muted-foreground"}]}]}]}]}]}],"themes":{"Mode":["Dark"]},"variables":{"--accent":{"type":"color","value":[{"value":"#EBEBEA"},{"value":"#252545","theme":{"Mode":"Dark"}}]},"--accent-blue":{"type":"color","value":[{"value":"#2383E2"},{"value":"#4a9eff","theme":{"Mode":"Dark"}},{"value":"#155DFF"},{"value":"#155DFF","theme":{"Mode":"Dark"}}]},"--accent-foreground":{"type":"color","value":[{"value":"#37352F"},{"value":"#ffffff","theme":{"Mode":"Dark"}}]},"--accent-green":{"type":"color","value":[{"value":"#0F7B6C"},{"value":"#4caf50","theme":{"Mode":"Dark"}},{"value":"#00B38B"},{"value":"#00B38B","theme":{"Mode":"Dark"}}]},"--accent-orange":{"type":"color","value":[{"value":"#D9730D"},{"value":"#ff9800","theme":{"Mode":"Dark"}}]},"--accent-purple":{"type":"color","value":[{"value":"#9065B0"},{"value":"#9c72ff","theme":{"Mode":"Dark"}},{"value":"#A932FF"},{"value":"#A932FF","theme":{"Mode":"Dark"}}]},"--accent-red":{"type":"color","value":[{"value":"#E03E3E"},{"value":"#f44336","theme":{"Mode":"Dark"}}]},"--background":{"type":"color","value":[{"value":"#FFFFFF"},{"value":"#0f0f1a","theme":{"Mode":"Dark"}}]},"--black":{"type":"color","value":"#000000"},"--border":{"type":"color","value":[{"value":"#E9E9E7"},{"value":"#2a2a4a","theme":{"Mode":"Dark"}}]},"--card":{"type":"color","value":[{"value":"#FFFFFF"},{"value":"#16162a","theme":{"Mode":"Dark"}}]},"--card-foreground":{"type":"color","value":[{"value":"#37352F"},{"value":"#e0e0e0","theme":{"Mode":"Dark"}}]},"--destructive":{"type":"color","value":[{"value":"#E03E3E"},{"value":"#f44336","theme":{"Mode":"Dark"}}]},"--destructive-foreground":{"type":"color","value":[{"value":"#FFFFFF"},{"value":"#ffffff","theme":{"Mode":"Dark"}}]},"--font-primary":{"type":"string","value":[{"value":"Inter"},{"value":"-apple-system, BlinkMacSystemFont, Inter, sans-serif"},{"value":"Inter"}]},"--font-system":{"type":"string","value":"-apple-system, BlinkMacSystemFont, sans-serif"},"--foreground":{"type":"color","value":[{"value":"#37352F"},{"value":"#e0e0e0","theme":{"Mode":"Dark"}}]},"--input":{"type":"color","value":[{"value":"#E9E9E7"},{"value":"#2a2a4a","theme":{"Mode":"Dark"}}]},"--muted":{"type":"color","value":[{"value":"#F0F0EF"},{"value":"#1e1e3a","theme":{"Mode":"Dark"}}]},"--muted-foreground":{"type":"color","value":[{"value":"#787774"},{"value":"#888888","theme":{"Mode":"Dark"}}]},"--popover":{"type":"color","value":[{"value":"#FFFFFF"},{"value":"#1e1e3a","theme":{"Mode":"Dark"}}]},"--popover-foreground":{"type":"color","value":[{"value":"#37352F"},{"value":"#e0e0e0","theme":{"Mode":"Dark"}}]},"--primary":{"type":"color","value":[{"value":"#2383E2"},{"value":"#4a9eff","theme":{"Mode":"Dark"}},{"value":"#155DFF"},{"value":"#155DFF","theme":{"Mode":"Dark"}}]},"--primary-foreground":{"type":"color","value":[{"value":"#FFFFFF"},{"value":"#ffffff","theme":{"Mode":"Dark"}}]},"--radius-lg":{"type":"number","value":8},"--radius-md":{"type":"number","value":6},"--radius-sm":{"type":"number","value":4},"--ring":{"type":"color","value":[{"value":"#2383E2"},{"value":"#4a9eff","theme":{"Mode":"Dark"}},{"value":"#155DFF"},{"value":"#155DFF","theme":{"Mode":"Dark"}}]},"--secondary":{"type":"color","value":[{"value":"#EBEBEA"},{"value":"#2a2a4a","theme":{"Mode":"Dark"}}]},"--secondary-foreground":{"type":"color","value":[{"value":"#37352F"},{"value":"#e0e0e0","theme":{"Mode":"Dark"}}]},"--sidebar":{"type":"color","value":[{"value":"#F7F6F3"},{"value":"#1a1a2e","theme":{"Mode":"Dark"}}]},"--sidebar-accent":{"type":"color","value":[{"value":"#EBEBEA"},{"value":"#252545","theme":{"Mode":"Dark"}}]},"--sidebar-accent-foreground":{"type":"color","value":[{"value":"#37352F"},{"value":"#ffffff","theme":{"Mode":"Dark"}}]},"--sidebar-border":{"type":"color","value":[{"value":"#E9E9E7"},{"value":"#2a2a4a","theme":{"Mode":"Dark"}}]},"--sidebar-foreground":{"type":"color","value":[{"value":"#37352F"},{"value":"#e0e0e0","theme":{"Mode":"Dark"}}]},"--sidebar-primary":{"type":"color","value":[{"value":"#2383E2"},{"value":"#4a9eff","theme":{"Mode":"Dark"}},{"value":"#155DFF"},{"value":"#155DFF","theme":{"Mode":"Dark"}}]},"--sidebar-primary-foreground":{"type":"color","value":[{"value":"#FFFFFF"},{"value":"#ffffff","theme":{"Mode":"Dark"}}]},"--sidebar-ring":{"type":"color","value":[{"value":"#2383E2"},{"value":"#4a9eff","theme":{"Mode":"Dark"}},{"value":"#155DFF"},{"value":"#155DFF","theme":{"Mode":"Dark"}}]},"--white":{"type":"color","value":"#ffffff"},"--accent-yellow":{"type":"color","value":[{"value":"#F0B100"},{"value":"#F0B100","theme":{"Mode":"Dark"}}]},"--accent-blue-light":{"type":"color","value":[{"value":"#155DFF14"},{"value":"#155DFF20","theme":{"Mode":"Dark"}}]},"--accent-green-light":{"type":"color","value":[{"value":"#00B38B14"},{"value":"#00B38B20","theme":{"Mode":"Dark"}}]},"--accent-purple-light":{"type":"color","value":[{"value":"#A932FF14"},{"value":"#A932FF20","theme":{"Mode":"Dark"}}]},"--accent-red-light":{"type":"color","value":[{"value":"#E03E3E14"},{"value":"#f4433620","theme":{"Mode":"Dark"}}]},"--accent-yellow-light":{"type":"color","value":[{"value":"#F0B10014"},{"value":"#F0B10020","theme":{"Mode":"Dark"}}]}},"fonts":[{"name":"GT Pressura Trial","url":"GT-Pressura-Regular-Trial.otf"}]} \ No newline at end of file From 1dfbbb8a9e5cfa6af58fdd2a0d273ae27033b12a Mon Sep 17 00:00:00 2001 From: lucaronin Date: Sat, 21 Feb 2026 17:27:19 +0100 Subject: [PATCH 2/4] feat: add order property to VaultEntry and install @dnd-kit - Add `order: number | null` to VaultEntry (TS) and VaultEntry (Rust) - Add order to Frontmatter struct and SKIP_KEYS in vault.rs - Update all mock Type documents with order values (0-10) - Add order: null to all non-Type mock entries and test fixtures - Install @dnd-kit/core, @dnd-kit/sortable, @dnd-kit/utilities Co-Authored-By: Claude Opus 4.6 --- package.json | 3 ++ pnpm-lock.yaml | 56 +++++++++++++++++++++++++++++++ src-tauri/src/vault.rs | 7 +++- src/components/Editor.test.tsx | 1 + src/components/Inspector.test.tsx | 2 ++ src/components/NoteList.test.tsx | 7 ++++ src/components/Sidebar.test.tsx | 12 +++++++ src/hooks/useNoteActions.ts | 4 +-- src/mock-tauri.ts | 39 +++++++++++++++++++++ src/types.ts | 2 ++ 10 files changed, 130 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index f03f7a28..60451401 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,9 @@ "@blocknote/core": "^0.46.2", "@blocknote/mantine": "^0.46.2", "@blocknote/react": "^0.46.2", + "@dnd-kit/core": "^6.3.1", + "@dnd-kit/sortable": "^10.0.0", + "@dnd-kit/utilities": "^3.2.2", "@mantine/core": "^8.3.14", "@phosphor-icons/react": "^2.1.10", "@radix-ui/react-dialog": "^1.1.15", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d3f43253..949346a2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,6 +20,15 @@ importers: '@blocknote/react': specifier: ^0.46.2 version: 0.46.2(@floating-ui/dom@1.7.5)(@types/hast@3.0.4)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(highlight.js@11.11.1)(lowlight@3.3.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@dnd-kit/core': + specifier: ^6.3.1 + version: 6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@dnd-kit/sortable': + specifier: ^10.0.0 + version: 10.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4) + '@dnd-kit/utilities': + specifier: ^3.2.2 + version: 3.2.2(react@19.2.4) '@mantine/core': specifier: ^8.3.14 version: 8.3.14(@mantine/hooks@8.3.14(react@19.2.4))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -322,6 +331,28 @@ packages: resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==} engines: {node: '>=20.19.0'} + '@dnd-kit/accessibility@3.1.1': + resolution: {integrity: sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==} + peerDependencies: + react: '>=16.8.0' + + '@dnd-kit/core@6.3.1': + resolution: {integrity: sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@dnd-kit/sortable@10.0.0': + resolution: {integrity: sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg==} + peerDependencies: + '@dnd-kit/core': ^6.3.0 + react: '>=16.8.0' + + '@dnd-kit/utilities@3.2.2': + resolution: {integrity: sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==} + peerDependencies: + react: '>=16.8.0' + '@emoji-mart/data@1.2.1': resolution: {integrity: sha512-no2pQMWiBy6gpBEiqGeU77/bFejDqUTRY7KX+0+iur13op3bqUsXdnwoZs6Xb1zbv0gAj5VvS1PWoUUckSr5Dw==} @@ -3811,6 +3842,31 @@ snapshots: '@csstools/css-tokenizer@4.0.0': {} + '@dnd-kit/accessibility@3.1.1(react@19.2.4)': + dependencies: + react: 19.2.4 + tslib: 2.8.1 + + '@dnd-kit/core@6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@dnd-kit/accessibility': 3.1.1(react@19.2.4) + '@dnd-kit/utilities': 3.2.2(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + tslib: 2.8.1 + + '@dnd-kit/sortable@10.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)': + dependencies: + '@dnd-kit/core': 6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@dnd-kit/utilities': 3.2.2(react@19.2.4) + react: 19.2.4 + tslib: 2.8.1 + + '@dnd-kit/utilities@3.2.2(react@19.2.4)': + dependencies: + react: 19.2.4 + tslib: 2.8.1 + '@emoji-mart/data@1.2.1': {} '@esbuild/aix-ppc64@0.27.3': diff --git a/src-tauri/src/vault.rs b/src-tauri/src/vault.rs index 5005e98f..35bfa838 100644 --- a/src-tauri/src/vault.rs +++ b/src-tauri/src/vault.rs @@ -39,6 +39,8 @@ pub struct VaultEntry { pub icon: Option, /// Accent color key for Type entries: "red", "purple", "blue", "green", "yellow", "orange". pub color: Option, + /// Display order for Type entries in sidebar (lower = higher). None = use default order. + pub order: Option, } /// Intermediate struct to capture YAML frontmatter fields. @@ -68,6 +70,8 @@ struct Frontmatter { icon: Option, #[serde(default)] color: Option, + #[serde(default)] + order: Option, } /// Handles YAML fields that can be either a single string or a list of strings. @@ -214,7 +218,7 @@ fn parse_frontmatter(data: &HashMap) -> Frontmatter { /// Only skip keys that can never contain wikilinks. const SKIP_KEYS: &[&str] = &[ "is a", "aliases", "status", "cadence", "archived", "created at", "created time", - "icon", "color", + "icon", "color", "order", ]; /// Check if a string contains a wikilink pattern `[[...]]`. @@ -367,6 +371,7 @@ pub fn parse_md_file(path: &Path) -> Result { modified_at, created_at, file_size, icon: frontmatter.icon, color: frontmatter.color, + order: frontmatter.order, }) } diff --git a/src/components/Editor.test.tsx b/src/components/Editor.test.tsx index e1b6e392..0848f367 100644 --- a/src/components/Editor.test.tsx +++ b/src/components/Editor.test.tsx @@ -60,6 +60,7 @@ const mockEntry: VaultEntry = { relationships: {}, icon: null, color: null, + order: null, } const mockContent = `--- diff --git a/src/components/Inspector.test.tsx b/src/components/Inspector.test.tsx index 8bb351f6..e58f2c31 100644 --- a/src/components/Inspector.test.tsx +++ b/src/components/Inspector.test.tsx @@ -22,6 +22,7 @@ const mockEntry: VaultEntry = { relationships: {}, icon: null, color: null, + order: null, } const mockContent = `--- @@ -61,6 +62,7 @@ const referrerEntry: VaultEntry = { relationships: {}, icon: null, color: null, + order: null, } const allContent: Record = { diff --git a/src/components/NoteList.test.tsx b/src/components/NoteList.test.tsx index 91c2cc4a..439473c0 100644 --- a/src/components/NoteList.test.tsx +++ b/src/components/NoteList.test.tsx @@ -28,6 +28,7 @@ const mockEntries: VaultEntry[] = [ }, icon: null, color: null, + order: null, }, { path: '/Users/luca/Laputa/note/facebook-ads-strategy.md', @@ -51,6 +52,7 @@ const mockEntries: VaultEntry[] = [ }, icon: null, color: null, + order: null, }, { path: '/Users/luca/Laputa/person/matteo-cellini.md', @@ -71,6 +73,7 @@ const mockEntries: VaultEntry[] = [ relationships: {}, icon: null, color: null, + order: null, }, { path: '/Users/luca/Laputa/event/2026-02-14-kickoff.md', @@ -91,6 +94,7 @@ const mockEntries: VaultEntry[] = [ relationships: {}, icon: null, color: null, + order: null, }, { path: '/Users/luca/Laputa/topic/software-development.md', @@ -111,6 +115,7 @@ const mockEntries: VaultEntry[] = [ relationships: {}, icon: null, color: null, + order: null, }, ] @@ -268,6 +273,7 @@ describe('getSortComparator', () => { relationships: {}, icon: null, color: null, + order: null, ...overrides, }) @@ -343,6 +349,7 @@ describe('NoteList sort controls', () => { relationships: {}, icon: null, color: null, + order: null, ...overrides, }) diff --git a/src/components/Sidebar.test.tsx b/src/components/Sidebar.test.tsx index dfc6d417..b5b187d5 100644 --- a/src/components/Sidebar.test.tsx +++ b/src/components/Sidebar.test.tsx @@ -35,6 +35,7 @@ const mockEntries: VaultEntry[] = [ relationships: {}, icon: null, color: null, + order: null, }, { path: '/vault/responsibility/grow-newsletter.md', @@ -55,6 +56,7 @@ const mockEntries: VaultEntry[] = [ relationships: {}, icon: null, color: null, + order: null, }, { path: '/vault/experiment/stock-screener.md', @@ -75,6 +77,7 @@ const mockEntries: VaultEntry[] = [ relationships: {}, icon: null, color: null, + order: null, }, { path: '/vault/procedure/weekly-essays.md', @@ -95,6 +98,7 @@ const mockEntries: VaultEntry[] = [ relationships: {}, icon: null, color: null, + order: null, }, { path: '/vault/topic/software-development.md', @@ -115,6 +119,7 @@ const mockEntries: VaultEntry[] = [ relationships: {}, icon: null, color: null, + order: null, }, { path: '/vault/topic/trading.md', @@ -135,6 +140,7 @@ const mockEntries: VaultEntry[] = [ relationships: {}, icon: null, color: null, + order: null, }, { path: '/vault/person/alice.md', @@ -155,6 +161,7 @@ const mockEntries: VaultEntry[] = [ relationships: {}, icon: null, color: null, + order: null, }, { path: '/vault/event/kickoff.md', @@ -175,6 +182,7 @@ const mockEntries: VaultEntry[] = [ relationships: {}, icon: null, color: null, + order: null, }, ] @@ -322,6 +330,7 @@ describe('Sidebar', () => { relationships: {}, icon: null, color: null, + order: null, }, { path: '/vault/type/book.md', @@ -342,6 +351,7 @@ describe('Sidebar', () => { relationships: {}, icon: null, color: null, + order: null, }, { path: '/vault/recipe/pasta.md', @@ -362,6 +372,7 @@ describe('Sidebar', () => { relationships: {}, icon: null, color: null, + order: null, }, ] @@ -410,6 +421,7 @@ describe('Sidebar', () => { relationships: {}, icon: null, color: null, + order: null, } render( {}} />) // "Projects" should appear once (the built-in section), not twice diff --git a/src/hooks/useNoteActions.ts b/src/hooks/useNoteActions.ts index 30ede554..479d7098 100644 --- a/src/hooks/useNoteActions.ts +++ b/src/hooks/useNoteActions.ts @@ -214,7 +214,7 @@ export function useNoteActions( aliases: [], belongsTo: [], relatedTo: [], status: noStatusTypes.has(type) ? null : 'Active', owner: null, cadence: null, archived: false, modifiedAt: now, createdAt: now, fileSize: 0, - snippet: '', relationships: {}, icon: null, color: null, + snippet: '', relationships: {}, icon: null, color: null, order: null, } const frontmatter = [ @@ -242,7 +242,7 @@ export function useNoteActions( aliases: [], belongsTo: [], relatedTo: [], status: null, owner: null, cadence: null, archived: false, modifiedAt: now, createdAt: now, fileSize: 0, - snippet: '', relationships: {}, icon: null, color: null, + snippet: '', relationships: {}, icon: null, color: null, order: null, } const content = `---\nIs A: Type\n---\n\n# ${typeName}\n\n` diff --git a/src/mock-tauri.ts b/src/mock-tauri.ts index c013e6f0..618e871a 100644 --- a/src/mock-tauri.ts +++ b/src/mock-tauri.ts @@ -449,6 +449,7 @@ AI agents are autonomous systems that can plan, execute, and adapt to achieve go // --- Type documents --- '/Users/luca/Laputa/type/project.md': `--- Is A: Type +order: 0 --- # Project @@ -462,6 +463,7 @@ A **time-bound initiative** that advances a [[type/responsibility|Responsibility `, '/Users/luca/Laputa/type/responsibility.md': `--- Is A: Type +order: 1 --- # Responsibility @@ -474,6 +476,7 @@ An **ongoing area of ownership** — something you're accountable for indefinite `, '/Users/luca/Laputa/type/procedure.md': `--- Is A: Type +order: 2 --- # Procedure @@ -488,6 +491,7 @@ A **recurring process** tied to a [[type/responsibility|Responsibility]]. Proced `, '/Users/luca/Laputa/type/experiment.md': `--- Is A: Type +order: 3 --- # Experiment @@ -500,6 +504,7 @@ A **hypothesis-driven investigation** with a clear test and measurable outcome. `, '/Users/luca/Laputa/type/person.md': `--- Is A: Type +order: 4 --- # Person @@ -511,6 +516,7 @@ A **person** you interact with — team members, collaborators, contacts. People `, '/Users/luca/Laputa/type/event.md': `--- Is A: Type +order: 5 --- # Event @@ -522,6 +528,7 @@ A **point-in-time occurrence** — meetings, launches, milestones. Events are li `, '/Users/luca/Laputa/type/topic.md': `--- Is A: Type +order: 6 --- # Topic @@ -533,6 +540,7 @@ A **subject area** for categorization. Topics group related notes, projects, and `, '/Users/luca/Laputa/type/essay.md': `--- Is A: Type +order: 7 --- # Essay @@ -544,6 +552,7 @@ A **published piece of writing** — newsletter essays, blog posts, articles. Es `, '/Users/luca/Laputa/type/note.md': `--- Is A: Type +order: 8 --- # Note @@ -683,6 +692,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ }, icon: null, color: null, + order: null, }, { path: '/Users/luca/Laputa/responsibility/grow-newsletter.md', @@ -712,6 +722,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ }, icon: null, color: null, + order: null, }, { path: '/Users/luca/Laputa/responsibility/manage-sponsorships.md', @@ -735,6 +746,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ }, icon: null, color: null, + order: null, }, { path: '/Users/luca/Laputa/procedure/write-weekly-essays.md', @@ -758,6 +770,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ }, icon: null, color: null, + order: null, }, { path: '/Users/luca/Laputa/procedure/run-sponsorships.md', @@ -781,6 +794,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ }, icon: null, color: null, + order: null, }, { path: '/Users/luca/Laputa/experiment/stock-screener.md', @@ -805,6 +819,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ }, icon: null, color: null, + order: null, }, { path: '/Users/luca/Laputa/note/facebook-ads-strategy.md', @@ -829,6 +844,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ }, icon: null, color: null, + order: null, }, { path: '/Users/luca/Laputa/note/budget-allocation.md', @@ -852,6 +868,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ }, icon: null, color: null, + order: null, }, { path: '/Users/luca/Laputa/person/matteo-cellini.md', @@ -874,6 +891,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ }, icon: null, color: null, + order: null, }, { path: '/Users/luca/Laputa/event/2026-02-14-laputa-app-kickoff.md', @@ -897,6 +915,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ }, icon: null, color: null, + order: null, }, { path: '/Users/luca/Laputa/topic/software-development.md', @@ -920,6 +939,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ }, icon: null, color: null, + order: null, }, { path: '/Users/luca/Laputa/topic/trading.md', @@ -943,6 +963,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ }, icon: null, color: null, + order: null, }, { path: '/Users/luca/Laputa/essay/on-writing-well.md', @@ -966,6 +987,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ }, icon: null, color: null, + order: null, }, { path: '/Users/luca/Laputa/essay/engineering-leadership-101.md', @@ -990,6 +1012,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ }, icon: null, color: null, + order: null, }, { path: '/Users/luca/Laputa/essay/ai-agents-primer.md', @@ -1013,6 +1036,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ }, icon: null, color: null, + order: null, }, // --- Type documents --- { @@ -1034,6 +1058,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ relationships: {}, icon: null, color: null, + order: 0, }, { path: '/Users/luca/Laputa/type/responsibility.md', @@ -1054,6 +1079,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ relationships: {}, icon: null, color: null, + order: 1, }, { path: '/Users/luca/Laputa/type/procedure.md', @@ -1074,6 +1100,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ relationships: {}, icon: null, color: null, + order: 2, }, { path: '/Users/luca/Laputa/type/experiment.md', @@ -1094,6 +1121,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ relationships: {}, icon: null, color: null, + order: 3, }, { path: '/Users/luca/Laputa/type/person.md', @@ -1114,6 +1142,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ relationships: {}, icon: null, color: null, + order: 4, }, { path: '/Users/luca/Laputa/type/event.md', @@ -1134,6 +1163,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ relationships: {}, icon: null, color: null, + order: 5, }, { path: '/Users/luca/Laputa/type/topic.md', @@ -1154,6 +1184,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ relationships: {}, icon: null, color: null, + order: 6, }, { path: '/Users/luca/Laputa/type/essay.md', @@ -1174,6 +1205,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ relationships: {}, icon: null, color: null, + order: 7, }, { path: '/Users/luca/Laputa/type/note.md', @@ -1194,6 +1226,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ relationships: {}, icon: null, color: null, + order: 8, }, // --- Custom type documents (user-created types) --- { @@ -1215,6 +1248,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ relationships: {}, icon: 'cooking-pot', color: 'orange', + order: 9, }, { path: '/Users/luca/Laputa/type/book.md', @@ -1235,6 +1269,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ relationships: {}, icon: 'book-open', color: 'green', + order: 10, }, // --- Instances of custom types --- { @@ -1258,6 +1293,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ }, icon: null, color: null, + order: null, }, { path: '/Users/luca/Laputa/book/designing-data-intensive-applications.md', @@ -1280,6 +1316,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ }, icon: null, color: null, + order: null, }, // --- Archived entries --- { @@ -1296,6 +1333,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ archived: true, icon: null, color: null, + order: null, modifiedAt: Date.now() / 1000 - 86400 * 120, createdAt: Date.now() / 1000 - 86400 * 200, fileSize: 680, @@ -1319,6 +1357,7 @@ const MOCK_ENTRIES: VaultEntry[] = [ archived: true, icon: null, color: null, + order: null, modifiedAt: Date.now() / 1000 - 86400 * 90, createdAt: Date.now() / 1000 - 86400 * 150, fileSize: 520, diff --git a/src/types.ts b/src/types.ts index 3bf8ec29..a571ea3b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -20,6 +20,8 @@ export interface VaultEntry { icon: string | null /** Accent color key for Type entries: "red" | "purple" | "blue" | "green" | "yellow" | "orange" */ color: string | null + /** Display order for Type entries in sidebar (lower = higher). null = use default order. */ + order: number | null } export interface GitCommit { From f805c7d1bfa7e7efed50446f2ed4ce8032e4aecd Mon Sep 17 00:00:00 2001 From: lucaronin Date: Sat, 21 Feb 2026 17:29:42 +0100 Subject: [PATCH 3/4] feat: draggable section groups in sidebar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Wrap sidebar section groups in @dnd-kit sortable context - Add grip-vertical drag handle visible on hover of section headers - Sort sections by `order` property from Type document entries - On drag end, compute new sequential order values and persist to each Type document's frontmatter via handleReorderSections - Add onReorderSections callback from Sidebar → App.tsx → vault Co-Authored-By: Claude Opus 4.6 --- src/App.tsx | 11 +++- src/components/Sidebar.tsx | 116 +++++++++++++++++++++++++++++++++---- 2 files changed, 114 insertions(+), 13 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 10265e39..24f126c3 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -112,6 +112,15 @@ function App() { vault.updateEntry(typeEntry.path, { icon, color }) }, [vault, notes]) + const handleReorderSections = useCallback((orderedTypes: { typeName: string; order: number }[]) => { + for (const { typeName, order } of orderedTypes) { + const typeEntry = vault.entries.find((e) => e.isA === 'Type' && e.title === typeName) + if (!typeEntry) continue + notes.handleUpdateFrontmatter(typeEntry.path, 'order', order) + vault.updateEntry(typeEntry.path, { order }) + } + }, [vault, notes]) + useAppKeyboard({ onQuickOpen: () => setShowQuickOpen(true), onCreateNote: openCreateDialog, @@ -161,7 +170,7 @@ function App() {
- setShowCommitDialog(true)} /> + setShowCommitDialog(true)} />
diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index 7bc27cda..dd273aa9 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -1,10 +1,26 @@ import { useState, useMemo, useRef, useEffect, useCallback, memo, type ComponentType } from 'react' import type { VaultEntry, SidebarSelection } from '../types' import { cn } from '@/lib/utils' -import { ChevronRight, ChevronDown, GitCommitHorizontal, Plus, SlidersHorizontal } from 'lucide-react' +import { ChevronRight, ChevronDown, GitCommitHorizontal, Plus, SlidersHorizontal, GripVertical } from 'lucide-react' import { getTypeColor, getTypeLightColor } from '../utils/typeColors' import { resolveIcon, TypeCustomizePopover } from './TypeCustomizePopover' import { useSectionVisibility } from '../hooks/useSectionVisibility' +import { + DndContext, + closestCenter, + KeyboardSensor, + PointerSensor, + useSensor, + useSensors, + type DragEndEvent, +} from '@dnd-kit/core' +import { + SortableContext, + sortableKeyboardCoordinates, + useSortable, + verticalListSortingStrategy, +} from '@dnd-kit/sortable' +import { CSS } from '@dnd-kit/utilities' import { FileText, Star, @@ -30,6 +46,7 @@ interface SidebarProps { onCreateType?: (type: string) => void onCreateNewType?: () => void onCustomizeType?: (typeName: string, icon: string, color: string) => void + onReorderSections?: (orderedTypes: { typeName: string; order: number }[]) => void modifiedCount?: number onCommitPush?: () => void } @@ -59,7 +76,7 @@ const BUILT_IN_SECTION_GROUPS: SectionGroup[] = [ const BUILT_IN_TYPES = new Set(BUILT_IN_SECTION_GROUPS.map((s) => s.type)) -export const Sidebar = memo(function Sidebar({ entries, selection, onSelect, onSelectNote, onCreateType, onCreateNewType, onCustomizeType, modifiedCount = 0, onCommitPush }: SidebarProps) { +export const Sidebar = memo(function Sidebar({ entries, selection, onSelect, onSelectNote, onCreateType, onCreateNewType, onCustomizeType, onReorderSections, modifiedCount = 0, onCommitPush }: SidebarProps) { const [collapsed, setCollapsed] = useState>({}) const [customizeTarget, setCustomizeTarget] = useState(null) const [contextMenuPos, setContextMenuPos] = useState<{ x: number; y: number } | null>(null) @@ -130,11 +147,47 @@ export const Sidebar = memo(function Sidebar({ entries, selection, onSelect, onS }) }, [typeEntryMap]) - const allSectionGroups = useMemo( - () => [...builtInWithOverrides, ...customSectionGroups], - [builtInWithOverrides, customSectionGroups], + // Merge built-in and custom sections, then sort by order from type entries + const allSectionGroups = useMemo(() => { + const merged = [...builtInWithOverrides, ...customSectionGroups] + return merged.sort((a, b) => { + const orderA = typeEntryMap[a.type]?.order ?? Infinity + const orderB = typeEntryMap[b.type]?.order ?? Infinity + if (orderA !== orderB) return orderA - orderB + return a.label.localeCompare(b.label) + }) + }, [builtInWithOverrides, customSectionGroups, typeEntryMap]) + + // DnD sensors with activation distance to avoid accidental drags on click + const sensors = useSensors( + useSensor(PointerSensor, { activationConstraint: { distance: 5 } }), + useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }), ) + const visibleSections = useMemo( + () => allSectionGroups.filter((g) => isSectionVisible(g.type)), + [allSectionGroups, isSectionVisible], + ) + + const sectionIds = useMemo(() => visibleSections.map((g) => g.type), [visibleSections]) + + const handleDragEnd = useCallback((event: DragEndEvent) => { + const { active, over } = event + if (!over || active.id === over.id) return + + const oldIndex = sectionIds.indexOf(active.id as string) + const newIndex = sectionIds.indexOf(over.id as string) + if (oldIndex === -1 || newIndex === -1) return + + // Compute new order: assign sequential order values to the reordered list + const reordered = [...sectionIds] + reordered.splice(oldIndex, 1) + reordered.splice(newIndex, 0, active.id as string) + + const updates = reordered.map((typeName, i) => ({ typeName, order: i })) + onReorderSections?.(updates) + }, [sectionIds, onReorderSections]) + const archivedCount = useMemo(() => entries.filter((e) => e.archived).length, [entries]) // Close context menu on outside click @@ -191,7 +244,7 @@ export const Sidebar = memo(function Sidebar({ entries, selection, onSelect, onS } }, [customizeTarget, typeEntryMap, onCustomizeType]) - const renderSection = ({ label, type, Icon, customColor }: SectionGroup) => { + const renderSectionContent = ({ label, type, Icon, customColor }: SectionGroup, dragHandleProps?: Record) => { const items = entries.filter((e) => e.isA === type && !e.archived) const isCollapsed = collapsed[type] ?? true const isTopic = type === 'Topic' @@ -209,7 +262,7 @@ export const Sidebar = memo(function Sidebar({ entries, selection, onSelect, onS } return ( -
+ <> {/* Section header row */}
onSelect({ kind: 'sectionGroup', type })} onContextMenu={(e) => handleContextMenu(e, type)} > -
+
+ {/* Drag handle */} +
+ +
- {label} + {label}
{(onCreateType || (isTypeSection && onCreateNewType)) && ( @@ -280,6 +342,30 @@ export const Sidebar = memo(function Sidebar({ entries, selection, onSelect, onS ))}
)} + + ) + } + + function SortableSection({ group }: { group: SectionGroup }) { + const { + attributes, + listeners, + setNodeRef, + transform, + transition, + isDragging, + } = useSortable({ id: group.type }) + + const style = { + transform: CSS.Transform.toString(transform), + transition, + opacity: isDragging ? 0.5 : 1, + padding: '4px 6px', + } + + return ( +
+ {renderSectionContent(group, listeners)}
) } @@ -428,8 +514,14 @@ export const Sidebar = memo(function Sidebar({ entries, selection, onSelect, onS )}
- {/* Section Groups (built-in + custom), filtered by visibility */} - {allSectionGroups.filter((g) => isSectionVisible(g.type)).map(renderSection)} + {/* Section Groups (built-in + custom), filtered by visibility, sortable by drag */} + + + {visibleSections.map((g) => ( + + ))} + + {/* Commit button — always visible */} From a10589fb6c7125e166bd5e34114c31f0fc25cef7 Mon Sep 17 00:00:00 2001 From: lucaronin Date: Sat, 21 Feb 2026 17:33:36 +0100 Subject: [PATCH 4/4] fix: sidebar collapse toggle and update tests for DnD - Fix toggleSection to account for default collapsed state (collapsed[type] ?? true, not just !prev[type]) - Update tests to expand sections before asserting item visibility (sections start collapsed by default) - Add tests for section ordering by Type entry order property - Add test for drag handle rendering on section headers Co-Authored-By: Claude Opus 4.6 --- src/components/Sidebar.test.tsx | 103 ++++++++++++++++++++++++++------ src/components/Sidebar.tsx | 2 +- 2 files changed, 85 insertions(+), 20 deletions(-) diff --git a/src/components/Sidebar.test.tsx b/src/components/Sidebar.test.tsx index b5b187d5..b4e89eb7 100644 --- a/src/components/Sidebar.test.tsx +++ b/src/components/Sidebar.test.tsx @@ -207,34 +207,45 @@ describe('Sidebar', () => { expect(screen.getByText('Types')).toBeInTheDocument() }) - it('shows entity names under their section groups', () => { + it('shows entity names under their section groups after expanding', () => { render( {}} />) + // Sections start collapsed by default — expand them first + fireEvent.click(screen.getByLabelText('Expand Projects')) + fireEvent.click(screen.getByLabelText('Expand Responsibilities')) + fireEvent.click(screen.getByLabelText('Expand Experiments')) + fireEvent.click(screen.getByLabelText('Expand Procedures')) expect(screen.getByText('Build Laputa App')).toBeInTheDocument() expect(screen.getByText('Grow Newsletter')).toBeInTheDocument() expect(screen.getByText('Stock Screener')).toBeInTheDocument() expect(screen.getByText('Write Weekly Essays')).toBeInTheDocument() }) - it('shows People and Events as section groups', () => { + it('shows People and Events items after expanding', () => { render( {}} />) + fireEvent.click(screen.getByLabelText('Expand People')) + fireEvent.click(screen.getByLabelText('Expand Events')) expect(screen.getByText('Alice')).toBeInTheDocument() expect(screen.getByText('Kickoff Meeting')).toBeInTheDocument() }) it('collapses and expands sections', () => { render( {}} />) - expect(screen.getByText('Build Laputa App')).toBeInTheDocument() - - fireEvent.click(screen.getByLabelText('Collapse Projects')) + // Start collapsed — items hidden expect(screen.queryByText('Build Laputa App')).not.toBeInTheDocument() + // Expand fireEvent.click(screen.getByLabelText('Expand Projects')) expect(screen.getByText('Build Laputa App')).toBeInTheDocument() + + // Collapse + fireEvent.click(screen.getByLabelText('Collapse Projects')) + expect(screen.queryByText('Build Laputa App')).not.toBeInTheDocument() }) it('calls onSelect when clicking an entity', () => { const onSelect = vi.fn() render() + fireEvent.click(screen.getByLabelText('Expand Projects')) fireEvent.click(screen.getByText('Build Laputa App')) expect(onSelect).toHaveBeenCalledWith({ kind: 'entity', @@ -262,9 +273,10 @@ describe('Sidebar', () => { }) }) - it('renders Topics section with topic entries', () => { + it('renders Topics section with topic entries after expanding', () => { render( {}} />) expect(screen.getByText('Topics')).toBeInTheDocument() + fireEvent.click(screen.getByLabelText('Expand Topics')) expect(screen.getByText('Software Development')).toBeInTheDocument() expect(screen.getByText('Trading')).toBeInTheDocument() }) @@ -272,6 +284,7 @@ describe('Sidebar', () => { it('calls onSelect with topic kind when clicking a topic', () => { const onSelect = vi.fn() render() + fireEvent.click(screen.getByLabelText('Expand Topics')) fireEvent.click(screen.getByText('Software Development')) expect(onSelect).toHaveBeenCalledWith({ kind: 'topic', @@ -382,8 +395,9 @@ describe('Sidebar', () => { expect(screen.getByText('Recipes')).toBeInTheDocument() }) - it('shows instances of custom types under their section', () => { + it('shows instances of custom types under their section after expanding', () => { render( {}} onCreateType={() => {}} />) + fireEvent.click(screen.getByLabelText('Expand Recipes')) expect(screen.getByText('Pasta Carbonara')).toBeInTheDocument() }) @@ -451,15 +465,17 @@ describe('Sidebar', () => { it('hides a section when its toggle is clicked off', () => { render( {}} />) - // People section should be visible initially - expect(screen.getByText('Alice')).toBeInTheDocument() + // People section header should be visible initially + expect(screen.getByText('People')).toBeInTheDocument() // Open customize popover and toggle People off fireEvent.click(screen.getByTitle('Customize sections')) fireEvent.click(screen.getByLabelText('Toggle People')) - // People section and its items should be gone - expect(screen.queryByText('Alice')).not.toBeInTheDocument() + // People section header should be gone (use getAllByText to handle popover) + const peopleElements = screen.queryAllByText('People') + // Only the toggle label in the popover should remain, not the section header + expect(peopleElements.length).toBeLessThanOrEqual(1) }) it('re-shows a section when its toggle is clicked on again', () => { @@ -468,11 +484,12 @@ describe('Sidebar', () => { // Hide People fireEvent.click(screen.getByTitle('Customize sections')) fireEvent.click(screen.getByLabelText('Toggle People')) - expect(screen.queryByText('Alice')).not.toBeInTheDocument() // Show People again fireEvent.click(screen.getByLabelText('Toggle People')) - expect(screen.getByText('Alice')).toBeInTheDocument() + // People section should be visible again — popover toggle + section header = 2 "People" texts + const peopleElements = screen.getAllByText('People') + expect(peopleElements.length).toBe(2) }) it('persists hidden sections in localStorage', () => { @@ -490,13 +507,13 @@ describe('Sidebar', () => { localStorage.setItem('laputa-hidden-sections', JSON.stringify(['Person', 'Event'])) render( {}} />) - // People and Events sections should be hidden - expect(screen.queryByText('Alice')).not.toBeInTheDocument() - expect(screen.queryByText('Kickoff Meeting')).not.toBeInTheDocument() + // People and Events section headers should be hidden + expect(screen.queryByText('People')).not.toBeInTheDocument() + expect(screen.queryByText('Events')).not.toBeInTheDocument() - // Other sections should still be visible - expect(screen.getByText('Build Laputa App')).toBeInTheDocument() - expect(screen.getByText('Software Development')).toBeInTheDocument() + // Other section headers should still be visible + expect(screen.getByText('Projects')).toBeInTheDocument() + expect(screen.getByText('Topics')).toBeInTheDocument() }) it('does not affect All Notes or other sidebar filters when sections are hidden', () => { @@ -522,4 +539,52 @@ describe('Sidebar', () => { expect(screen.queryByText('Show in sidebar')).not.toBeInTheDocument() }) }) + + describe('section ordering by type order property', () => { + const entriesWithOrder: VaultEntry[] = [ + ...mockEntries, + // Type entries with order values — reversed from default + { + path: '/vault/type/project.md', filename: 'project.md', title: 'Project', isA: 'Type', + aliases: [], belongsTo: [], relatedTo: [], status: null, owner: null, cadence: null, + archived: false, modifiedAt: 1700000000, createdAt: null, fileSize: 200, snippet: '', + relationships: {}, icon: null, color: null, order: 5, + }, + { + path: '/vault/type/topic.md', filename: 'topic.md', title: 'Topic', isA: 'Type', + aliases: [], belongsTo: [], relatedTo: [], status: null, owner: null, cadence: null, + archived: false, modifiedAt: 1700000000, createdAt: null, fileSize: 200, snippet: '', + relationships: {}, icon: null, color: null, order: 0, + }, + { + path: '/vault/type/person.md', filename: 'person.md', title: 'Person', isA: 'Type', + aliases: [], belongsTo: [], relatedTo: [], status: null, owner: null, cadence: null, + archived: false, modifiedAt: 1700000000, createdAt: null, fileSize: 200, snippet: '', + relationships: {}, icon: null, color: null, order: 1, + }, + ] + + it('sorts sections by order from Type entries', () => { + render( {}} />) + // Get all section header labels + const headers = screen.getAllByText(/^(Topics|People|Projects|Experiments|Responsibilities|Procedures|Events|Types)$/) + const labels = headers.map((el) => el.textContent) + + // Topics (order: 0) and People (order: 1) should come before Projects (order: 5) + const topicsIdx = labels.indexOf('Topics') + const peopleIdx = labels.indexOf('People') + const projectsIdx = labels.indexOf('Projects') + + expect(topicsIdx).toBeLessThan(projectsIdx) + expect(peopleIdx).toBeLessThan(projectsIdx) + expect(topicsIdx).toBeLessThan(peopleIdx) + }) + + it('renders drag handle on section headers', () => { + render( {}} />) + const dragHandles = screen.getAllByLabelText(/^Drag to reorder/) + // Should have one drag handle per visible section group + expect(dragHandles.length).toBeGreaterThan(0) + }) + }) }) diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index dd273aa9..32de58ee 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -100,7 +100,7 @@ export const Sidebar = memo(function Sidebar({ entries, selection, onSelect, onS }, [showCustomize]) const toggleSection = (type: string) => { - setCollapsed((prev) => ({ ...prev, [type]: !prev[type] })) + setCollapsed((prev) => ({ ...prev, [type]: !(prev[type] ?? true) })) } // Build a map of type name → type entry for quick lookup of icon/color