initial commit
This commit is contained in:
+66
@@ -0,0 +1,66 @@
|
||||
# Force Dark Mode via CSS Overrides
|
||||
|
||||
## When to Use
|
||||
|
||||
The user wants the site to **always look like dark mode** regardless of:
|
||||
- The `.dark` class being toggled on/off
|
||||
- The `prefers-color-scheme` system setting
|
||||
- The dark mode toggle switch being flipped
|
||||
|
||||
## Approach
|
||||
|
||||
Instead of editing every `dark:` Tailwind variant across all pages (fragile, tedious), use CSS `!important` overrides in a shared stylesheet (e.g., `style.css`). These override the light-mode base classes so they render with dark-mode colors.
|
||||
|
||||
## The Override Block
|
||||
|
||||
```css
|
||||
/* Force dark mode colors regardless of .dark class */
|
||||
body {
|
||||
background: #111827 !important;
|
||||
color: #e5e7eb !important;
|
||||
}
|
||||
|
||||
/* Common background classes — map to dark slate */
|
||||
.bg-white { background-color: #1f2937 !important; }
|
||||
[class*="bg-white "] { background-color: #1f2937 !important; }
|
||||
[class*="bg-white/"] { background-color: rgba(31, 41, 55, 0.8) !important; }
|
||||
|
||||
.bg-gray-50 { background-color: #111827 !important; }
|
||||
.bg-gray-100 { background-color: #1f2937 !important; }
|
||||
|
||||
/* Text colors — map to light text */
|
||||
.text-gray-900 { color: #f9fafb !important; }
|
||||
.text-gray-800 { color: #f3f4f6 !important; }
|
||||
.text-gray-700 { color: #d1d5db !important; }
|
||||
.text-gray-600 { color: #9ca3af !important; }
|
||||
.text-gray-500 { color: #9ca3af !important; }
|
||||
|
||||
/* Border colors — map to dark borders */
|
||||
.border-gray-200 { border-color: #374151 !important; }
|
||||
.border-gray-100 { border-color: #374151 !important; }
|
||||
|
||||
/* Shadows — make them dark-ambient */
|
||||
.shadow-lg, .shadow-xl, .shadow-md, .shadow-sm {
|
||||
box-shadow: 0 1px 3px 0 rgba(0,0,0,0.3) !important;
|
||||
}
|
||||
|
||||
/* Gradient backgrounds — used for page backgrounds */
|
||||
[class*="from-gray-50"], [class*="to-gray-100"] {
|
||||
background: #111827 !important;
|
||||
}
|
||||
|
||||
/* Card-specific overrides */
|
||||
.dashboard-card, .metric-card, .modern-card {
|
||||
background: #1e293b !important;
|
||||
border-color: #334155 !important;
|
||||
}
|
||||
```
|
||||
|
||||
## Pitfalls
|
||||
|
||||
1. **Specificity issues** — The `[class*="..."]` attribute selectors may be needed to match compound classes like `bg-white/10` which contain `/` and don't match `.bg-white` alone.
|
||||
2. **Inline styles** — CSS with `!important` in the stylesheet still won't override inline `style="background: white"` on the element. Those need to be edited at the HTML level.
|
||||
3. **Tailwind dynamic classes** — If Tailwind JIT generates classes at runtime (e.g., `bg-[#123456]`), they bypass the override block. Use `!important` on the specific selector.
|
||||
4. **Box shadows** — Tailwind shadow utilities like `shadow-lg` use color-specific box-shadows. The override block replaces them all with a single dark shadow, which may look slightly different than the original dark-mode shadows.
|
||||
5. **Backdrop filters** — Elements with `backdrop-filter: blur(...)` may still show through with unintended colors. Check these manually.
|
||||
6. **The toggle still functions** — The `.dark` class can still be toggled on/off, it just won't produce visual changes anymore. If you want to fully disable the toggle, hide it with `display: none` or set `pointer-events: none`.
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
# CSS Z-Index & Overflow Clipping Debugging
|
||||
|
||||
## Symptom
|
||||
A dropdown, tooltip, or popup renders but is cut off / hidden behind elements below it.
|
||||
|
||||
## Root Cause (almost always one of these)
|
||||
|
||||
1. **Parent `overflow: hidden`** — the dropdown's parent container clips it via CSS overflow
|
||||
2. **Missing or broken z-index** — the dropdown has no z-index, or its z-index CSS variable is undefined
|
||||
3. **Stacking context** — a parent creates a new stacking context (via `position: relative + z-index`, `opacity < 1`, `transform`, `filter`, `will-change`) which limits how high the child can stack
|
||||
4. **Parent position / overflow conflicts** — `position: relative` on a grandparent with `overflow: hidden` blocks absolute children even with high z-index
|
||||
5. **Sibling DOM ordering** — the header wrapper has no z-index, so its sibling (main content) paints on top by default
|
||||
|
||||
## Diagnosis Checklist
|
||||
|
||||
### 1. Check parent overflow
|
||||
```bash
|
||||
# Search for overflow:hidden on or near the dropdown's container
|
||||
search_files("overflow-hidden", file_glob="*.html", path="src/")
|
||||
search_files("overflow-hidden", file_glob="*.css", path="src/")
|
||||
search_files("overflow.*hidden", file_glob="*.html", path="src/")
|
||||
```
|
||||
|
||||
### 2. Check CSS variable definitions
|
||||
```bash
|
||||
# If the dropdown uses a CSS variable for z-index, verify it's defined
|
||||
# e.g., `z-index: var(--z-critical) !important;` without `--z-critical: N;` in :root = broken
|
||||
search_files("--z-", file_glob="*.css", path="src/")
|
||||
search_files("var\(--z-", file_glob="*.html", path="src/")
|
||||
search_files("var\(--z-", file_glob="*.js", path="src/")
|
||||
```
|
||||
|
||||
A CSS variable referenced but never defined evaluates to `z-index: invalid` — effectively no z-index at all.
|
||||
|
||||
### 3. Check the element's actual z-index
|
||||
In browser dev tools: inspect the dropdown → computed styles → z-index. If it says `invalid` or isn't listed, the variable isn't resolving.
|
||||
|
||||
### 4. Check the outer wrapper's position and z-index
|
||||
Even when the dropdown and its immediate parent have high z-index, the **outermost header wrapper** may lack `position: relative`, allowing the next DOM sibling (main content) to paint on top.
|
||||
|
||||
Check: Does the `<div>` that wraps the entire header have `position: relative` and `z-index`?
|
||||
|
||||
## Fixes
|
||||
|
||||
### Fix 1: Ensure parent overflow is visible
|
||||
On the dropdown's immediate positioned parent:
|
||||
```css
|
||||
overflow: visible !important;
|
||||
```
|
||||
Or remove `overflow-hidden` from the Tailwind class list if `overflow-visible-important` is already applied.
|
||||
|
||||
### Fix 2: Define undefined CSS variables
|
||||
```css
|
||||
:root {
|
||||
--z-critical: 999999;
|
||||
}
|
||||
```
|
||||
|
||||
### Fix 3: Set z-index on the header card
|
||||
```css
|
||||
.header-card {
|
||||
z-index: 100;
|
||||
position: relative;
|
||||
}
|
||||
```
|
||||
This keeps the header above page content, so the dropdown (which is a child) can stack above content below the header.
|
||||
|
||||
### Fix 4: Remove conflicting Tailwind classes
|
||||
If a div has both `overflow-hidden` AND a class that sets `overflow: visible !important`, remove `overflow-hidden` — the `!important` should win in theory, but mobile Safari and some browsers handle this inconsistently.
|
||||
|
||||
### Fix 5: Set z-index on the outer header wrapper (non-obvious)
|
||||
Even with Fix 1-4, the dropdown can be covered by page content. This happens when the **outermost header div** doesn't create a stacking context:
|
||||
|
||||
```html
|
||||
<div class="header-wrapper"> ← NEEDS position:relative + z-index
|
||||
<div class="header-card z-100"> ← Fix 3 applied
|
||||
<div id="user-dropdown" z-10001> ← high z-index
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="main-content"> ← SIBLING of header-wrapper
|
||||
... ← paints ON TOP without Fix 5
|
||||
</div>
|
||||
```
|
||||
|
||||
**Fix:** Add `position: relative; z-index: 1000;` to the outermost header wrapper div (not just the header-card inside it). A value of 1000 is enough to beat any content z-index below.
|
||||
|
||||
## Multi-Layer Verification
|
||||
|
||||
After fixing, check ALL pages that share the same component:
|
||||
- Search for the same CSS classes/IDs across all HTML files
|
||||
- Check if each page has its own `<style>` block that overrides the shared stylesheet
|
||||
- Verify that shared stylesheet changes (e.g., `style.css`) apply to all pages
|
||||
|
||||
## Common Pattern: Header Dropdown Clipping
|
||||
|
||||
```
|
||||
<div class="header-card overflow-hidden"> ← PROBLEM: clips children
|
||||
<div class="user-menu-container relative">
|
||||
<div id="user-dropdown">...</div> ← gets clipped
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
Fix: Remove `overflow-hidden` from `header-card`, add `z-index` to it, and ensure the dropdown has a defined high z-index. Add `.user-menu-container { overflow: visible !important; }` for safety. Then add `position: relative; z-index: 1000` to the outer header wrapper to beat sibling DOM ordering.
|
||||
@@ -0,0 +1,56 @@
|
||||
# JavaScript Silent Crash: Block-Scoped `const` in `try`
|
||||
|
||||
**Pattern:** A `const` (or `let`) declared inside a `try {}` block is referenced
|
||||
outside the block. JavaScript throws a `ReferenceError` that silently crashes
|
||||
async event handlers — no error visible in the UI, no console output if the
|
||||
handler is an `addEventListener` callback calling an `async function`.
|
||||
|
||||
## Example
|
||||
|
||||
```javascript
|
||||
async function handleFinancialCompletion() {
|
||||
// ...
|
||||
try {
|
||||
const roData = getROData(roId); // block-scoped to try
|
||||
// ...
|
||||
} catch (e) {}
|
||||
|
||||
// BUG: roData is undefined here — ReferenceError
|
||||
if (roData) {
|
||||
roData.statusHistory.push({ ... });
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## Why it's silent
|
||||
|
||||
The `completeBtn.addEventListener('click', (e) => { handleFinancialCompletion(); })`
|
||||
does NOT catch the rejected promise from the async function. The ReferenceError
|
||||
propagates as an unhandled promise rejection — which browsers log but the UI
|
||||
shows nothing. The user sees "nothing happens."
|
||||
|
||||
## Fix
|
||||
|
||||
Declare the variable OUTSIDE the `try` block:
|
||||
|
||||
```javascript
|
||||
const roData = getROData(roId); // outside try
|
||||
try {
|
||||
const servicesLines = roData?.services ? ...;
|
||||
// ...
|
||||
} catch (e) {}
|
||||
// roData is accessible here
|
||||
if (roData) { ... }
|
||||
```
|
||||
|
||||
## Detection
|
||||
|
||||
Grep for `const.*=.*try` patterns or any variable accessed after a `} catch`
|
||||
that was declared inside the `try`:
|
||||
```bash
|
||||
grep -n 'const ' file.js | while read line; do
|
||||
# Check if any const declared in try block is used after catch
|
||||
...
|
||||
done
|
||||
```
|
||||
Reference in New Issue
Block a user