Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
864267b
[fix]: add explicit type annotations, build internal package before s…
KealanAU Mar 29, 2026
26308af
[feat] updates to have the scoped-css work
KealanAU Apr 1, 2026
2ecaeaa
chore: fix build — move docs out of runtime/src, restore private flag
KealanAU Apr 1, 2026
3c30c18
chore: remove internal docs from PR
KealanAU Apr 3, 2026
1a24a34
[refactor] remove script module/setup testing
KealanAU Apr 3, 2026
9c45f22
fix(runtime): add onBeforeUpdate hook and fix VNode over-walking in u…
Huxpro Apr 3, 2026
9ecb759
docs: update vue-compatibility to reflect v-bind() in CSS support
Huxpro Apr 3, 2026
b8748be
chore: revert rejected type annotations, add changeset
Huxpro Apr 4, 2026
72deddd
[fix] make the feature css look nicer and work better together
KealanAU Apr 5, 2026
db48246
[debug] looking into why mobile doesn't get the same styling as web
KealanAU Apr 5, 2026
b78cc64
[refactor] updates to the css features, change to have explict naming…
KealanAU Apr 5, 2026
280591f
[fix] updates to properly stamp with enableCSSInheritance
KealanAU Apr 5, 2026
e8463a4
[fix] testing the inheritance
KealanAU Apr 5, 2026
6f5788f
[fix] merge conflicts
KealanAU Apr 5, 2026
e80ced0
Merge upstream/main — bring in #145 entry.ts fix and version bumps
KealanAU Apr 9, 2026
7d44ac9
chore: merge upstream/main, resolve App.vue conflict
KealanAU May 4, 2026
1c14b4f
docs: remove stale workaround references from useCssVars comments
KealanAU May 4, 2026
8314700
docs: reconcile lynx#5912/#5889 references and state minimum engine v…
KealanAU Jun 27, 2026
4ef99b7
docs: require Lynx engine >= 3.9.0 for CSS v-bind() propagation
KealanAU Jul 17, 2026
b8256b2
Merge remote-tracking branch 'upstream/main' into fix/opacity-investi…
KealanAU Jul 17, 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
7 changes: 7 additions & 0 deletions .changeset/v-bind-css-vars.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"vue-lynx": minor
---

feat: support `v-bind()` in `<style>` blocks via Lynx-native `useCssVars`

Implements a Background Thread compatible `useCssVars` that merges CSS custom properties into the component root element's inline style via the ops pipeline; the Lynx engine propagates them to descendants (lynx-family/lynx#5912, closing #5889). Requires `enableCSSInlineVariables: true` in `lynx.config` and Lynx engine ≥ 3.9.0 (the first tagged release containing the #5912 propagation code). `enableCSSInheritance` is not required for `v-bind()` in CSS.
5 changes: 4 additions & 1 deletion examples/css-features/lynx.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ export default defineConfig({
enableIFR: true,
optionsApi: false,
enableCSSInlineVariables: true,
enableCSSInheritance: true,
// Deliberately false: the example must prove that CSS custom property
// propagation (lynx-family/lynx#5912, engine >= 3.9.0) works without
// inheritance mode masking it.
enableCSSInheritance: false,
}),
],
});
39 changes: 21 additions & 18 deletions examples/css-features/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<script setup lang="ts">
import VBindCSS from './VBindCSS.vue'
import VBindThreads from './VBindThreads.vue'
import CSSInheritanceTest from './CSSInheritanceTest.vue'
import PlainStyle from './PlainStyle.vue'
import ScopedStyle from './ScopedStyle.vue'
import CSSModules from './CSSModules.vue'
import VBindCSS from './VBindCSS.vue'
import VBindThreads from './VBindThreads.vue'
import CSSVarsWorkaround from './CSSVarsWorkaround.vue'
import ImportedCSS from './ImportedCSS.vue'
</script>
Expand All @@ -17,25 +18,27 @@ import ImportedCSS from './ImportedCSS.vue'
CSS Features Test
</text>

<!-- 1. Plain <style> — WORKS -->
<PlainStyle />

<!-- 2a. <style scoped> — WORKS (via Lynx cssId) -->
<ScopedStyle />

<!-- 3. <style module> — SHOULD WORK -->
<CSSModules />

<!-- 4. v-bind() in CSS — WORKS (useCssVars implemented in vue-lynx) -->
<!-- v-bind() in CSS — primary focus -->
<VBindCSS />

<!-- 4b. v-bind() thread comparison — BG (useCssVars) vs MT (setStyleProperty) -->
<VBindThreads />

<!-- 5. Workaround: Reactive inline :style -->
<CSSVarsWorkaround />
<!-- Engine custom-property propagation test — no useCssVars, enableCSSInheritance off -->
<CSSInheritanceTest />

<!-- 6. Imported .css file — WORKS -->
<ImportedCSS />
<!-- Divider -->
<text :style="{ fontSize: '13px', fontWeight: 'bold', color: '#888', marginBottom: '12px', marginTop: '4px' }">
Other CSS patterns
</text>

<!-- Workarounds and supporting patterns — 2 per row -->
<CSSVarsWorkaround />
<view :style="{ display: 'flex', flexDirection: 'row', alignItems: 'flex-start', marginBottom: '12px' }">
<view :style="{ flex: 1, paddingRight: '6px' }"><ScopedStyle /></view>
<view :style="{ flex: 1, paddingLeft: '6px' }"><CSSModules /></view>
</view>
<view :style="{ display: 'flex', flexDirection: 'row', alignItems: 'flex-start', marginBottom: '12px' }">
<view :style="{ flex: 1, paddingRight: '6px' }"><PlainStyle /></view>
<view :style="{ flex: 1, paddingLeft: '6px' }"><ImportedCSS /></view>
</view>
</scroll-view>
</template>
73 changes: 73 additions & 0 deletions examples/css-features/src/CSSInheritanceTest.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<script setup lang="ts">
import { ref } from 'vue'

const COLORS = ['#c62828', '#1565c0', '#2e7d32']
const colorIdx = ref(0)
const color = ref(COLORS[0]!)

function cycleColor() {
colorIdx.value = (colorIdx.value + 1) % COLORS.length
color.value = COLORS[colorIdx.value]!
}
</script>

<template>
<view :style="{
backgroundColor: '#fafafa',
padding: '12px',
borderRadius: '8px',
marginBottom: '12px',
}">
<text :style="{ fontSize: '15px', fontWeight: 'bold', marginBottom: '2px', color: '#333' }">
CSS custom property propagation (CSSInheritanceTest.vue)
</text>
<text :style="{ fontSize: '11px', color: '#888', marginBottom: '10px' }">
Parent sets --test-color via :style. Children consume it via var() in class rules.
No useCssVars, and enableCSSInheritance is false — tests that engine-level custom
property propagation (lynx#5912, engine >= 3.9.0) works on its own.
</text>

<!-- Parent sets the CSS var via :style only — no v-bind(), no useCssVars -->
<view :style="{ '--test-color': color, padding: '10px', borderRadius: '6px', backgroundColor: '#fff' }">
<text :style="{ fontSize: '11px', color: '#555', marginBottom: '6px' }">
Parent: :style="{ '--test-color': color }"
</text>

<!-- Depth 1 child -->
<view :style="{ marginBottom: '4px' }">
<text class="inherited-color" :style="{ fontWeight: 'bold' }">
Depth 1 — color: var(--test-color)
</text>
</view>

<!-- Depth 2 child -->
<view>
<view>
<text class="inherited-color" :style="{ fontWeight: 'bold' }">
Depth 2 — color: var(--test-color)
</text>
</view>
</view>
</view>

<text
:style="{
marginTop: '10px',
backgroundColor: '#1565c0',
color: '#fff',
padding: '6px 10px',
borderRadius: '4px',
fontSize: '11px',
}"
:bindtap="cycleColor"
>
Cycle color (currently: {{ color }})
</text>
</view>
</template>

<style>
.inherited-color {
color: var(--test-color);
}
</style>
2 changes: 1 addition & 1 deletion examples/css-features/src/CSSModules.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

<template>
<view :class="$style.card">
<text :class="$style.title">&lt;style module&gt;</text>
<text :class="$style.title">&lt;style module&gt; (CSSModules.vue)</text>
<text :class="$style.desc">
Uses hashed class names (e.g. .card_abc123).
These are plain class selectors — Lynx supports them.
Expand Down
2 changes: 1 addition & 1 deletion examples/css-features/src/CSSVarsWorkaround.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ function toggle() {
<template>
<view :style="cardStyle">
<text :style="{ fontSize: '15px', fontWeight: 'bold', color: '#333', marginBottom: '4px' }">
Workaround: Reactive inline :style
Workaround: Reactive inline :style (CSSVarsWorkaround.vue)
</text>
<text :style="{ fontSize: '12px', color: '#555', marginBottom: '8px' }">
Use computed() + :style bindings instead of v-bind() in CSS.
Expand Down
2 changes: 1 addition & 1 deletion examples/css-features/src/ImportedCSS.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import './imported.css'

<template>
<view class="imported-card">
<text class="imported-title">Imported .css file</text>
<text class="imported-title">Imported .css file (ImportedCSS.vue)</text>
<text class="imported-desc">
External CSS files with class selectors work via the
@lynx-js/css-extract-webpack-plugin pipeline.
Expand Down
2 changes: 1 addition & 1 deletion examples/css-features/src/PlainStyle.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<template>
<view class="plain-card">
<text class="plain-title">Plain &lt;style&gt; (no scoped)</text>
<text class="plain-title">Plain &lt;style&gt; (PlainStyle.vue)</text>
<text class="plain-desc">Class selectors work via CSS extraction pipeline.</text>
</view>
</template>
Expand Down
2 changes: 1 addition & 1 deletion examples/css-features/src/ScopedStyle.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

<template>
<view class="scoped-card">
<text class="scoped-title">&lt;style scoped&gt;</text>
<text class="scoped-title">&lt;style scoped&gt; (ScopedStyle.vue)</text>
<text class="scoped-desc">
Bridged to Lynx's native cssId scoping system.
Styles are scoped to this component only.
Expand Down
Loading
Loading