From 25afad58b0bc2ee16d9ae50f080e82f005d4f604 Mon Sep 17 00:00:00 2001
From: timea-solid <4144203+timea-solid@users.noreply.github.com>
Date: Mon, 23 Mar 2026 10:43:30 +0100
Subject: [PATCH 1/3] moved some css variables up
---
dev/dev-light.css | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/dev/dev-light.css b/dev/dev-light.css
index 59d69a0a..fd162b2e 100644
--- a/dev/dev-light.css
+++ b/dev/dev-light.css
@@ -10,7 +10,7 @@
:root {
/* Background and Text */
--color-background: white;
- --color-text: ##1A1A1A;
+ --color-text: #1A1A1A;
--color-text-secondary: #666;
--color-text-light: #aaa;
--color-text-link: #3B5998;
@@ -29,6 +29,7 @@
--color-border-darker: #444;
--color-border-light: #aaa;
--color-border-pale: #eee;
+ --color-border-accent: #88c;
/* Status Colors */
--color-selected-bg: #8F3;
@@ -138,16 +139,23 @@
/* Spacing and Sizing */
--spacing-tiny: 0.05em;
--spacing-small: 0.1em;
+ --spacing-xxxs: 0.2em;
+ --spacing-xxs: 0.3em;
--spacing-xs: 0.5rem;
--spacing-sm: 0.75em;
+ --spacing-btn: 0.7em;
--spacing-base: 0.5em;
--spacing-md: 1em;
--spacing-lg: 1.5em;
--spacing-xl: 2em;
--spacing-2xl: 3em;
+ --border-width-xthin: 0.05em;
+ --border-width-sm: 0.1em;
--border-width-thin: 1px;
--border-width-medium: 2px;
--border-width-bold: 5px;
+ --border-radius-xs: 0.1em;
+ --border-radius-sm: 0.2em;
--border-radius-base: 0.5em;
--border-radius-lg: 0.75em;
--border-radius-full: 1em;
@@ -170,6 +178,12 @@
/* Shadows */
--box-shadow: 0 2px 8px rgba(124,77,255,0.08);
--box-shadow-sm: 0 1px 4px rgba(124,77,255,0.12);
+ --box-shadow-active: 0 1px 2px rgba(124, 77, 255, 0.2);
+ --box-shadow-focus: 0 0 0 5px rgba(124, 77, 255, 0.25);
+ --box-shadow-hover: 0 2px 4px rgba(124, 77, 255, 0.2);
+ --box-shadow-modal: 0 2px 10px rgba(0, 0, 0, 0.3);
+ --box-shadow-overlay: 0 4px 24px rgba(0, 0, 0, 0.2);
+ --box-shadow-popup: 0 0.5em 0.9em rgba(0, 0, 0, 0.2);
/* Accessibility */
--min-touch-target: 44px;
@@ -183,11 +197,13 @@
/* Overlay and Modal */
--overlay-bg: rgba(0, 0, 0, 0.5);
+ --overlay-bg-muted: rgba(0, 0, 0, 0.3);
--z-index-modal: 9999;
--z-index-skip-links: 1000;
/* Opacity */
--opacity-disabled: 0.6;
+ --opacity-input-disabled: 0.75;
/* Layout Values */
--max-width-readable: 65ch;
From 57056d454f25092bb1a853a4985f2a540b18cebf Mon Sep 17 00:00:00 2001
From: timea-solid <4144203+timea-solid@users.noreply.github.com>
Date: Tue, 24 Mar 2026 12:35:29 +0100
Subject: [PATCH 2/3] improved local dev
---
tsconfig.dev.json | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/tsconfig.dev.json b/tsconfig.dev.json
index 8a4f7fa3..1a84cca6 100644
--- a/tsconfig.dev.json
+++ b/tsconfig.dev.json
@@ -1,7 +1,14 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
- "rootDir": "."
+ "rootDir": ".",
+ "baseUrl": ".",
+ "preserveSymlinks": true,
+ "paths": {
+ "rdflib": ["node_modules/rdflib"],
+ "solid-logic": ["node_modules/solid-logic"],
+ "solid-ui": ["node_modules/solid-ui"]
+ }
},
"include": ["dev/index.ts", "dev/**/*.ts", "typings/**/*"]
}
From 4f2c7e026a8c722404afb6c153f227d8362e4eb6 Mon Sep 17 00:00:00 2001
From: timea-solid <4144203+timea-solid@users.noreply.github.com>
Date: Tue, 24 Mar 2026 13:27:24 +0100
Subject: [PATCH 3/3] new outine structure, ts ignores
---
README.md | 8 ++
dev/dev-mash.css | 134 +++++++++++++++-----------
dev/loader.ts | 14 ++-
package-lock.json | 2 +
src/dashboard/basicPreferences.ts | 1 +
src/internal/internalPane.ts | 1 +
src/outline/context.ts | 2 +
src/outline/manager.js | 38 ++++----
src/outline/userInput.js | 7 +-
src/pad/padPane.ts | 3 +
src/tabbed/tabbedPane.ts | 2 +
test/unit/meeting/Schedule/index.html | 20 +++-
12 files changed, 153 insertions(+), 79 deletions(-)
diff --git a/README.md b/README.md
index ef5f4287..5b29d99d 100644
--- a/README.md
+++ b/README.md
@@ -78,3 +78,11 @@ contacts (A VCARD Address Book, Group, Individual, Organization) can be handled
pane. Any other pane which wants to deal with contacts can just use the pane within its own user interface.

+
+
+## Generative AI usage
+The SolidOS team is using GitHub Copilot integrated in Visual Studio Code.
+We have added comments in the code to make it explicit which parts are 100% written by AI.
+
+### Prompt usage hitory:
+* Model Claude Opus 4.6: Initially solid-panes is loaded into a HTML shell form mashlib that looks like ... Also, an iFrame is rendered inside the
for “isolated pane rendering”. Analize the solid-panes code for what it uses from this HTML and suggest a new HTML structure which is mobile and accessibility friendly. Lets go ahead and make chnages in this code as suggested to accommodate the new databwroser HTML.
diff --git a/dev/dev-mash.css b/dev/dev-mash.css
index 8aa75274..8b36eea0 100644
--- a/dev/dev-mash.css
+++ b/dev/dev-mash.css
@@ -8,74 +8,46 @@
@import url("./dev-light.css");
@import url("./dev-mash-utilities.css");
-/* I couldn't find the code for the collapse image. this is a quick work around
-to make the collapsing easier to use ( the triangles dont jump 20 pixels). ~cm2
-*/
-img[title="Hide details."] {
- float: left;
-}
-
-html {
- height: 100%;
- line-height: 1.15;
-}
-body {
- height: 100%;
- background-color: var(--color-background);
- color: var(--color-text);
+html, body {
+ margin: 0;
+ padding: 0;
font-family: var(--font-family-base);
-}
-
-/* Improved heading hierarchy */
-h1, h2, h3, h4, h5, h6 {
- color: var(--color-primary);
- font-weight: 600;
- line-height: var(--line-height-tight);
- margin-top: 0;
- margin-bottom: var(--spacing-sm);
-}
-
-h1 { font-size: 2em; } /* 32px */
-h2 { font-size: 1.5em; } /* 24px */
-h3 { font-size: 1.25em; } /* 20px */
-h4 { font-size: 1.125em; }/* 18px */
-h5, h6 { font-size: 1em; }/* 16px */
-
-/* Better paragraph spacing */
-p {
- margin-bottom: var(--spacing-md);
+ font-size: var(--font-size-base);
line-height: var(--line-height-base);
- max-width: 65ch; /* Optimal reading width */
-}
-
-/* Improved link accessibility */
-a {
- color: var(--color-primary);
- text-decoration: underline;
- text-underline-offset: 0.125em;
- text-decoration-thickness: 0.0625em;
-}
-
-a:hover, a:focus {
- text-decoration-thickness: 0.125em;
+ background: var(--color-background);
+ color: var(--color-text);
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ text-rendering: optimizeLegibility;
}
-
-/* Main page elements in databrowser.html */
-#PageBody {
+/* ── App layout ── */
+body {
display: flex;
flex-direction: column;
+ min-height: 100dvh; /* dvh = dynamic viewport for mobile chrome */
}
-#DummyUUID {
- flex: 1 0 auto;
-}
+
#PageHeader {
+ position: sticky;
+ top: 0;
+ z-index: 100;
flex-shrink: 0;
}
+
+#MainContent {
+ flex: 1 1 auto;
+ overflow-y: auto;
+ -webkit-overflow-scrolling: touch; /* smooth iOS scroll */
+ padding: clamp(0.5rem, 2vw, 1.5rem); /* responsive gutter */
+ container-type: inline-size; /* enable @container queries */
+}
+
#PageFooter {
flex-shrink: 0;
}
+
.warning {
color: var(--color-warning);
}
@@ -83,6 +55,7 @@ a:hover, a:focus {
background-color: var(--color-selected-bg);
}
+/* used in profile-pane as success button */
.licOkay {
background-color: var(--color-success-bg);
}
@@ -1409,3 +1382,56 @@ End of styles for tableViewPane
-moz-box-shadow: $x-axis $y-axis $blur $color;
-o-box-shadow: $x-axis $y-axis $blur $color;
}
+
+/* Generated by AI */
+@media screen and (max-width: 768px) {
+ #PageHeader,
+ #PageFooter {
+ width: 100%;
+ }
+
+ #MainContent {
+ padding-top: 0.75rem;
+ padding-right: max(0.75rem, env(safe-area-inset-right));
+ padding-bottom: max(0.75rem, env(safe-area-inset-bottom));
+ padding-left: max(0.75rem, env(safe-area-inset-left));
+ }
+
+ .TabulatorOutline,
+ .outline-view {
+ overflow-x: auto;
+ -webkit-overflow-scrolling: touch;
+ }
+
+ .TabulatorOutline table,
+ .outline-view table {
+ min-width: 100%;
+ }
+
+ img.outlineImage,
+ img.pic,
+ img.foafPic {
+ height: auto;
+ max-width: 100%;
+ }
+
+ div.description,
+ div.premises,
+ div.justification,
+ div.mildNotice {
+ box-sizing: border-box;
+ margin-left: 0;
+ margin-right: 0;
+ width: 100%;
+ }
+}
+
+html[data-layout="mobile"] #PageBody {
+ min-height: var(--app-height, 100dvh);
+}
+
+html[data-layout="mobile"] #MainContent {
+ overscroll-behavior-x: contain;
+}
+
+/* END of Generated by AI */
\ No newline at end of file
diff --git a/dev/loader.ts b/dev/loader.ts
index 207e35db..eb9f3106 100644
--- a/dev/loader.ts
+++ b/dev/loader.ts
@@ -5,6 +5,7 @@ import { solidLogicSingleton, store, authSession } from 'solid-logic'
import { getOutliner } from '../src'
import Pane from 'profile-pane'
import './dev-mash.css'
+import { DataBrowserContext, RenderEnvironment } from 'pane-registry'
// Add custom properties to the Window interface for TypeScript
declare global {
@@ -27,7 +28,15 @@ async function renderPane (uri: string) {
await new Promise((resolve, reject) => {
store.fetcher.load(doc).then(resolve, reject)
})
- const context = {
+
+ const devEnvironment : RenderEnvironment = {
+ layout: 'desktop', // or 'mobile'
+ layoutPreference: 'desktop', // or 'mobile' or 'auto'
+ inputMode: 'pointer', // or 'touch'
+ theme: 'light', // or 'dark'
+ viewport: { width: 800, height: 480 } // this is the default viewport for the browser window
+ }
+ const context : DataBrowserContext = {
// see https://github.com/solidos/solid-panes/blob/005f90295d83e499fd626bd84aeb3df10135d5c1/src/index.ts#L30-L34
dom: document,
getOutliner,
@@ -35,7 +44,8 @@ async function renderPane (uri: string) {
store: store,
paneRegistry,
logic: solidLogicSingleton
- }
+ },
+ environment: devEnvironment
}
console.log(subject, context)
diff --git a/package-lock.json b/package-lock.json
index b3ea07eb..43f6a383 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5735,6 +5735,8 @@
},
"node_modules/copy-webpack-plugin": {
"version": "13.0.1",
+ "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-13.0.1.tgz",
+ "integrity": "sha512-J+YV3WfhY6W/Xf9h+J1znYuqTye2xkBUIGyTPWuBAT27qajBa5mR4f8WBmfDY3YjRftT2kqZZiLi1qf0H+UOFw==",
"dev": true,
"license": "MIT",
"dependencies": {
diff --git a/src/dashboard/basicPreferences.ts b/src/dashboard/basicPreferences.ts
index 5523d220..2b40e1b1 100644
--- a/src/dashboard/basicPreferences.ts
+++ b/src/dashboard/basicPreferences.ts
@@ -15,6 +15,7 @@ export const basicPreferencesPane: PaneDefinition = {
// The subject should be the logged in user.
render: (subject, context) => {
const dom = context.dom
+ // @ts-ignore
const store = context.session.store as Store
function complainIfBad (ok: Boolean, mess: any) {
diff --git a/src/internal/internalPane.ts b/src/internal/internalPane.ts
index b041634a..a73aa584 100644
--- a/src/internal/internalPane.ts
+++ b/src/internal/internalPane.ts
@@ -20,6 +20,7 @@ const pane: PaneDefinition = {
render: function (subject, context) {
const dom = context.dom
+ // @ts-ignore
const store = context.session.store as Store
const canonizedSubject = store.canon(subject) as BlankNode | NamedNode | Variable
const types = store.findTypeURIs(canonizedSubject)
diff --git a/src/outline/context.ts b/src/outline/context.ts
index dffe4f83..598b1f95 100644
--- a/src/outline/context.ts
+++ b/src/outline/context.ts
@@ -14,7 +14,9 @@ export function createContext (
getOutliner,
session: {
paneRegistry,
+ // @ts-ignore
store,
+ // @ts-ignore
logic
}
}
diff --git a/src/outline/manager.js b/src/outline/manager.js
index dee01991..ed54f4a8 100644
--- a/src/outline/manager.js
+++ b/src/outline/manager.js
@@ -464,10 +464,10 @@ export default function (context) {
async function showDashboard (options = {}) {
const dashboardContainer = getDashboardContainer()
const outlineContainer = getOutlineContainer()
- // reuse dashboard if already children already is inserted
+ // reuse dashboard if children already inserted
if (dashboardContainer.childNodes.length > 0 && options.pane) {
- outlineContainer.style.display = 'none'
- dashboardContainer.style.display = 'inherit'
+ outlineContainer.setAttribute('hidden', '')
+ dashboardContainer.removeAttribute('hidden')
const tab = dashboardContainer.querySelector(
`[data-global-pane-name="${options.pane}"]`
)
@@ -490,7 +490,8 @@ export default function (context) {
authSession.events.on('logout', closeDashboard)
// finally - switch to showing dashboard
- outlineContainer.style.display = 'none'
+ outlineContainer.setAttribute('hidden', '')
+ dashboardContainer.removeAttribute('hidden')
dashboardContainer.appendChild(dashboard)
const tab = dashboardContainer.querySelector(
`[data-global-pane-name="${options.pane}"]`
@@ -500,35 +501,37 @@ export default function (context) {
}
function closeDashboard () {
- dashboardContainer.style.display = 'none'
- outlineContainer.style.display = 'inherit'
+ dashboardContainer.setAttribute('hidden', '')
+ outlineContainer.removeAttribute('hidden')
}
}
this.showDashboard = showDashboard
function getDashboardContainer () {
- return getOrCreateContainer('GlobalDashboard')
+ return getOrCreateContainer('GlobalDashboard', 'Dashboard')
}
function getOutlineContainer () {
- return getOrCreateContainer('outline')
+ return getOrCreateContainer('OutlineView', 'Resource browser')
}
/**
- * Get element with id or create a new on the fly with that id
+ * Get element with id or create a new section on the fly with that id
*
* @param {string} id The ID of the element you want to get or create
+ * @param {string} [ariaLabel] Optional aria-label for accessibility
* @returns {HTMLElement}
*/
- function getOrCreateContainer (id) {
+ function getOrCreateContainer (id, ariaLabel) {
return (
document.getElementById(id) ||
(() => {
- const dashboardContainer = document.createElement('div')
- dashboardContainer.id = id
+ const container = document.createElement('section')
+ container.id = id
+ if (ariaLabel) container.setAttribute('aria-label', ariaLabel)
const mainContainer =
document.querySelector('[role="main"]') || document.body
- return mainContainer.appendChild(dashboardContainer)
+ return mainContainer.appendChild(container)
})()
)
}
@@ -581,8 +584,9 @@ export default function (context) {
const paneHiddenStyle =
'width: 24px; border-radius: 0.5em; margin-left: 1em; padding: 3px'
const paneIconTray = td.appendChild(dom.createElement('nav'))
- paneIconTray.style =
- 'display:flex; justify-content: flex-start; align-items: center;'
+ paneIconTray.setAttribute('role', 'toolbar')
+ paneIconTray.setAttribute('aria-label', 'Pane views')
+ paneIconTray.classList.add('paneIconTray')
const relevantPanes = options.hideList
? []
@@ -1577,7 +1581,7 @@ export default function (context) {
outline.GotoSubject(object, true)
/* //deal with this later
deselectAll();
- var newTr=dom.getElementById('outline').lastChild;
+ var newTr=dom.getElementById('OutlineView').lastChild;
setSelected(newTr.firstChild.firstChild.childNodes[1].lastChild,true);
function setSelectedAfterward(uri){
deselectAll();
@@ -2242,7 +2246,7 @@ export default function (context) {
@param table -- option -- a table element in which to put the outline.
*/
this.GotoSubject = function (subject, expand, pane, solo, referrer, table) {
- table = table || dom.getElementById('outline') // if does not exist just add one? nowhere to out it
+ table = table || dom.getElementById('OutlineView') // if does not exist just add one? nowhere to out it
if (solo) {
UI.utils.emptyNode(table)
table.style.width = '100%'
diff --git a/src/outline/userInput.js b/src/outline/userInput.js
index cdc24588..e6a7af47 100644
--- a/src/outline/userInput.js
+++ b/src/outline/userInput.js
@@ -1418,8 +1418,11 @@ export function UserInput (outline) {
false
)
window.addEventListener('mousedown', UserInput.Mousedown, false)
- document.getElementById('outline').oncontextmenu = function () {
- return false
+ const outlineView = document.getElementById('OutlineView')
+ if (outlineView) {
+ outlineView.oncontextmenu = function () {
+ return false
+ }
}
if (e.button === 2) {
diff --git a/src/pad/padPane.ts b/src/pad/padPane.ts
index 7003d960..1558235b 100644
--- a/src/pad/padPane.ts
+++ b/src/pad/padPane.ts
@@ -16,6 +16,7 @@ const paneDef: PaneDefinition = {
// Does the subject deserve an pad pane?
label: function (subject, context) {
+ // @ts-ignore
const t = (context.session.store as Store).findTypeURIs(subject)
if (t['http://www.w3.org/ns/pim/pad#Notepad']) {
return 'pad'
@@ -26,6 +27,7 @@ const paneDef: PaneDefinition = {
mintClass: ns.pad('Notepad'),
mintNew: function (context, newPaneOptions: any) {
+ // @ts-ignore
const store = context.session.store as Store
const updater = store.updater
if (newPaneOptions.me && !newPaneOptions.me.uri) {
@@ -77,6 +79,7 @@ const paneDef: PaneDefinition = {
// @@ TODO Set better type for paneOptions
render: function (subject, context, paneOptions: any) {
const dom = context.dom
+ // @ts-ignore
const store = context.session.store as Store
// Utility functions
const complainIfBad = function (ok: boolean, message: string) {
diff --git a/src/tabbed/tabbedPane.ts b/src/tabbed/tabbedPane.ts
index fa8dbe7b..c9b035d1 100644
--- a/src/tabbed/tabbedPane.ts
+++ b/src/tabbed/tabbedPane.ts
@@ -16,6 +16,7 @@ const TabbedPane: PaneDefinition = {
// Does the subject deserve this pane?
label: (subject, context) => {
+ // @ts-ignore
const kb = context.session.store as Store
const typeURIs = kb.findTypeURIs(subject)
if (ns.meeting('Cluster').uri in typeURIs) {
@@ -26,6 +27,7 @@ const TabbedPane: PaneDefinition = {
render: (subject, context) => {
const dom = context.dom
+ // @ts-ignore
const store = context.session.store as Store
const div = dom.createElement('div')
diff --git a/test/unit/meeting/Schedule/index.html b/test/unit/meeting/Schedule/index.html
index fe392cdc..753e3d22 100644
--- a/test/unit/meeting/Schedule/index.html
+++ b/test/unit/meeting/Schedule/index.html
@@ -64,9 +64,21 @@
>
-
-
+
+
+
+
+
+
+