{"id":13398578,"url":"https://github.com/davedawkins/sutil-oxide","last_synced_at":"2025-10-08T22:07:55.329Z","repository":{"id":133632420,"uuid":"544945062","full_name":"davedawkins/sutil-oxide","owner":"davedawkins","description":"A toolkit for building IDE-style web applications, using Sutil.","archived":false,"fork":false,"pushed_at":"2025-03-19T21:03:38.000Z","size":7153,"stargazers_count":19,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-19T22:22:11.066Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://davedawkins.github.io/sutil-oxide/","language":"F#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/davedawkins.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-03T14:08:00.000Z","updated_at":"2025-03-19T21:03:41.000Z","dependencies_parsed_at":"2023-10-12T08:16:39.503Z","dependency_job_id":"5e314a28-8b35-4117-8f31-404421254583","html_url":"https://github.com/davedawkins/sutil-oxide","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davedawkins%2Fsutil-oxide","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davedawkins%2Fsutil-oxide/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davedawkins%2Fsutil-oxide/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davedawkins%2Fsutil-oxide/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/davedawkins","download_url":"https://codeload.github.com/davedawkins/sutil-oxide/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244538579,"owners_count":20468741,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T19:00:28.821Z","updated_at":"2025-10-08T22:07:50.299Z","avatar_url":"https://github.com/davedawkins.png","language":"F#","funding_links":[],"categories":["Sample Apps"],"sub_categories":[],"readme":"# Sutil Oxide\n\nA toolkit for building IDE-style web applications, using [Sutil](https://sutil.dev).\n\n## Demo\n\nThe demo is best viewed on desktop, though it does try and be basically responsive.\n\nClick on the `Help` button for details on how the [demo](https://davedawkins.github.io/sutil-oxide/) works. Repository located at [https://github.com/davedawkins/sutil-oxide](https://github.com/davedawkins/sutil-oxide).\n\n## Motivation\n\nMy own projects frequently need a UI toolkit, and my latest project needed dockable windows. Sutil Oxide is intended to be where I develop any reusable UI code and components.\n\n## Status\nVery much still in development. My focus is on the main project that consumes this toolkit, and so I add functionality, make fixes etc as and when I need to according to the needs of that driving project. In fact, mostly I'm refactoring out of the main project into this toolkit.\n\nThe main reason you're seeing it at this early stage is that I wanted to contribute to the F# Advent, and a couple of people I'd already shown it to thought it was cool in its own right.\n\nYou will find many niggles and annoyances, but nonetheless I've found it valuable for getting my main project off the ground. I can more easily focus on the business logic and then categorise issues as either being UI/presentation or application based. It's a useful separation.\n\n## Scope\n\nAny reusable UI component that might be generally useful for other Sutil projects. It may be possible to wrap as `web components`, such that non-Sutil projects can use this toolkit.\n\n## Features\n\n- 9 docking locations\n- Resizable panes\n- Drag and drop pane's tab to relocate panes\n- Also relocate panes with \"cog\" drop-down menu\n- Minimize pane with \"-\" button or click on tab\n- Theming support\n- Functionally reactive thanks to [Sutil](https://sutil.dev)\n- Toolbar\n- Statusbar\n- File Explorer (and basic IFileSystem interface with LocalStorage implementation)\n\n## Issues\n- No drag *to* centre pane. Use \"cog\" menu to send panes to centre\n- Submenu placement janky, would prefer a CSS-only solution but may have to resort to code\n- No persistence of layout\n- Very basic mobile support, currently best experience desktop\n\n## Docking Layout\n\n```\n+-----------------------------+---------------------------+\n| TopLeft                     |                  TopRight |\n+------------+----------------+-------------+-------------+\n| LeftTop    |                              |    RightTop |\n|            |          CentreCentre        |             |\n|            |                              |             |\n+------------+                              +-------------+\n| LeftBottom |                              | RightBottom |\n|            |                              |             |\n|            |                              |             |\n+------------+----------------+-------------+-------------+\n| BottomLeft                  |               BottomRight |\n+-----------------------------+---------------------------+\n```\n\n## Creating a Dock Layout\n\nSee `src/App/App.fs` for a full example.\n\n```fs\n    open SutilOxide\n    open SutilOxide.Dock\n    open SutilOxide.Types\n\n    let initPanes (dc : DockContainer) =\n        dc.AddPane( \"Test\", LeftTop, Html.div \"This is the Test pane\" )\n        dc.AddPane( \"Main\", CentreCentre, Html.div \"This is the Main pane\" )\n\n\n    let mainView() =\n        Html.div [\n            Attr.className \"main-container\"\n            DockContainer.Create initPanes\n        ]\n```\n\n## Top-level Styling\n\nA suggested style for `div.main-container`:\n\n```css\n    .dock-container {\n        /* Occupy all of browser viewport */\n        height: 100vh;\n        width: 100vw;\n    }\n```\n\nYou can either use a regular `main.css` file for this, or apply the style within Sutil:\n\nUsing inline styles:\n\n```fs\n\n    open type Feliz.length\n\n    // 1. Apply style inline\n\n    let mainView() =\n        Html.div [\n            Attr.style [\n                Css.width (vw 100)\n                Css.height (vh 100)\n            ]\n            DockContainer.Create initPanes\n        ]\n```\n\nor using `withStyle` to apply a private stylesheet:\n\n```fs\n    open Sutil.Style\n    open type Feliz.length\n\n    let mainStyle = [\n        rule \".main-container\" [\n            Css.width (vw 100)\n            Css.height (vh 100)\n        ]\n    ]\n\n    let mainView() =\n        Html.div [\n            Attr.className \"main-container\"\n            DockContainer.Create initPanes\n        ] |\u003e withStyle mainStyle\n```\n\nIf you plan to add a toolbar or a statusbar then you may want to make the top-level div into a `flex column`:\n\n```fs\n    open Sutil.Style\n    open type Feliz.length\n\n    let mainStyle = [\n        rule \".main-container\" [\n            Css.width (vw 100)\n            Css.height (vh 100)\n            Css.displayFlex\n            Css.flexDirectionColumn\n        ]\n    ]\n\n    let mainView() =\n        Html.div [\n            Attr.className \"main-container\"\n            DockContainer.Create initPanes\n        ] |\u003e withStyle mainStyle\n```\n\n## Adding Panes\n\nMethod `AddPane` takes the following arguments:\n\n```fs\n    member _.AddPane (name : string, initLoc : DockLocation, content : SutilElement )\n```\n\n- Name of pane, as a `string`. This should be unique, and will also be the default label shown in the pane header\n- Initial location of pane, as a `DockLocation` (see below)\n- Pane content, as a `SutilElement`\n\n\nAnother overload of `AddPane` will allow the header to be given as a `SutilElement`:\n\n```fs\n    member __.AddPane (name : string, initLoc : DockLocation, header : SutilElement, content : SutilElement, show : bool ) =\n```\n\nParameters are as before, but with the addition of `show : bool`:\n- Initial visibility of pane as a boolean\n\nAnother overload of `AddPane` will allow the header to be given as a `SutilElement`:\n\n```fs\n    member __.AddPane (name : string, initLoc : DockLocation, header : SutilElement, content : SutilElement, show : bool ) =\n```\n\nParameters are as before, but with the addition of `header : SutilElement`:\n\n- Content of header, as a `SutilElement`.\n\nPossible dock locations are defined by `DockLocation`:\n\n```fs\ntype DockLocation =\n    | LeftTop\n    | LeftBottom\n    | BottomLeft\n    | CentreCentre\n    | BottomRight\n    | RightTop\n    | RightBottom\n    | TopLeft\n    | TopRight\n```\n\n...more to come","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavedawkins%2Fsutil-oxide","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavedawkins%2Fsutil-oxide","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavedawkins%2Fsutil-oxide/lists"}