[{"data":1,"prerenderedAt":875},["ShallowReactive",2],{"docs:\u002Fdocs\u002Freactions":3},{"id":4,"title":5,"body":6,"description":867,"extension":868,"meta":869,"navigation":647,"path":870,"rawbody":871,"seo":872,"stem":873,"__hash__":874},"docs\u002Fdocs\u002Freactions.md","Reactions",{"type":7,"value":8,"toc":857},"minimark",[9,18,96,120,125,128,270,273,290,292,299,395,399,405,408,411,417,451,454,456,459,501,504,506,513,566,569,573,576,597,714,717,727,731,749,820,832,836,853],[10,11,12,13,17],"p",{},"A reaction has a trigger and outputs. ",[14,15,16],"code",{},"--k-when"," sets the trigger, and outputs set what changes. Kinesis turns the trigger into a progress value from 0 to 1, springs it, and moves each output with it.",[19,20,25],"pre",{"className":21,"code":22,"language":23,"meta":24,"style":24},"language-css shiki shiki-themes github-dark-default",".card {\n  --k-when: hover;   \u002F* trigger *\u002F\n  --k-y: -6px;       \u002F* outputs *\u002F\n  --k-scale: 1.02;\n}\n","css","",[14,26,27,40,54,76,90],{"__ignoreMap":24},[28,29,32,36],"span",{"class":30,"line":31},"line",1,[28,33,35],{"class":34},"sFSAA",".card",[28,37,39],{"class":38},"sZEs4"," {\n",[28,41,43,47,50],{"class":30,"line":42},2,[28,44,46],{"class":45},"sQhOw","  --k-when",[28,48,49],{"class":38},": hover;   ",[28,51,53],{"class":52},"sH3jZ","\u002F* trigger *\u002F\n",[28,55,57,60,63,66,70,73],{"class":30,"line":56},3,[28,58,59],{"class":45},"  --k-y",[28,61,62],{"class":38},": ",[28,64,65],{"class":34},"-6",[28,67,69],{"class":68},"suJrU","px",[28,71,72],{"class":38},";       ",[28,74,75],{"class":52},"\u002F* outputs *\u002F\n",[28,77,79,82,84,87],{"class":30,"line":78},4,[28,80,81],{"class":45},"  --k-scale",[28,83,62],{"class":38},[28,85,86],{"class":34},"1.02",[28,88,89],{"class":38},";\n",[28,91,93],{"class":30,"line":92},5,[28,94,95],{"class":38},"}\n",[10,97,98,99,102,103,106,107,102,110,112,113,102,116,119],{},"A dock is ",[14,100,101],{},"near"," with ",[14,104,105],{},"--k-scale",". A pressable button is ",[14,108,109],{},"press",[14,111,105],{},". A reveal is ",[14,114,115],{},"view",[14,117,118],{},"--k-opacity",".",[121,122,124],"h2",{"id":123},"outputs","Outputs",[10,126,127],{},"One value goes from rest to that value. Two values go from the first to the second.",[129,130,131,147],"table",{},[132,133,134],"thead",{},[135,136,137,141,144],"tr",{},[138,139,140],"th",{},"Output",[138,142,143],{},"Rest",[138,145,146],{},"Example",[148,149,150,173,190,207,223,240,255],"tbody",{},[135,151,152,162,167],{},[153,154,155,158,159],"td",{},[14,156,157],{},"--k-x",", ",[14,160,161],{},"--k-y",[153,163,164],{},[14,165,166],{},"0",[153,168,169,172],{},[14,170,171],{},"--k-y: 24px 0"," rises into place",[135,174,175,180,185],{},[153,176,177],{},[14,178,179],{},"--k-rotate",[153,181,182],{},[14,183,184],{},"0deg",[153,186,187],{},[14,188,189],{},"--k-rotate: -8deg 8deg",[135,191,192,196,201],{},[153,193,194],{},[14,195,105],{},[153,197,198],{},[14,199,200],{},"1",[153,202,203,206],{},[14,204,205],{},"--k-scale: 1.1"," grows a little",[135,208,209,213,217],{},[153,210,211],{},[14,212,118],{},[153,214,215],{},[14,216,200],{},[153,218,219,222],{},[14,220,221],{},"--k-opacity: 0 1"," fades in",[135,224,225,230,234],{},[153,226,227],{},[14,228,229],{},"--k-blur",[153,231,232],{},[14,233,166],{},[153,235,236,239],{},[14,237,238],{},"--k-blur: 8px 0"," sharpens",[135,241,242,247,250],{},[153,243,244],{},[14,245,246],{},"--k-color",[153,248,249],{},"current color",[153,251,252],{},[14,253,254],{},"--k-color: tomato",[135,256,257,262,265],{},[153,258,259],{},[14,260,261],{},"--k-background",[153,263,264],{},"current background",[153,266,267],{},[14,268,269],{},"--k-background: #0c1324 #2f6bff",[10,271,272],{},"Colors accept any CSS color. The browser mixes them in Oklab, which keeps transitions from passing through gray.",[10,274,275,276,281,282,285,286,289],{},"Transform outputs add to ",[277,278,280],"a",{"href":279},"\u002Fdocs\u002Fpointer-effects\u002F","pointer effects"," on the same element and respect ",[14,283,284],{},"transform-origin",". A dock icon with ",[14,287,288],{},"transform-origin: bottom"," grows upward.",[121,291,101],{"id":101},[10,293,294,295,298],{},"The pointer's closeness: 0 at ",[14,296,297],{},"--k-radius",", 1 at the element's center.",[19,300,302],{"className":21,"code":301,"language":23,"meta":24,"style":24},".dock__icon {\n  --k-when: near;\n  --k-radius: 120px;\n  --k-axis: x;\n  --k-scale: 1.65;\n  --k-y: -14px;\n  transform-origin: 50% 100%;\n}\n",[14,303,304,311,318,332,344,355,369,390],{"__ignoreMap":24},[28,305,306,309],{"class":30,"line":31},[28,307,308],{"class":34},".dock__icon",[28,310,39],{"class":38},[28,312,313,315],{"class":30,"line":42},[28,314,46],{"class":45},[28,316,317],{"class":38},": near;\n",[28,319,320,323,325,328,330],{"class":30,"line":56},[28,321,322],{"class":45},"  --k-radius",[28,324,62],{"class":38},[28,326,327],{"class":34},"120",[28,329,69],{"class":68},[28,331,89],{"class":38},[28,333,334,337,339,342],{"class":30,"line":78},[28,335,336],{"class":45},"  --k-axis",[28,338,62],{"class":38},[28,340,341],{"class":34},"x",[28,343,89],{"class":38},[28,345,346,348,350,353],{"class":30,"line":92},[28,347,81],{"class":45},[28,349,62],{"class":38},[28,351,352],{"class":34},"1.65",[28,354,89],{"class":38},[28,356,358,360,362,365,367],{"class":30,"line":357},6,[28,359,59],{"class":45},[28,361,62],{"class":38},[28,363,364],{"class":34},"-14",[28,366,69],{"class":68},[28,368,89],{"class":38},[28,370,372,375,377,380,383,386,388],{"class":30,"line":371},7,[28,373,374],{"class":34},"  transform-origin",[28,376,62],{"class":38},[28,378,379],{"class":34},"50",[28,381,382],{"class":68},"%",[28,384,385],{"class":34}," 100",[28,387,382],{"class":68},[28,389,89],{"class":38},[28,391,393],{"class":30,"line":392},8,[28,394,95],{"class":38},[396,397],"demo",{"id":398},"dock",[10,400,401,404],{},[14,402,403],{},"--k-axis: x"," measures horizontal distance only, so the icons follow the pointer along the dock.",[121,406,407],{"id":407},"hover",[10,409,410],{},"1 while the pointer is over the element. Keyboard focus also turns it on.",[10,412,413,414,119],{},"Kinesis tests hover against the element's resting position. An element that shrinks or tilts away from the pointer doesn't flicker at its edges, as it would with CSS ",[14,415,416],{},":hover",[19,418,420],{"className":21,"code":419,"language":23,"meta":24,"style":24},".card {\n  --k-when: hover;\n  --k-y: -6px;\n}\n",[14,421,422,428,435,447],{"__ignoreMap":24},[28,423,424,426],{"class":30,"line":31},[28,425,35],{"class":34},[28,427,39],{"class":38},[28,429,430,432],{"class":30,"line":42},[28,431,46],{"class":45},[28,433,434],{"class":38},": hover;\n",[28,436,437,439,441,443,445],{"class":30,"line":56},[28,438,59],{"class":45},[28,440,62],{"class":38},[28,442,65],{"class":34},[28,444,69],{"class":68},[28,446,89],{"class":38},[28,448,449],{"class":30,"line":78},[28,450,95],{"class":38},[10,452,453],{},"Touch never turns hover on.",[121,455,109],{"id":109},[10,457,458],{},"1 while the element is pressed, by mouse, finger, or pen, or by Enter or Space when it has focus.",[19,460,462],{"className":21,"code":461,"language":23,"meta":24,"style":24},".button {\n  --k-when: press;\n  --k-scale: 0.9;\n  --k-motion: bouncy;\n}\n",[14,463,464,471,478,489,497],{"__ignoreMap":24},[28,465,466,469],{"class":30,"line":31},[28,467,468],{"class":34},".button",[28,470,39],{"class":38},[28,472,473,475],{"class":30,"line":42},[28,474,46],{"class":45},[28,476,477],{"class":38},": press;\n",[28,479,480,482,484,487],{"class":30,"line":56},[28,481,81],{"class":45},[28,483,62],{"class":38},[28,485,486],{"class":34},"0.9",[28,488,89],{"class":38},[28,490,491,494],{"class":30,"line":78},[28,492,493],{"class":45},"  --k-motion",[28,495,496],{"class":38},": bouncy;\n",[28,498,499],{"class":30,"line":92},[28,500,95],{"class":38},[396,502],{"id":503},"press-buttons",[121,505,115],{"id":115},[10,507,508,509,512],{},"1 once the element is a tenth of the way into the viewport, 0 when it leaves. ",[14,510,511],{},"view once"," stays at 1 after the first time.",[19,514,516],{"className":21,"code":515,"language":23,"meta":24,"style":24},".feature {\n  --k-when: view once;\n  --k-opacity: 0 1;\n  --k-y: 28px 0;\n}\n",[14,517,518,525,532,546,562],{"__ignoreMap":24},[28,519,520,523],{"class":30,"line":31},[28,521,522],{"class":34},".feature",[28,524,39],{"class":38},[28,526,527,529],{"class":30,"line":42},[28,528,46],{"class":45},[28,530,531],{"class":38},": view once;\n",[28,533,534,537,539,541,544],{"class":30,"line":56},[28,535,536],{"class":45},"  --k-opacity",[28,538,62],{"class":38},[28,540,166],{"class":34},[28,542,543],{"class":34}," 1",[28,545,89],{"class":38},[28,547,548,550,552,555,557,560],{"class":30,"line":78},[28,549,59],{"class":45},[28,551,62],{"class":38},[28,553,554],{"class":34},"28",[28,556,69],{"class":68},[28,558,559],{"class":34}," 0",[28,561,89],{"class":38},[28,563,564],{"class":30,"line":92},[28,565,95],{"class":38},[396,567],{"id":568},"reveal",[121,570,572],{"id":571},"scroll-and-page","scroll and page",[10,574,575],{},"These follow scrolling continuously.",[577,578,579,589],"ul",{},[580,581,582,588],"li",{},[583,584,585],"strong",{},[14,586,587],{},"scroll"," is the element's trip through the viewport: 0 when its top enters at the bottom, 1 when its bottom leaves at the top.",[580,590,591,596],{},[583,592,593],{},[14,594,595],{},"page"," is the whole document: 0 at the top, 1 at the bottom.",[19,598,600],{"className":21,"code":599,"language":23,"meta":24,"style":24},".tile {\n  --k-when: scroll;\n  --k-rotate: -120deg 120deg;\n}\n\n.reading-progress {\n  --k-when: page;\n  --k-motion: instant;\n  scale: var(--k-progress) 1;\n  transform-origin: left;\n}\n",[14,601,602,609,619,639,643,649,656,666,673,697,709],{"__ignoreMap":24},[28,603,604,607],{"class":30,"line":31},[28,605,606],{"class":34},".tile",[28,608,39],{"class":38},[28,610,611,613,615,617],{"class":30,"line":42},[28,612,46],{"class":45},[28,614,62],{"class":38},[28,616,587],{"class":34},[28,618,89],{"class":38},[28,620,621,624,626,629,632,635,637],{"class":30,"line":56},[28,622,623],{"class":45},"  --k-rotate",[28,625,62],{"class":38},[28,627,628],{"class":34},"-120",[28,630,631],{"class":68},"deg",[28,633,634],{"class":34}," 120",[28,636,631],{"class":68},[28,638,89],{"class":38},[28,640,641],{"class":30,"line":78},[28,642,95],{"class":38},[28,644,645],{"class":30,"line":92},[28,646,648],{"emptyLinePlaceholder":647},true,"\n",[28,650,651,654],{"class":30,"line":357},[28,652,653],{"class":34},".reading-progress",[28,655,39],{"class":38},[28,657,658,660,662,664],{"class":30,"line":371},[28,659,46],{"class":45},[28,661,62],{"class":38},[28,663,595],{"class":34},[28,665,89],{"class":38},[28,667,668,670],{"class":30,"line":392},[28,669,493],{"class":45},[28,671,672],{"class":38},": instant;\n",[28,674,676,679,681,684,687,690,693,695],{"class":30,"line":675},9,[28,677,678],{"class":34},"  scale",[28,680,62],{"class":38},[28,682,683],{"class":34},"var",[28,685,686],{"class":38},"(",[28,688,689],{"class":45},"--k-progress",[28,691,692],{"class":38},") ",[28,694,200],{"class":34},[28,696,89],{"class":38},[28,698,700,702,704,707],{"class":30,"line":699},10,[28,701,374],{"class":34},[28,703,62],{"class":38},[28,705,706],{"class":34},"left",[28,708,89],{"class":38},[28,710,712],{"class":30,"line":711},11,[28,713,95],{"class":38},[396,715],{"id":716},"scroll-linked",[10,718,719,720,722,723,119],{},"The progress bar reads ",[14,721,689],{}," in its own CSS. See ",[277,724,726],{"href":725},"\u002Fdocs\u002Fcss\u002F#reaction-progress","Reaction progress",[121,728,730],{"id":729},"stagger-and-delay","Stagger and delay",[10,732,733,736,737,158,739,741,742,744,745,748],{},[14,734,735],{},"--k-delay"," waits before a ",[14,738,407],{},[14,740,109],{},", or ",[14,743,115],{}," reaction starts. ",[14,746,747],{},"--k-stagger"," adds that delay once per sibling, so a list reacts in order.",[19,750,752],{"className":21,"code":751,"language":23,"meta":24,"style":24},".list > li {\n  --k-when: view once;\n  --k-opacity: 0 1;\n  --k-y: 20px 0;\n  --k-stagger: 60ms;\n}\n",[14,753,754,768,774,786,801,816],{"__ignoreMap":24},[28,755,756,759,762,766],{"class":30,"line":31},[28,757,758],{"class":34},".list",[28,760,761],{"class":68}," >",[28,763,765],{"class":764},"sPWt5"," li",[28,767,39],{"class":38},[28,769,770,772],{"class":30,"line":42},[28,771,46],{"class":45},[28,773,531],{"class":38},[28,775,776,778,780,782,784],{"class":30,"line":56},[28,777,536],{"class":45},[28,779,62],{"class":38},[28,781,166],{"class":34},[28,783,543],{"class":34},[28,785,89],{"class":38},[28,787,788,790,792,795,797,799],{"class":30,"line":78},[28,789,59],{"class":45},[28,791,62],{"class":38},[28,793,794],{"class":34},"20",[28,796,69],{"class":68},[28,798,559],{"class":34},[28,800,89],{"class":38},[28,802,803,806,808,811,814],{"class":30,"line":92},[28,804,805],{"class":45},"  --k-stagger",[28,807,62],{"class":38},[28,809,810],{"class":34},"60",[28,812,813],{"class":68},"ms",[28,815,89],{"class":38},[28,817,818],{"class":30,"line":357},[28,819,95],{"class":38},[10,821,822,823,826,827,831],{},"The order is the element's position among its Kinesis siblings. ",[14,824,825],{},"--k-index"," sets it yourself. ",[277,828,830],{"href":829},"\u002Fdocs\u002Ftext\u002F","Text splitting"," sets it on every character and word.",[121,833,835],{"id":834},"motion","Motion",[10,837,838,839,845,846,158,849,852],{},"Reactions use the element's ",[277,840,842],{"href":841},"\u002Fdocs\u002Fmotion\u002F",[14,843,844],{},"--k-motion",". Springs can overshoot. With ",[14,847,848],{},"bouncy",[14,850,851],{},"--k-scale: 1.2"," passes 1.2 briefly and settles back. Opacity stays between 0 and 1.",[854,855,856],"style",{},"html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}html pre.shiki code .sQhOw, html code.shiki .sQhOw{--shiki-default:#FFA657}html pre.shiki code .sH3jZ, html code.shiki .sH3jZ{--shiki-default:#8B949E}html pre.shiki code .suJrU, html code.shiki .suJrU{--shiki-default:#FF7B72}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sPWt5, html code.shiki .sPWt5{--shiki-default:#7EE787}",{"title":24,"searchDepth":56,"depth":56,"links":858},[859,860,861,862,863,864,865,866],{"id":123,"depth":42,"text":124},{"id":101,"depth":42,"text":101},{"id":407,"depth":42,"text":407},{"id":109,"depth":42,"text":109},{"id":115,"depth":42,"text":115},{"id":571,"depth":42,"text":572},{"id":729,"depth":42,"text":730},{"id":834,"depth":42,"text":835},"Animate between two states when the pointer comes near, an element is hovered or pressed, it scrolls into view, or the page scrolls.","md",{},"\u002Fdocs\u002Freactions","---\ntitle: Reactions\ndescription: Animate between two states when the pointer comes near, an element is hovered or pressed, it scrolls into view, or the page scrolls.\n---\n\nA reaction has a trigger and outputs. `--k-when` sets the trigger, and outputs set what changes. Kinesis turns the trigger into a progress value from 0 to 1, springs it, and moves each output with it.\n\n```css\n.card {\n  --k-when: hover;   \u002F* trigger *\u002F\n  --k-y: -6px;       \u002F* outputs *\u002F\n  --k-scale: 1.02;\n}\n```\n\nA dock is `near` with `--k-scale`. A pressable button is `press` with `--k-scale`. A reveal is `view` with `--k-opacity`.\n\n## Outputs\n\nOne value goes from rest to that value. Two values go from the first to the second.\n\n| Output | Rest | Example |\n| --- | --- | --- |\n| `--k-x`, `--k-y` | `0` | `--k-y: 24px 0` rises into place |\n| `--k-rotate` | `0deg` | `--k-rotate: -8deg 8deg` |\n| `--k-scale` | `1` | `--k-scale: 1.1` grows a little |\n| `--k-opacity` | `1` | `--k-opacity: 0 1` fades in |\n| `--k-blur` | `0` | `--k-blur: 8px 0` sharpens |\n| `--k-color` | current color | `--k-color: tomato` |\n| `--k-background` | current background | `--k-background: #0c1324 #2f6bff` |\n\nColors accept any CSS color. The browser mixes them in Oklab, which keeps transitions from passing through gray.\n\nTransform outputs add to [pointer effects](\u002Fdocs\u002Fpointer-effects\u002F) on the same element and respect `transform-origin`. A dock icon with `transform-origin: bottom` grows upward.\n\n## near\n\nThe pointer's closeness: 0 at `--k-radius`, 1 at the element's center.\n\n```css\n.dock__icon {\n  --k-when: near;\n  --k-radius: 120px;\n  --k-axis: x;\n  --k-scale: 1.65;\n  --k-y: -14px;\n  transform-origin: 50% 100%;\n}\n```\n\n::demo{id=\"dock\"}\n::\n\n`--k-axis: x` measures horizontal distance only, so the icons follow the pointer along the dock.\n\n## hover\n\n1 while the pointer is over the element. Keyboard focus also turns it on.\n\nKinesis tests hover against the element's resting position. An element that shrinks or tilts away from the pointer doesn't flicker at its edges, as it would with CSS `:hover`.\n\n```css\n.card {\n  --k-when: hover;\n  --k-y: -6px;\n}\n```\n\nTouch never turns hover on.\n\n## press\n\n1 while the element is pressed, by mouse, finger, or pen, or by Enter or Space when it has focus.\n\n```css\n.button {\n  --k-when: press;\n  --k-scale: 0.9;\n  --k-motion: bouncy;\n}\n```\n\n::demo{id=\"press-buttons\"}\n::\n\n## view\n\n1 once the element is a tenth of the way into the viewport, 0 when it leaves. `view once` stays at 1 after the first time.\n\n```css\n.feature {\n  --k-when: view once;\n  --k-opacity: 0 1;\n  --k-y: 28px 0;\n}\n```\n\n::demo{id=\"reveal\"}\n::\n\n## scroll and page\n\nThese follow scrolling continuously.\n\n- **`scroll`** is the element's trip through the viewport: 0 when its top enters at the bottom, 1 when its bottom leaves at the top.\n- **`page`** is the whole document: 0 at the top, 1 at the bottom.\n\n```css\n.tile {\n  --k-when: scroll;\n  --k-rotate: -120deg 120deg;\n}\n\n.reading-progress {\n  --k-when: page;\n  --k-motion: instant;\n  scale: var(--k-progress) 1;\n  transform-origin: left;\n}\n```\n\n::demo{id=\"scroll-linked\"}\n::\n\nThe progress bar reads `--k-progress` in its own CSS. See [Reaction progress](\u002Fdocs\u002Fcss\u002F#reaction-progress).\n\n## Stagger and delay\n\n`--k-delay` waits before a `hover`, `press`, or `view` reaction starts. `--k-stagger` adds that delay once per sibling, so a list reacts in order.\n\n```css\n.list > li {\n  --k-when: view once;\n  --k-opacity: 0 1;\n  --k-y: 20px 0;\n  --k-stagger: 60ms;\n}\n```\n\nThe order is the element's position among its Kinesis siblings. `--k-index` sets it yourself. [Text splitting](\u002Fdocs\u002Ftext\u002F) sets it on every character and word.\n\n## Motion\n\nReactions use the element's [`--k-motion`](\u002Fdocs\u002Fmotion\u002F). Springs can overshoot. With `bouncy`, `--k-scale: 1.2` passes 1.2 briefly and settles back. Opacity stays between 0 and 1.\n",{"title":5,"description":867},"docs\u002Freactions","_iZth3yiB0l57V4UlCnxX2uma-QJ-s5Nl90_vZCsheg",1791309902772]