Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
73face8
feat: structure the basic layout of float-pane feature
ohxyz Jun 4, 2026
e841b50
refactor: inline glass class defaults
ohxyz Jun 5, 2026
50ce52f
feat: add glass to a float pane
ohxyz Jun 5, 2026
304df34
fix: use dom id to mark float pane. sash-id are only used for panes b…
ohxyz Jun 5, 2026
45a4470
fix: append float pane to bw window and enchance check at drag and drop
ohxyz Jun 5, 2026
1ec8c8e
refactor: replace float pane with detached glass
ohxyz Jun 6, 2026
a8d30e2
chore: use @ as root path
ohxyz Jun 6, 2026
0a980b5
fix: detached glass shows text copy cursor when dragging on glass header
ohxyz Jun 6, 2026
867c06f
chore: cleanup
ohxyz Jun 6, 2026
820391d
feat(detached-glass): resize
ohxyz Jun 6, 2026
6d7b584
feat(detached-glass): move
ohxyz Jun 6, 2026
6cca4ec
chore: shorten comments
ohxyz Jun 6, 2026
aa1cd45
refactor: create actions dir to host actions
ohxyz Jun 6, 2026
81a89d8
refactor: path
ohxyz Jun 6, 2026
7d22c82
refactor: consolidate glass and actions modules to make them have the…
ohxyz Jun 6, 2026
f4fd57b
refactor: remove export of detached glass actions
ohxyz Jun 6, 2026
222f948
feat: export detached glass actions
ohxyz Jun 6, 2026
17fda45
chore: rename detached glass example
ohxyz Jun 6, 2026
d686ff6
refactor: imports exports
ohxyz Jun 6, 2026
104a38a
feat: handle default actions for glass and detached glass
ohxyz Jun 6, 2026
4cd40af
feat: add offset x and y to addDetacchedGlass api
ohxyz Jun 7, 2026
531ff16
feat: cascade detached glass from active one; naming/comment conventions
ohxyz Jun 7, 2026
e44265b
feat: keep cascaded glass within viewport; guard default size in addD…
ohxyz Jun 7, 2026
16fce32
chore: comment and ai guide
ohxyz Jun 7, 2026
df634e2
refactor: cursor style when detached glass being dragged
ohxyz Jun 7, 2026
fd53bf6
Merge branch 'main' into feat/detached-glass
ohxyz Jun 7, 2026
6ec169d
chore: add a perf example
ohxyz Jun 7, 2026
81d3cb6
feat: minimize and restore
ohxyz Jun 7, 2026
6eb26c9
refactor: split glass module into action and drag submodules
ohxyz Jun 7, 2026
1bca9fb
refactor: remove no op check code
ohxyz Jun 7, 2026
7c82593
refactor: split detached-glass module into feature submodules
ohxyz Jun 7, 2026
5c1374e
refactor: fold glass module.js into index.js; localize drag state
ohxyz Jun 7, 2026
d56200d
feat: add native drag module for detached glass
ohxyz Jun 7, 2026
aeb3bf0
docs: add commit style to CLAUDE.md
ohxyz Jun 7, 2026
f676953
fix: normActions
ohxyz Jun 7, 2026
7bd003a
feat: add detach glass action
ohxyz Jun 7, 2026
0d5f1e4
docs: drop commit-message style rule from CLAUDE.md
ohxyz Jun 7, 2026
25ac456
fix: move glass title to detached glass title on detach action
ohxyz Jun 7, 2026
573b2e2
refactor: detached action file names
ohxyz Jun 7, 2026
5951394
fix: disable detached action button when it's the last pane
ohxyz Jun 7, 2026
d3ed895
refactor: rename builtin actions to DEFAULT_*_ACTIONS
ohxyz Jun 8, 2026
2d1202a
refactor: normActions with default detached glass actions
ohxyz Jun 8, 2026
37e450a
refactor: update action icons
ohxyz Jun 8, 2026
d2a4d2b
feat: re-attach detached glass to its original sibling pane
ohxyz Jun 8, 2026
46deb02
fix: set sash.parent when building tree so re-attached panes can detach
ohxyz Jun 8, 2026
5517e73
feat: attach falls back to largest pane when original sibling is gone
ohxyz Jun 8, 2026
a535d95
chore: align debug env var name and document commit-message rule
ohxyz Jun 8, 2026
8e70398
refactor: rename detached-glass add module to crud, make placement pr…
ohxyz Jun 8, 2026
aebebd3
fix: unnest bw-glass-content when re-attaching detached glass
ohxyz Jun 8, 2026
5b59c9f
docs: add naming rule on matching established domain/library terms
ohxyz Jun 8, 2026
cd9d6a1
chore: toggle bw-window dark theme from test page
ohxyz Jun 8, 2026
88db61b
docs: restructure CLAUDE.md so each rule leads with the action
ohxyz Jun 8, 2026
2de425d
feat: strengthen detached glass box shadow in light and dark modes
ohxyz Jun 9, 2026
59fc321
chore: toggle iframe background, text, and color-scheme with theme bu…
ohxyz Jun 9, 2026
f16990f
feat: flash minimized glass background to draw attention when added t…
ohxyz Jun 9, 2026
015a73b
chore: tweak detached-glass dev window width
ohxyz Jun 9, 2026
64a6572
chore: code format
ohxyz Jun 9, 2026
1212731
refactor: rename highlight var to --bw-minimized-glass-highlight-color
ohxyz Jun 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env.production
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
VITE_DEFAULT_SASH_MIN_WIDTH=100
VITE_DEFAULT_SASH_MIN_HEIGHT=100
VITE_DEFAULT_DEBUG=false
VITE_DEBUG=false
28 changes: 25 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,31 @@
# CLAUDE.md

## Git rules
## Git

- **Never `git commit` or `git push` unless explicitly asked in that same message.** Approval doesn't carry over — ask each time.
- **Don't `git commit` or `git push` unless the same message explicitly asks for it.** Approval doesn't carry over — ask each time.
- When committing, print the commit message in your reply.
- Type commits that only touch `dev/` as plain `chore:` — never `feat:`/`fix:`, no `(dev)` scope. It's test scaffolding, not library source (see [Dev pages](#dev-pages-dev)).

## Testing

- Don't run tests or build after completing a feature or fixing a bug unless asked.
- Don't run tests or builds after finishing a feature or fix unless asked.

## Naming

- Suffix DOM-element variables with `El`, and keep the noun specific: `activeGlassEl`, not `activeEl`. Name element accessors `get<Noun>` to match (e.g. `getActiveGlass`).
- Name constants for the context they apply to, not just the quantity: `MIN_RESIZE_WIDTH`, not `MIN_WIDTH` — so they aren't confused with unrelated values like creation-time defaults.
- Prefer established domain/library terms and match their conventional meaning. Don't pick a name whose well-known meaning differs from what the code does — e.g. jQuery's `unwrap` removes the wrapper in place, so `extractChildNodes` is clearer for moving children into a fragment.

## Comments

- Comment only when it adds something the code doesn't already say.
- Keep comments to 2 lines max, 100 chars per line. If one genuinely needs more, prefix it with `RATIONAL:`.

## Debug sentinel values

- Leave repeating-digit literals like `222` and `333` in default/fallback paths alone — they're intentional debug sentinels, not magic numbers. Don't rename them to constants or replace them. If one surfaces in a lower-level API or the rendered output, a guard upstream was bypassed and a real value leaked — investigate that instead.

## Dev pages (`dev/`)

- Treat `dev/` as test scaffolding for manually exercising features/bugs, not shippable library source.
- Put interactive testing items (buttons, inputs, forms, selects, etc.) in the `.html` file, not the `.js`. The paired `.js` queries them with `document.querySelector(...)` and wires up behavior with `addEventListener`. See `dev/features/add-remove-pane.html` / `add-remove-pane.js` for the pattern.
27 changes: 27 additions & 0 deletions dev/features/bwin-detached-glass.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script type="module" src="./bwin-detached-glass.js"></script>
<title>Detached Glass</title>
</head>

<body>
<main>
<h2>BinaryWindow - detached glass</h2>
<label>offset <input type="number" id="offset" value="0" /></label>
<label>offsetX <input type="number" id="offsetX" /></label>
<label>offsetY <input type="number" id="offsetY" /></label>
<div>
<button id="add-default">Add default</button>
<button data-position="top-left">Add top-left</button>
<button data-position="top-right">Add top-right</button>
<button data-position="bottom-left">Add bottom-left</button>
<button data-position="bottom-right">Add bottom-right</button>
<button data-position="center">Add center</button>
</div>
<section id="container"></section>
</main>
</body>
</html>
135 changes: 135 additions & 0 deletions dev/features/bwin-detached-glass.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import {
BinaryWindow,
DEFAULT_GLASS_ACTIONS,
BUILTIN_ACTIONS,
DEFAULT_DETACHED_GLASS_ACTIONS,
} from '../../src';

const elem = document.createElement('div');
const zIndex = 100;

elem.textContent = 'z-index: ' + zIndex;
elem.style.backgroundColor = 'hsl(120 100% 90%)';
elem.style.width = '200px';
elem.style.height = '400px';
elem.style.position = 'absolute';
elem.style.top = '0';
elem.style.left = '0';
elem.style.opacity = '0.8';
elem.style.zIndex = zIndex;

const elem2 = document.createElement('div');
elem2.textContent = 'z-index: ' + (zIndex + 1);
elem2.style.backgroundColor = 'hsl(240 100% 90%)';
elem2.style.width = '300px';
elem2.style.height = '400px';
elem2.style.position = 'absolute';
elem2.style.top = '50px';
elem2.style.left = '50px';
elem2.style.opacity = '0.8';
elem2.style.zIndex = zIndex + 1;

const parentElem = document.createElement('div');
parentElem.style.position = 'relative';
parentElem.appendChild(elem);
parentElem.appendChild(elem2);

const settings = {
width: 777,
height: 444,
actions: [BUILTIN_ACTIONS],
children: [
{
position: 'left',
size: '40%',
children: [
{
position: 'top',
size: '50%',
content: createGlassContent('top-left'),
title: 'Top-left pane',
},
{
position: 'bottom',
size: '50%',
content: createGlassContent('bottom-left'),
title: 'Bottom-left pane',
},
],
},
{
children: [
{
position: 'top',
size: '30%',
content: createGlassContent('top-right'),
title: 'Top-right pane',
},
{ position: 'bottom', size: '70%', content: parentElem, title: 'Bottom pane' },
],
},
],
};

const bwin = new BinaryWindow(settings);
bwin.mount(document.querySelector('#container'));

// Distinguishable, interactive content so the glass body is visible while dragging.
function createGlassContent(label) {
const wrapEl = document.createElement('div');
wrapEl.style.padding = '8px';
wrapEl.style.fontFamily = 'sans-serif';
wrapEl.style.fontSize = '12px';

const headingEl = document.createElement('h3');
headingEl.textContent = `Content: ${label}`;
headingEl.style.margin = '0 0 8px';
wrapEl.appendChild(headingEl);

const inputEl = document.createElement('input');
inputEl.type = 'text';
inputEl.placeholder = 'type here…';
inputEl.style.width = '100%';
inputEl.style.boxSizing = 'border-box';
inputEl.style.marginBottom = '8px';
wrapEl.appendChild(inputEl);

const listEl = document.createElement('ul');
listEl.style.margin = '0';
listEl.style.paddingLeft = '18px';
for (let i = 1; i <= 8; i += 1) {
const itemEl = document.createElement('li');
itemEl.textContent = `${label} — row ${i}`;
listEl.appendChild(itemEl);
}
wrapEl.appendChild(listEl);

return wrapEl;
}

const offsetInput = document.querySelector('#offset');
const offsetXInput = document.querySelector('#offsetX');
const offsetYInput = document.querySelector('#offsetY');

// Empty input → undefined, so genStylesByPosition can fall back to `offset`.
const toOffset = (input) => (input.value === '' ? undefined : Number(input.value));

document.querySelectorAll('button[data-position]').forEach((button) => {
button.addEventListener('click', () => {
bwin.addDetachedGlass({
position: button.dataset.position,
title: button.dataset.position,
offset: Number(offsetInput.value),
offsetX: toOffset(offsetXInput),
offsetY: toOffset(offsetYInput),
content: createGlassContent(button.dataset.position),
});
});
});

// No options → exercises the DetachedGlass constructor defaults.
document.querySelector('#add-default').addEventListener('click', () => {
bwin.addDetachedGlass({ content: createGlassContent('default') });
});

// document.querySelector('#add-default').click();
32 changes: 0 additions & 32 deletions dev/features/float-pane.html

This file was deleted.

49 changes: 0 additions & 49 deletions dev/features/float-pane.js

This file was deleted.

2 changes: 1 addition & 1 deletion dev/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<body>
<nav>
<menu class="_menu">
<li><button id="_toggle-bg">Toggle BG</button></li>
<li><button id="_toggle-theme">Toggle Theme</button></li>
</menu>
</nav>
<iframe id="_frame"></iframe>
Expand Down
24 changes: 17 additions & 7 deletions dev/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,23 @@ function route() {
window.addEventListener('hashchange', route);
route();

navEl.querySelector('#_toggle-bg').addEventListener('click', () => {
const bgColor = 'hsl(0 0 90)';
const bodyEl = iframeEl.contentDocument?.body;
navEl.querySelector('#_toggle-theme').addEventListener('click', () => {
const frameDoc = iframeEl.contentDocument;
const windowEls = frameDoc?.querySelectorAll('bw-window');

if (!bodyEl) return;
if (!windowEls?.length) return;

// Compare against '' rather than bgColor: the CSSOM re-serializes colors on
// read (e.g. hsl() -> rgb()), so equality with the original string fails.
bodyEl.style.backgroundColor = bodyEl.style.backgroundColor ? '' : bgColor;
const goDark = windowEls[0].getAttribute('theme') !== 'dark';

windowEls.forEach((windowEl) => {
if (goDark) {
windowEl.setAttribute('theme', 'dark');
} else {
windowEl.removeAttribute('theme');
}
});

frameDoc.body.style.backgroundColor = goDark ? 'hsl(0 0% 12%)' : '';
frameDoc.body.style.color = goDark ? 'hsl(0 0% 90%)' : '';
frameDoc.documentElement.style.colorScheme = goDark ? 'dark' : '';
});
8 changes: 8 additions & 0 deletions jsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
}
},
"exclude": ["node_modules", "dist"]
}
Loading