-
-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Description
Describe the bug
Ok, this is going to be difficult for me because I'm not front-end dev. Maybe the bug is not a bug but an error on my side. The summary: In SveteKit + [email protected], I use a CSS class named grid-cell
that doesn't have "explicit" setting in the script's style tag, but it is used in a very specific selector: div.grid.row.row-highlight:hover div.grid-cell-bg.sticky-data > div.grid-cell
. There it is. Apparently, this usage is not enough for Svelte to add the scoping class to those DIV's. The structure is: div.grid-container > div.grid > div.grid-body > div.grid-row-bg > div.grid-row > div.grid-cell-bg > div.grid-cell. That's the markup the component specifies. That last DIV, when inspected in the browser, doesn't have the scoping class.
Just in case it isn't clear: The compiled CSS adds the scoping class to the big selector above. If I inspect the div.grid-cell element and manually add the scoping class, then the style is applied.
Reproduction
I currently cannot sit down to make a small repro, so I figured I should post the entire component. It is a bit over 200 lines (not much, right?). It is a table component made out of DIV's.
<script context="module" lang="ts">
export type ColAlignment = 'start' | 'center' | 'end';
export type WjGridRow<TRow extends Record<string, any> = Record<string, any>> = TRow & {
id: string | number;
selected?: boolean;
expanded?: boolean;
}
export type WjGridColumn<TCol extends Record<string, any> = Record<string, any>, TRow extends Record<string, any> = Record<string, any>> = TCol & {
key: string;
text: string;
width?: number;
pinnable?: boolean;
pinned?: boolean;
alignment?: ColAlignment;
get?: (row: TRow) => any;
}
</script>
<script lang="ts" generics="TCol extends Record<string, any> = Record<string, any>, TRow extends Record<string, any> = Record<string, any>">
import { combineClasses } from "./utils.js";
let {
columns,
data,
get = (r, k) => r[k],
defaultWidth = 10,
rowHighlight = true,
striped = true,
class: cssClass, ...restProps
}: {
columns: WjGridColumn<TCol, TRow>[];
data: WjGridRow<TRow>[];
get?: (row: TRow, key: string) => any;
defaultWidth?: number;
rowHighlight?: boolean;
striped?: boolean;
class?: string;
} = $props();
type ColumnInfo = {
column: WjGridColumn<TCol, TRow>;
left?: number;
}
const segregatedColumns = $derived(columns.reduce<{
accPinnedWidth: number;
accUnpinnedWidth: number;
pinned: ColumnInfo[];
unpinned: ColumnInfo[];
}>((p, c) => {
if (c.pinned) {
p.pinned.push({
column: c,
left: p.accPinnedWidth
});
p.accPinnedWidth += columnWidth(c);
}
else {
p.unpinned.push({
column: c,
left: p.accUnpinnedWidth
});
p.accUnpinnedWidth += columnWidth(c);
}
return p;
}, { accPinnedWidth: 0, accUnpinnedWidth: 0, pinned: [], unpinned: [] }));
$effect(() => {
console.log('Column data: %o', segregatedColumns);
});
function columnWidth(col: WjGridColumn<TCol, TRow>) {
return col.width ?? defaultWidth;
}
</script>
{#snippet colHeaders(cols: ColumnInfo[])}
{#each cols as ci (ci.column.key)}
<div
class={combineClasses('col-header', { 'sticky-header': !!ci.column.pinned })}
role="columnheader"
style:width={`${columnWidth(ci.column)}em`}
style:left={ci.left !== undefined ? `${ci.left}em` : undefined}
>
{ci.column.text}
</div>
{/each}
{/snippet}
{#snippet colData(row: WjGridRow<TRow>, cols: ColumnInfo[])}
{#each cols as ci (ci.column.key)}
{@const getFn = ci.column.get ?? (r => get(r, ci.column.key))}
<div
class={combineClasses('grid-cell-bg', { 'sticky-data': !!ci.column.pinned })}
role="gridcell"
style:width={`${ci.column.width ?? defaultWidth}em`}
style:left={ci.left !== undefined ? `${ci.left}em` : undefined}
>
<div class="grid-cell"> <!-- THIS GUY! WHEN RENDERED, THE SCOPING CLASS IS NOT THERE.-->
{getFn(row)}
</div>
</div>
{/each}
{/snippet}
<div class={combineClasses('grid-container', cssClass)}>
<div class="grid" role="table" {...restProps}>
<div class="header-group" role="rowheader">
{#if segregatedColumns.pinned.length}
{@render colHeaders(segregatedColumns.pinned)}
{/if}
{@render colHeaders(segregatedColumns.unpinned)}
<div class="col-header extra-header"> </div>
</div>
<div class={combineClasses('grid-body', { striped })}>
{#each data as row (row.id)}
<div class="grid-row-bg">
<div class={combineClasses('grid-row', { 'row-highlight': rowHighlight })}>
{#if segregatedColumns.pinned.length}
{@render colData(row, segregatedColumns.pinned)}
{/if}
{@render colData(row, segregatedColumns.unpinned)}
<div class="grid-cell"></div>
</div>
</div>
{/each}
</div>
</div>
</div>
<style lang="scss">
$tableGap: 0rem;
div.grid-container {
height: 100%;
width: 100%;
overflow: auto;
position: relative;
--wjg-bg-color-rgb: 255, 255, 255;
--wjg-bg-color-opacity: 1;
--wjg-color: inherit;
--wjg-striped-even-bg-color-rgb: 240, 240, 240;
--wjg-striped-odd-bg-color-rgb: 255, 255, 255;
--wjg-rowhighlight-bg-color-rgb: 0, 0, 0;
--wjg-rowhightlight-bg-opacity: 0.12;
}
div.grid {
display: table;
flex-direction: column;
flex-wrap: nowrap;
color: var(--wjg-color);
min-width: 100%;
background-color: rgba(var(--wjg-bg-color-rgb), var(--wjg-bg-color-opacity));
}
div.header-group {
display: flex;
flex-direction: row;
gap: $tableGap;
}
div.col-header {
position: sticky;
z-index: 1;
top: 0;
font-weight: bold;
box-shadow: inset 0 -0.4em 1em rgba(0, 0, 0, 0.15);
&.sticky-header {
z-index: 2;
}
}
div.extra-header {
flex: 1 1 0;
}
div.grid-body {
display: flex;
flex-direction: column;
&.striped {
> div.grid-row-bg {
background-color: rgba(var(--wjg-striped-even-bg-color-rgb), var(--wjg-bg-color-opacity));
& div.grid-cell-bg.sticky-data {
background-color: rgba(var(--wjg-striped-even-bg-color-rgb), var(--wjg-bg-color-opacity));
}
}
> div.grid-row-bg:nth-of-type(2n+1) {
background-color: rgba(var(--wjg-striped-odd-bg-color-rgb), var(--wjg-bg-color-opacity));
& div.grid-cell-bg.sticky-data {
background-color: rgba(var(--wjg-striped-odd-bg-color-rgb), var(--wjg-bg-color-opacity));
}
}
}
}
div.grid-row {
display: flex;
flex-direction: row;
gap: $tableGap;
padding: 0.2em 0em;
&.row-highlight {
&:hover, &.hover {
background-color: rgba(0, 0, 0, var(--wjg-rowhightlight-bg-opacity));
div.grid-cell-bg.sticky-data > div.grid-cell {
background-color: rgba(0, 0, 0, var(--wjg-rowhightlight-bg-opacity));
}
}
}
}
div.grid-cell-bg {
overflow: hidden;
text-wrap: nowrap;
text-overflow: ellipsis;
&.sticky-data {
position: sticky;
z-index: 1;
}
}
</style>
Logs
No response
System Info
System:
OS: Windows 11 10.0.22631
CPU: (16) x64 11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz
Memory: 4.39 GB / 15.77 GB
Binaries:
Node: 20.6.1 - C:\Program Files\nodejs\node.EXE
npm: 9.8.1 - C:\Program Files\nodejs\npm.CMD
Browsers:
Edge: Spartan (), Chromium (123.0.2420.97), ChromiumDev ()
Internet Explorer: 11.0.22621.1
npmPackages:
svelte: ^5.0.0-next.1 => 5.0.0-next.127
Severity
blocking an upgrade