diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 00000000..0ce7d8d0
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,5 @@
+blank_issues_enabled: false
+contact_links:
+ - name: 🙏 Question or Help
+ url: https://github.com/vuejs/rfcs/discussions/new
+ about: If you have a question or need help, ask a question on the discussion forums.
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 00000000..5a2bc857
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,31 @@
+## Summary
+
+
+
+## Links
+
+
+
+- [Full Rendered Proposal]()
+
+
+
+- [Discussion Thread]()
+
+
+
+---
+
+**Important: Do NOT comment on this PR. Please use the discussion thread linked above to provide feedback, as it provides branched discussions that are easier to follow. This also makes the edit history of the PR clearer.**
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..e43b0f98
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.DS_Store
diff --git a/.prettierrc b/.prettierrc
index f5a1bdcd..8c353d7a 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -1,3 +1,4 @@
semi: false
singleQuote: true
printWidth: 80
+trailingComma: 'none'
\ No newline at end of file
diff --git a/README.md b/README.md
index 0b4c50a3..e11c2332 100644
--- a/README.md
+++ b/README.md
@@ -10,30 +10,23 @@ implemented and reviewed via the normal GitHub pull request workflow.
Some changes though are "substantial", and we ask that these be put
through a bit of a design process and produce a consensus among the Vue
-core team and the community.
+[core team] and the community.
## The RFC life-cycle
An RFC goes through the following stages:
-- **Pending:** when the RFC is submitted as a PR.
-- **Active:** when an RFC PR is merged and undergoing implementation.
-- **Landed:** when an RFC's proposed changes are shipped in an actual release.
-- **Rejected:** when an RFC PR is closed without being merged.
-
-[Pending RFC List](https://github.com/vuejs/rfcs/pulls)
+- **Pending:** when the RFC is submitted as a discussion thread. We use discussions instead of Pull Requests as the former provides better discussion threading.
+- **Active:** when an RFC is acknowledged and undergoing implementation. The feature may be shipped as experimental during this phase.
+- **Landed:** when an RFC's proposed changes are shipped as stable in a release.
+- **Rejected:** when an RFC is officially rejected or dropped.
## When to follow this process
You need to follow this process if you intend to make "substantial"
-changes to one of the projects listed below:
-
-- [Vue core](https://github.com/vuejs/vue)
-- [Vue Router](https://github.com/vuejs/vue-router)
-- [Vuex](https://github.com/vuejs/vuex)
-- [Vue CLI](https://github.com/vuejs/vue-cli)
+changes to [Vue core](https://github.com/vuejs/core).
-We are limiting the RFC process for these repos to test out the process in a more manageable fashion, and may expand it to cover more projects under the `vuejs` organization in the future. For now, if you wish to suggest changes to those other projects, please use their respective issue lists.
+We are limiting the RFC process to core to keep the workflow manageable. If you wish to suggest changes to those other projects, please use their respective issue lists.
What constitutes a "substantial" change is evolving based on community norms, but may include the following:
@@ -75,40 +68,36 @@ RFC merged into the RFC repo as a markdown file. At that point the RFC
is 'active' and may be implemented with the goal of eventual inclusion
into Vue.
-* Fork the RFC repo http://github.com/vuejs/rfcs
+1. Work on your proposal in a Markdown file based on the template (`0000-template.md`) found in this repo.
+
+ - Put care into the details: **RFCs that do not present convincing motivation, demonstrate understanding of the impact of the design, or are disingenuous about the drawbacks or alternatives tend to be poorly-received**.
+
+2. Open a new thread in [Discussions](https://github.com/vuejs/rfcs/discussions) and make sure to set category to "RFC Discussions".
+
+ - Build consensus and integrate feedback in the discussion thread. RFCs that have broad support are much more likely to make progress than those that don't receive any comments.
-* Copy `0000-template.md` to `active-rfcs/0000-my-feature.md` (where
-'my-feature' is descriptive. don't assign an RFC number yet).
+3. Eventually, the [core team] will decide whether the RFC is a candidate
+ for inclusion in Vue.
-* Fill in the RFC. Put care into the details: **RFCs that do not
-present convincing motivation, demonstrate understanding of the
-impact of the design, or are disingenuous about the drawbacks or
-alternatives tend to be poorly-received**.
+ - An RFC can be modified based upon feedback from the [core team] and community. Significant modifications may trigger a new final comment period.
-* Submit a pull request. As a pull request the RFC will receive design
-feedback from the larger community, and the author should be prepared
-to revise it in response.
+ - An RFC may be rejected after public discussion has settled and comments have been made summarizing the rationale for rejection. A member of the [core team] should then close the RFC's associated pull request.
-* Build consensus and integrate feedback. RFCs that have broad support
-are much more likely to make progress than those that don't receive any
-comments.
+ - An RFC may be accepted at the close of its final comment period. A [core team] member will merge the RFC's associated pull request, at which point the RFC will become 'active'.
-* Eventually, the [core team] will decide whether the RFC is a candidate
-for inclusion in Vue.
+4. If the proposal has been approved for inclusion, you can prepare a Pull Request:
-* An RFC can be modified based upon feedback from the [core team] and community. Significant modifications may trigger a new final comment period.
+ - Fork this repo.
-* An RFC may be rejected after public discussion has settled
-and comments have been made summarizing the rationale for rejection. A member of the [core team] should then close the RFC's associated pull request.
+ - Create your proposal as `active-rfcs/0000-my-feature.md` (where "my-feature" is descriptive. don't assign an RFC number yet).
-* An RFC may be accepted at the close of its final comment period. A [core team] member will merge the RFC's associated pull request, at which point the RFC will become 'active'.
+ - Submit a pull request. Make sure to link to the discussion thread.
## Details on Active RFCs
Once an RFC becomes active then authors may implement it and submit the
-feature as a pull request to the Vue repo. Becoming 'active' is not a rubber
-stamp, and in particular still does not mean the feature will ultimately
-be merged; it does mean that the core team has agreed to it in principle
+feature as a pull request to the Vue core repo. Becoming 'active' is not a rubber stamp, and in particular still does not mean the feature will ultimately
+be merged; it does mean that the [core team] has agreed to it in principle
and are amenable to merging it.
Furthermore, the fact that a given RFC has been accepted and is
@@ -138,11 +127,11 @@ feel free to ask (e.g. by leaving a comment on the associated issue).
## Reviewing RFC's
Members of the [core team] will attempt to review some set of open RFC
-pull requests on a regular basis. If a core team member believes an RFC PR is ready to be accepted into active status, they can approve the PR using GitHub's review feature to signal their approval of the RFC.
+pull requests on a regular basis. If a [core team] member believes an RFC PR is ready to be accepted into active status, they can approve the PR using GitHub's review feature to signal their approval of the RFC.
**Vue's RFC process owes its inspiration to the [React RFC process], [Rust RFC process] and [Ember RFC process]**
-[React RFC process]: https://github.com/reactjs/rfcs
-[Rust RFC process]: https://github.com/rust-lang/rfcs
-[Ember RFC process]: https://github.com/emberjs/rfcs
-[core team]: https://vuejs.org/v2/guide/team.html
+[react rfc process]: https://github.com/reactjs/rfcs
+[rust rfc process]: https://github.com/rust-lang/rfcs
+[ember rfc process]: https://github.com/emberjs/rfcs
+[core team]: https://vuejs.org/about/team.html
diff --git a/active-rfcs/0004-global-api-treeshaking.md b/active-rfcs/0004-global-api-treeshaking.md
index e0f27504..fa0a0910 100644
--- a/active-rfcs/0004-global-api-treeshaking.md
+++ b/active-rfcs/0004-global-api-treeshaking.md
@@ -9,7 +9,7 @@ Make Vue runtime tree-shakable by exposing as much APIs through named exports as
# Basic example
-``` js
+```js
import { nextTick, observable } from 'vue'
nextTick(() => {})
@@ -29,7 +29,7 @@ In addition, knowing that optional features won't increase the bundle size for u
Currently in 2.x, all global APIs are exposed on the single Vue object:
-``` js
+```js
import Vue from 'vue'
Vue.nextTick(() => {})
@@ -39,7 +39,7 @@ const obj = Vue.observable({})
In 3.x, they can **only** be accessed as named imports:
-``` js
+```js
import Vue, { nextTick, observable } from 'vue'
Vue.nextTick // undefined
@@ -64,7 +64,7 @@ By not attaching all APIs on the `Vue` default export, any unused APIs can be dr
In addition to public APIs, many of the internal components / helpers can be exported as named exports as well. This allows the compiler to output code that only imports features when they are used. For example the following template:
-``` html
+```html
hello
@@ -86,7 +86,7 @@ This means the `Transition` component only gets imported when the application ac
**Note the above only applies to the ES Modules builds for use with tree-shaking capable bundlers - the UMD build still includes all features and exposes everything on the `Vue` global variable (and the compiler will produce appropriate output to use APIs off the global instead of importing).**
-# Drawbacks
+# Drawbacks
Users can no longer import a single `Vue` variable and then use APIs off of it. However this should be a worthwhile tradeoff for minimal bundle sizes.
@@ -94,7 +94,7 @@ Users can no longer import a single `Vue` variable and then use APIs off of it.
Some plugins may rely on global APIs originally exposed on `Vue`:
-``` js
+```js
const plugin = {
install: Vue => {
Vue.nextTick(() => {
@@ -106,7 +106,7 @@ const plugin = {
In 3.0 they will need to import these explicitly:
-``` js
+```js
import { nextTick } from 'vue'
const plugin = {
diff --git a/active-rfcs/0005-replace-v-bind-sync-with-v-model-argument.md b/active-rfcs/0005-replace-v-bind-sync-with-v-model-argument.md
index c751b6d5..1f543e9f 100644
--- a/active-rfcs/0005-replace-v-bind-sync-with-v-model-argument.md
+++ b/active-rfcs/0005-replace-v-bind-sync-with-v-model-argument.md
@@ -94,7 +94,7 @@ None of these are great options, but I'm probably most in favor of option 2. I'd
## Drawbacks
-Beyond the inevitable pains with any breaking change, I think the pain for this syntax would be relatively minimal - partly because the `.sync` modifier is not as widely used a feature and also due to the potential easy of migrating users (see addoption strategy below).
+Beyond the inevitable pains with any breaking change, I think the pain for this syntax would be relatively minimal - partly because the `.sync` modifier is not as widely used a feature and also due to the potential easy of migrating users (see adoption strategy below).
## Adoption strategy
diff --git a/active-rfcs/0009-global-api-change.md b/active-rfcs/0009-global-api-change.md
index 8cd5bd26..7ca7963e 100644
--- a/active-rfcs/0009-global-api-change.md
+++ b/active-rfcs/0009-global-api-change.md
@@ -9,7 +9,7 @@ Re-design app bootstrapping and global API.
- Global APIs that globally mutate Vue's behavior are now moved to **app instances** created by the new `createApp` method, and their effects are now scoped to that app instance only.
-- Global APIs that are do not mutate Vue's behavior (e.g. `nextTick` and the APIs proposed in [Advanced Reactivity API](https://github.com/vuejs/rfcs/pull/22)) are now named exports as specified in [the Global API Treeshaking RFC](https://github.com/vuejs/rfcs/blob/treeshaking/active-rfcs/0000-global-api-treeshaking.md).
+- Global APIs that are do not mutate Vue's behavior (e.g. `nextTick` and the APIs proposed in [Advanced Reactivity API](https://github.com/vuejs/rfcs/pull/22)) are now named exports as specified in [the Global API Treeshaking RFC](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0004-global-api-treeshaking.md).
# Basic example
diff --git a/active-rfcs/0011-v-model-api-change.md b/active-rfcs/0011-v-model-api-change.md
index 31e8f07f..abdabcd5 100644
--- a/active-rfcs/0011-v-model-api-change.md
+++ b/active-rfcs/0011-v-model-api-change.md
@@ -39,7 +39,7 @@ h(Comp, {
})
```
-If the component wants to support `v-model` without an argument, it should expect a prop named `modelValue`. To sync its value back to the parent, the child should emit an event named `"update:modelValue"` (see [Render Function API change](https://github.com/vuejs/rfcs/blob/render-fn-api-change/active-rfcs/0000-render-function-api-change.md) for details on the new VNode data structure).
+If the component wants to support `v-model` without an argument, it should expect a prop named `modelValue`. To sync its value back to the parent, the child should emit an event named `"update:modelValue"` (see [Render Function API change](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0008-render-function-api-change.md) for details on the new VNode data structure).
The default compilation output prefixes the prop and event names with `model` to avoid conflict with common prop names.
diff --git a/active-rfcs/0012-custom-directive-api-change.md b/active-rfcs/0012-custom-directive-api-change.md
index f0274008..08249bcf 100644
--- a/active-rfcs/0012-custom-directive-api-change.md
+++ b/active-rfcs/0012-custom-directive-api-change.md
@@ -46,12 +46,13 @@ Make custom directive hook names more consistent with the component lifecycle.
Existing hooks are renamed to map better to the component lifecycle, with some timing adjustments. Arguments passed to the hooks remain unchanged.
-- `bind` -> `beforeMount`
-- `inserted` -> `mounted`
-- `beforeUpdate` *new, called before the element itself is updated*
+- **new** `created` (called before vnode props are applied to DOM node)
+- `bind` -> `beforeMount` (called after vnode props have been applied to DOM node)
+- `inserted` -> `mounted` (called after children have been inserted into the DOM node, and the DOM node itself has been inserted into parent element)
+- **new** `beforeUpdate` (called before the element itself is updated)
- ~~`update`~~ *removed, use `updated` instead*
-- `componentUpdated` -> `updated`
-- `beforeUnmount` *new*
+- `componentUpdated` -> `updated` (called after the element itself and its children have been updated)
+- **new** `beforeUnmount`
- `unbind` -> `unmounted`
## Usage on Components
@@ -76,7 +77,7 @@ return withDirectives(h('div'), [
Where `vFoo` will be the directive object written by the user, which contains hooks like `mounted` and `updated`.
-`withDirectives` returns a cloned VNode with the user hooks wrapped and injected as vnode lifecycle hooks (see [Render Function API Changes](https://github.com/vuejs/rfcs/blob/render-fn-api-change/active-rfcs/0000-render-function-api-change.md#special-reserved-props) for more details):
+`withDirectives` returns a cloned VNode with the user hooks wrapped and injected as vnode lifecycle hooks (see [Render Function API Changes](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0008-render-function-api-change.md#special-reserved-props) for more details):
``` js
{
diff --git a/active-rfcs/0013-composition-api.md b/active-rfcs/0013-composition-api.md
index 008c921c..5dbf48bc 100644
--- a/active-rfcs/0013-composition-api.md
+++ b/active-rfcs/0013-composition-api.md
@@ -748,7 +748,7 @@ We agree with that to a certain extent. However, we believe that:
Some users used Angular 1 controllers as examples of how the design could lead to poorly written code. The biggest difference between the Composition API and Angular 1 controllers is that it doesn't rely on a shared scope context. This makes it significantly easier to split out logic into separate functions, which is the core mechanism of JavaScript code organization.
-Any JavaScript program starts with an entry file (think of it as the `setup()` for a program). We organize the program by splitting it into functions and modules based on logical concerns. **The Composition API enables us to do the same for Vue component code.** In other words, skills in writing well-organized JavaScript code translates directly into skills of writing well-organized Vue code when using the Composition API.
+Any JavaScript program starts with an entry file (think of it as the `setup()` for a program). We organize the program by splitting it into functions and modules based on logical concerns. **The Composition API enables us to do the same for Vue component code.** In other words, skills in writing well-organized JavaScript code translate directly into skills of writing well-organized Vue code when using the Composition API.
## Adoption strategy
diff --git a/active-rfcs/0018-transition-class-change.md b/active-rfcs/0018-transition-class-change.md
index 23321314..6eddeda3 100644
--- a/active-rfcs/0018-transition-class-change.md
+++ b/active-rfcs/0018-transition-class-change.md
@@ -7,6 +7,7 @@
- Rename the `v-enter` transition class to `v-enter-from`
- Rename the `v-leave` transition class to `v-leave-from`
+- Rename the `v-appear` transition class to `v-appear-from`
# Basic example
@@ -52,9 +53,11 @@ The asymmetry and lack of explicitness in `.v-enter` and `.v-leave` makes these
- `.v-enter` is renamed to `.v-enter-from`
- `.v-leave` is renamed to `.v-leave-from`
+- `.v-appear` is renamed to `.v-appear-from`
- The `` component's related prop names are also changed:
- `leave-class` is renamed to `leave-from-class` (in render functions or JSX, can be written as `leaveFromClass`)
- `enter-class` is renamed to `enter-from-class` (in render functions or JSX, can be written as `enterFromClass`)
+ - `appear-class` is renamed to `appear-from-class` (in render functions or JSX, can be written as `appearFromClass`)
# Adoption strategy
diff --git a/active-rfcs/0021-router-link-scoped-slot.md b/active-rfcs/0021-router-link-scoped-slot.md
index 444d62bb..3f6141a6 100644
--- a/active-rfcs/0021-router-link-scoped-slot.md
+++ b/active-rfcs/0021-router-link-scoped-slot.md
@@ -9,6 +9,7 @@
- Remove `event` prop
- Stop automatically assigning click events to inner anchors
- Add a scoped-slot API
+- Add a `custom` prop to fully customize `router-link`'s rendering
# Basic example
@@ -55,34 +56,12 @@ This implementation would:
- no longer accepts `event` -> use the scoped slot instead
- no longer works as a wrapper automatically looking for the first `a` inside -> use the scoped slot instead
-## Custom `tag` prop
-
-I am not sure about keeping the `tag` prop if it can be replaced which a scoped slot because it wouldn't handle custom components and except for very simple cases, we will likely use custom UI components instead of the basics ones:
-
-```vue
-
- homeHome
-
-```
-
-is equivalent to
-
-```vue
-
-
-
-```
-
-(see below for explanation about the attributes passed to the scoped-slot)
-
## Scoped slot
-A scoped slot would get access to every bit of information needed to provide a custom integration and allows applying the active classes, click listener, links, etc at any level. This would allow a better integration with frameworks like Bootstrap (https://getbootstrap.com/docs/4.3/components/navbar/). The idea would be to create a Vue component to avoid the boilerplate like bootstrap-vue does (https://bootstrap-vue.js.org/docs/components/navbar/#navbar)
+A scoped slot would get access to every bit of information needed to provide a custom integration and allows applying the active classes, click listener, links, etc at any level. This would allow a better integration with UI frameworks like Bootstrap (https://getbootstrap.com/docs/4.3/components/navbar/). The idea would be to create a Vue component to avoid the boilerplate like bootstrap-vue does (https://bootstrap-vue.js.org/docs/components/navbar/#navbar)
```vue
-
+
```
+The `custom` prop is necessary to take full control over `router-link`'s rendering: not rendering a wrapping `a` element.
+
+**Why is a `custom` prop necessary**: in Vue 3, scoped slots and regular slots cannot be differentiated from each other, which means vue router is unable to make the difference between these 3 cases:
+
+```vue
+
+
+Some Link
+```
+
+In all three cases we need to render the slot content but `router-link` needs to know if it has to render a wrapping `a` element. In Vue 2, we are able to do so by checking `$scopedSlots` but in Vue 3, only `slots` exists. This means that the behavior is slightly different in Vue Router v3 and Vue Router v4:
+
+- In v3, the `custom` prop is required (see [Adoption strategy](#adoption-strategy)) alongside `v-slot`. `router-link` will not wrap the slot content with an `a` element.
+- In v4, the `custom` prop is **not** required alongside `v-slot`. It controls whether `router-link` should wrap its slot content with an `a` element or not:
+ ```vue
+
+
+ {{ href }}
+
+
+ /
+ /
+ ```
+
### Accessible variables
The slot should provide values that are computed inside `router-link`:
@@ -101,6 +104,28 @@ The slot should provide values that are computed inside `router-link`:
- `isActive`: true whenever `router-link-active` is applied. Can be modified by `exact` prop
- `isExactActive`: true whenever `router-link-exact-active` is aplied. Can be modified by `exact` prop.
+## The removal of the `tag` prop
+
+The `tag` prop can be replaced which a scoped slot and make the code clearer while not being exposed to any caveat. Its removal will also lighten the vue-router library.
+
+```vue
+
+ homeHome
+
+```
+
+is equivalent to
+
+```vue
+
+
+
+```
+
+(see above for explanation about the attributes passed to the scoped-slot)
+
# Drawbacks
- Whereas it's possible to keep existing behaviour working and only expose a new behaviour with scoped slots, it will still prevent us from fixing existing issues with current implementation. That's why there are some breaking changes, to make things more consistent.
@@ -109,10 +134,28 @@ The slot should provide values that are computed inside `router-link`:
# Alternatives
- Keeping `event` prop for convienience
+- Use a different named slot instead of a `prop`:
+
+ ```vue
+
+
+
+
+
+
+
+
+
+
+
+ ```
+
+ The adoption strategy in this case would be similar but the warning would tell the user to use a different slot instead of a prop named `custom`
+
+- Create a new component like `router-link-custom` to differentiate the behavior. This solution is however heavier (in terms of size) than a prop or a different named slot. It is also less suitable than a prop because we are only changing a behavior of the component. The difference between the two components woud be too small to justify a whole new component.
# Adoption strategy
- Document new slot behaviour based on examples
-- Deprecate `tag` and `event` with a message and link to documentation the remove in v4
-
-# Unresolved questions
+- Deprecate `tag` and `event` with a message in v3 and link to documentation, then remove in v4
+- In v3, if no `custom` prop is provided when using a scoped slot, warn the user to use the `custom` prop
diff --git a/active-rfcs/0023-scoped-styles-changes.md b/active-rfcs/0023-scoped-styles-changes.md
index b6f2dd66..84594b30 100644
--- a/active-rfcs/0023-scoped-styles-changes.md
+++ b/active-rfcs/0023-scoped-styles-changes.md
@@ -13,12 +13,18 @@ Provide more consistent custom CSS extensions in Single File Component scoped st
```
@@ -38,17 +44,19 @@ To avoid the confusion of the dropped `/deep/` combinator, we introduced yet ano
The previous versions of the deep combinator are still supported for compatibility reasons in the current [Vue 2 SFC compiler](https://github.com/vuejs/component-compiler-utils), which again, can be confusing to users. In v3, we are deprecating the support for `>>>` and `/deep/`.
-As we were working on the new SFC compiler for v3, we noticed that CSS pseudo elements are in fact semantically NOT [combinators](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators). It is more consistent with idiomatic CSS for pseudo elements to accept arguments instead, so we are also making `::v-deep()` work that way. The current usage of `::v-deep` as a combinator is still supported, however it is considered deprecated and will raise a warning.
+As we were working on the new SFC compiler for v3, we noticed that CSS pseudo elements are in fact semantically NOT [combinators](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators). It is more consistent with idiomatic CSS for pseudo elements to accept arguments instead, so we are also making `::v-deep()` work that way. If you don't care about the explicit `v-` prefix, you can also use the shorter `:deep()` variant, which works exactly the same.
+
+The current usage of `::v-deep` as a combinator is still supported, however it is considered deprecated and will raise a warning.
## Targeting / Avoiding Slot Content
Currently, slot content passed in from the parent are affected by both the parent's scoped styles AND the child's scoped styles. There is no way to author rules that explicitly target slot content only, or ones that do not affect slot content.
-In v3, we intend to make child scoped styles NOT affecting slot content by default. To explicitly target slot content, the `::v-slotted()` pseudo element can be used.
+In v3, we intend to make child scoped styles NOT affecting slot content by default. To explicitly target slot content, the `::v-slotted()` (shorthand: `:slotted()`) pseudo element can be used.
## One-Off Global Rules
-Currently to add a global CSS rule we need to use a separate unscoped `
+```
+
+# Motivation
+
+Vue SFC styles provide straightforward CSS collocation and encapsulation, but it is purely static - which means up to this point we have no capability of dynamically updating the styles at runtime based on the component's state.
+
+Now with [most modern browsers supporting native CSS variables](https://caniuse.com/#feat=css-variables), we can leverage it to easily connect the component's state and styles.
+
+# Detailed design
+
+The `
+```
+
+As expected, this would bind the `color` declaration's value to the `color` property of the component's state, reactively.
+
+The `v-bind` function can support arbitrary JavaScript expressions inside, but since JavaScript expressions may contain characters that are not valid in CSS identifiers, they will need to be wrapped in quotes most of the time:
+
+```css
+.text {
+ font-size: v-bind('theme.font.size');
+}
+```
+
+When such CSS variables are detected, the SFC compiler will perform the following:
+
+1. Rewrite the `v-bind()` to a native `var()` with a hashed variable name. The above will be rewritten to:
+
+ ```css
+ .text {
+ color: var(--6b53742-color);
+ font-size: var(--6b53742-theme_font_size);
+ }
+ ```
+
+ Note the hashing will be applied in all cases, regardless of whether `