[{"data":1,"prerenderedAt":1312},["ShallowReactive",2],{"blog-\u002Fblog\u002Fthe-ir-behind-your-ternary":3,"cover-\u002Fblog\u002Fthe-ir-behind-your-ternary":1311},{"id":4,"title":5,"body":6,"canonical":1299,"date":1300,"description":1301,"draft":1302,"duration":1299,"extension":422,"lang":1299,"meta":1303,"navigation":689,"part":245,"path":1304,"place":1299,"placeLink":1299,"readingTime":1305,"seo":1306,"seoTitle":1307,"series":1308,"stem":1309,"updated":1299,"__hash__":1310},"blog\u002Fblog\u002Fthe-ir-behind-your-ternary.md","The IR behind your ternary",{"type":7,"value":8,"toc":1287},"minimark",[9,16,19,31,45,91,94,116,123,126,136,141,144,147,150,154,157,372,375,413,430,433,442,446,451,454,461,464,491,506,510,518,521,603,606,624,627,631,634,640,646,652,710,713,771,775,778,901,907,917,921,924,1028,1031,1034,1038,1041,1085,1090,1096,1151,1172,1175,1189,1193,1196,1245,1248,1252,1255,1283],[10,11,12],"subtitle",{},[13,14,15],"p",{},"What Panda builds from your style before it writes a single class.",[17,18],"post-cover",{},[13,20,21],{},[22,23,24,25,30],"em",{},"Panda internals, part 5. Start with ",[26,27,29],"a",{"href":28},"\u002Fblog\u002Fbuild-once-at-build-time","Build once, at build time"," if you're new here.",[13,32,33,37,38,44],{},[26,34,36],{"href":35},"\u002Fblog\u002Fpanda-never-runs-your-code","Part 4"," ended on a promise. With ",[26,39,43],{"href":40,"rel":41},"https:\u002F\u002Fpanda-css.com\u002Fdocs\u002Fstyling\u002Fsource-transforms",[42],"nofollow","source transforms"," on, this call:",[46,47,52],"pre",{"className":48,"code":49,"language":50,"meta":51,"style":51},"language-ts shiki shiki-themes github-light github-dark","css({ fontSize: 'xl', color: active ? 'red.700' : 'gray.700' })\n","ts","",[53,54,55],"code",{"__ignoreMap":51},[56,57,60,64,68,72,75,79,82,85,88],"span",{"class":58,"line":59},"line",1,[56,61,63],{"class":62},"sScJk","css",[56,65,67],{"class":66},"sVt8B","({ fontSize: ",[56,69,71],{"class":70},"sZZnC","'xl'",[56,73,74],{"class":66},", color: active ",[56,76,78],{"class":77},"szBVR","?",[56,80,81],{"class":70}," 'red.700'",[56,83,84],{"class":77}," :",[56,86,87],{"class":70}," 'gray.700'",[56,89,90],{"class":66}," })\n",[13,92,93],{},"ships to the browser as this:",[46,95,99],{"className":96,"code":97,"language":98,"meta":51,"style":51},"language-js shiki shiki-themes github-light github-dark","active ? \"c_red.700 fs_xl\" : \"c_gray.700 fs_xl\"\n","js",[53,100,101],{"__ignoreMap":51},[56,102,103,106,108,111,113],{"class":58,"line":59},[56,104,105],{"class":66},"active ",[56,107,78],{"class":77},[56,109,110],{"class":70}," \"c_red.700 fs_xl\"",[56,112,84],{"class":77},[56,114,115],{"class":70}," \"c_gray.700 fs_xl\"\n",[13,117,118,119,122],{},"Two finished class strings and the condition you wrote. No ",[53,120,121],{},"css()"," call left.",[13,124,125],{},"To get there, Panda doesn't go straight from your code to class names. It builds something in between first.",[13,127,128],{},[22,129,130,131,135],{},"Just want the habits? Skip to ",[26,132,134],{"href":133},"#what-this-means-for-your-code","what this means for your code",".",[137,138,140],"h2",{"id":139},"something-in-between","Something in between",[13,142,143],{},"Compilers rarely turn their input straight into output. They first turn it into a model of the program that's easier to work with, then generate output from that model. The model is called an intermediate representation, or IR.",[13,145,146],{},"Panda has one for styles. It's called the StyleTree, and every style call gets one.",[13,148,149],{},"The reason Panda needs it is that one style can produce two outputs. There's the stylesheet, which every Panda project gets. And with source transforms on, there's your rewritten code. Both have to agree on what your style means, so both are built from the same tree.",[137,151,153],{"id":152},"the-shapes-in-the-tree","The shapes in the tree",[13,155,156],{},"A StyleTree node is one of a few shapes. Written as TypeScript, it looks roughly like this:",[46,158,160],{"className":48,"code":159,"language":50,"meta":51,"style":51},"type StyleTree =\n  | string | number | boolean | null\n  | { token: string }\n  | { [key: string]: StyleTree }\n  | StyleTree[]\n  | { branches: StyleTree[] }\n  | { ternary: Source, consequent: StyleTree, alternate: StyleTree }\n  | { and: Source, value: StyleTree }\n  | { open: true }\n  | { open: true, fallback: StyleTree }\n",[53,161,162,173,199,219,243,253,270,306,331,348],{"__ignoreMap":51},[56,163,164,167,170],{"class":58,"line":59},[56,165,166],{"class":77},"type",[56,168,169],{"class":62}," StyleTree",[56,171,172],{"class":77}," =\n",[56,174,176,179,183,186,189,191,194,196],{"class":58,"line":175},2,[56,177,178],{"class":77},"  |",[56,180,182],{"class":181},"sj4cs"," string",[56,184,185],{"class":77}," |",[56,187,188],{"class":181}," number",[56,190,185],{"class":77},[56,192,193],{"class":181}," boolean",[56,195,185],{"class":77},[56,197,198],{"class":181}," null\n",[56,200,202,204,207,211,214,216],{"class":58,"line":201},3,[56,203,178],{"class":77},[56,205,206],{"class":66}," { ",[56,208,210],{"class":209},"s4XuR","token",[56,212,213],{"class":77},":",[56,215,182],{"class":181},[56,217,218],{"class":66}," }\n",[56,220,222,224,227,230,232,234,237,239,241],{"class":58,"line":221},4,[56,223,178],{"class":77},[56,225,226],{"class":66}," { [",[56,228,229],{"class":209},"key",[56,231,213],{"class":77},[56,233,182],{"class":181},[56,235,236],{"class":66},"]",[56,238,213],{"class":77},[56,240,169],{"class":62},[56,242,218],{"class":66},[56,244,246,248,250],{"class":58,"line":245},5,[56,247,178],{"class":77},[56,249,169],{"class":62},[56,251,252],{"class":66},"[]\n",[56,254,256,258,260,263,265,267],{"class":58,"line":255},6,[56,257,178],{"class":77},[56,259,206],{"class":66},[56,261,262],{"class":209},"branches",[56,264,213],{"class":77},[56,266,169],{"class":62},[56,268,269],{"class":66},"[] }\n",[56,271,273,275,277,280,282,285,288,291,293,295,297,300,302,304],{"class":58,"line":272},7,[56,274,178],{"class":77},[56,276,206],{"class":66},[56,278,279],{"class":209},"ternary",[56,281,213],{"class":77},[56,283,284],{"class":62}," Source",[56,286,287],{"class":66},", ",[56,289,290],{"class":209},"consequent",[56,292,213],{"class":77},[56,294,169],{"class":62},[56,296,287],{"class":66},[56,298,299],{"class":209},"alternate",[56,301,213],{"class":77},[56,303,169],{"class":62},[56,305,218],{"class":66},[56,307,309,311,313,316,318,320,322,325,327,329],{"class":58,"line":308},8,[56,310,178],{"class":77},[56,312,206],{"class":66},[56,314,315],{"class":209},"and",[56,317,213],{"class":77},[56,319,284],{"class":62},[56,321,287],{"class":66},[56,323,324],{"class":209},"value",[56,326,213],{"class":77},[56,328,169],{"class":62},[56,330,218],{"class":66},[56,332,334,336,338,341,343,346],{"class":58,"line":333},9,[56,335,178],{"class":77},[56,337,206],{"class":66},[56,339,340],{"class":209},"open",[56,342,213],{"class":77},[56,344,345],{"class":181}," true",[56,347,218],{"class":66},[56,349,351,353,355,357,359,361,363,366,368,370],{"class":58,"line":350},10,[56,352,178],{"class":77},[56,354,206],{"class":66},[56,356,340],{"class":209},[56,358,213],{"class":77},[56,360,345],{"class":181},[56,362,287],{"class":66},[56,364,365],{"class":209},"fallback",[56,367,213],{"class":77},[56,369,169],{"class":62},[56,371,218],{"class":66},[13,373,374],{},"Most of it is plain values. The interesting shapes are the last five:",[376,377,378,386,395,401,407],"ul",{},[379,380,381,385],"li",{},[382,383,384],"strong",{},"Ternary"," keeps both sides. The condition itself isn't stored as a value. Panda keeps a pointer to where it sits in your source, so it can copy it out later.",[379,387,388,391,392,135],{},[382,389,390],{},"And"," is ",[53,393,394],{},"condition && value",[379,396,397,400],{},[382,398,399],{},"Branches"," holds alternatives with no condition to point at, like a conditional value imported from another file.",[379,402,403,406],{},[382,404,405],{},"Open"," means Panda can't know this value at build time.",[379,408,409,412],{},[382,410,411],{},"Open with a fallback"," means Panda can't know the value, but it knows what to fall back to.",[13,414,415,416,419,420,423,424,426,427,135],{},"Conditions like ",[53,417,418],{},"_hover"," and ",[53,421,422],{},"md"," aren't special nodes. They're ordinary nested objects, so a ternary inside ",[53,425,418],{}," just lives one level deeper, at ",[53,428,429],{},"_hover → color",[13,431,432],{},"Here's the running example as a tree:",[13,434,435],{},[436,437],"img",{"alt":438,"src":439,"width":440,"height":441},"A css() call becomes a StyleTree: an object with fontSize set to xl and color set to a ternary on active, with red.700 and gray.700 as its branches. The tree then feeds two outputs: the stylesheet, with fs_xl, c_red.700 and c_gray.700, and the rewritten code, active ? \"c_red.700 fs_xl\" : \"c_gray.700 fs_xl\".","\u002Fimages\u002Fblog\u002Fthe-ir-behind-your-ternary\u002Ftree.svg",1200,860,[137,443,445],{"id":444},"how-your-code-becomes-branches","How your code becomes branches",[13,447,448,450],{},[26,449,36],{"href":35}," covered how Panda works out values without running your code. The StyleTree is where that work lands.",[13,452,453],{},"When Panda can work out a ternary's condition at build time, it picks the matching side and stores only that. No ternary ends up in the tree.",[13,455,456,457,460],{},"When the condition depends on runtime, like ",[53,458,459],{},"active"," here, it keeps both sides in a ternary node.",[13,462,463],{},"The logical operators split two ways:",[376,465,466,475],{},[379,467,468,471,472,474],{},[53,469,470],{},"active && value"," becomes an ",[382,473,390],{}," node.",[379,476,477,419,480,483,484,486,487,490],{},[53,478,479],{},"a ?? b",[53,481,482],{},"a || b",", with a left side Panda can't know, become ",[382,485,411],{},", where ",[53,488,489],{},"b"," is the fallback.",[13,492,493,494,497,498,501,502,505],{},"That last rule is the answer to part 4's opening puzzle. ",[53,495,496],{},"colorByType[type] ?? 'gray.100'"," is an open value with ",[53,499,500],{},"'gray.100'"," as its fallback. So ",[53,503,504],{},"gray.100"," is the only color Panda ever sees.",[137,507,509],{"id":508},"output-one-the-stylesheet","Output one: the stylesheet",[13,511,512,513,517],{},"To generate CSS, Panda flattens the tree into the atoms from ",[26,514,516],{"href":515},"\u002Fblog\u002Fevery-style-is-an-atom","part 2",". Every branch gets its atoms emitted, because Panda can't know which one will run.",[13,519,520],{},"So the running example produces three atoms:",[46,522,525],{"className":523,"code":524,"language":63,"meta":51,"style":51},"language-css shiki shiki-themes github-light github-dark",".fs_xl { font-size: var(--font-sizes-xl) }\n.c_red\\.700 { color: var(--colors-red-700) }\n.c_gray\\.700 { color: var(--colors-gray-700) }\n",[53,526,527,552,579],{"__ignoreMap":51},[56,528,529,532,534,537,540,543,546,549],{"class":58,"line":59},[56,530,531],{"class":62},".fs_xl",[56,533,206],{"class":66},[56,535,536],{"class":181},"font-size",[56,538,539],{"class":66},": ",[56,541,542],{"class":181},"var",[56,544,545],{"class":66},"(",[56,547,548],{"class":209},"--font-sizes-xl",[56,550,551],{"class":66},") }\n",[56,553,554,557,560,563,565,568,570,572,574,577],{"class":58,"line":175},[56,555,556],{"class":62},".c_red",[56,558,559],{"class":181},"\\.",[56,561,562],{"class":62},"700",[56,564,206],{"class":66},[56,566,567],{"class":181},"color",[56,569,539],{"class":66},[56,571,542],{"class":181},[56,573,545],{"class":66},[56,575,576],{"class":209},"--colors-red-700",[56,578,551],{"class":66},[56,580,581,584,586,588,590,592,594,596,598,601],{"class":58,"line":201},[56,582,583],{"class":62},".c_gray",[56,585,559],{"class":181},[56,587,562],{"class":62},[56,589,206],{"class":66},[56,591,567],{"class":181},[56,593,539],{"class":66},[56,595,542],{"class":181},[56,597,545],{"class":66},[56,599,600],{"class":209},"--colors-gray-700",[56,602,551],{"class":66},[13,604,605],{},"For the other shapes:",[376,607,608,614,619],{},[379,609,610,611,613],{},"An ",[382,612,390],{}," node emits its value.",[379,615,610,616,618],{},[382,617,340],{}," node with a fallback emits the fallback.",[379,620,610,621,623],{},[382,622,340],{}," node without one emits nothing, since there's nothing to emit.",[13,625,626],{},"This is the same for every Panda project, with or without source transforms.",[137,628,630],{"id":629},"output-two-your-code","Output two: your code",[13,632,633],{},"With source transforms on, the bundler plugin walks the same tree and rewrites the call.",[13,635,636,637,135],{},"It looks for each place in the tree that holds a condition. Then it moves the condition outward, to the edge of the whole call. Each branch gets the static styles plus its own value, and becomes a complete class string. That's how the opening call became ",[53,638,639],{},"active ? \"c_red.700 fs_xl\" : \"c_gray.700 fs_xl\"",[13,641,642,645],{},[53,643,644],{},"fs_xl"," appears in both strings, because each one has to be complete on its own.",[13,647,648,649,651],{},"Conditions nested under ",[53,650,418],{}," work the same way:",[46,653,655],{"className":96,"code":654,"language":98,"meta":51,"style":51},"\u002F\u002F you write\ncss({ fontSize: 'xl', _hover: { color: active ? 'red.700' : 'gray.700' } })\n\n\u002F\u002F your bundle ships\nactive ? \"fs_xl hover:c_red.700\" : \"fs_xl hover:c_gray.700\"\n",[53,656,657,663,685,691,696],{"__ignoreMap":51},[56,658,659],{"class":58,"line":59},[56,660,662],{"class":661},"sJ8bj","\u002F\u002F you write\n",[56,664,665,667,669,671,674,676,678,680,682],{"class":58,"line":175},[56,666,63],{"class":62},[56,668,67],{"class":66},[56,670,71],{"class":70},[56,672,673],{"class":66},", _hover: { color: active ",[56,675,78],{"class":77},[56,677,81],{"class":70},[56,679,84],{"class":77},[56,681,87],{"class":70},[56,683,684],{"class":66}," } })\n",[56,686,687],{"class":58,"line":201},[56,688,690],{"emptyLinePlaceholder":689},true,"\n",[56,692,693],{"class":58,"line":221},[56,694,695],{"class":661},"\u002F\u002F your bundle ships\n",[56,697,698,700,702,705,707],{"class":58,"line":245},[56,699,105],{"class":66},[56,701,78],{"class":77},[56,703,704],{"class":70}," \"fs_xl hover:c_red.700\"",[56,706,84],{"class":77},[56,708,709],{"class":70}," \"fs_xl hover:c_gray.700\"\n",[13,711,712],{},"And a conditional spread is just a ternary with an empty side:",[46,714,716],{"className":96,"code":715,"language":98,"meta":51,"style":51},"\u002F\u002F you write\ncss({ fontSize: 'xl', ...(active && { color: 'red.700' }) })\n\n\u002F\u002F your bundle ships\nactive ? \"c_red.700 fs_xl\" : \"fs_xl\"\n",[53,717,718,722,750,754,758],{"__ignoreMap":51},[56,719,720],{"class":58,"line":59},[56,721,662],{"class":661},[56,723,724,726,728,730,732,735,738,741,744,747],{"class":58,"line":175},[56,725,63],{"class":62},[56,727,67],{"class":66},[56,729,71],{"class":70},[56,731,287],{"class":66},[56,733,734],{"class":77},"...",[56,736,737],{"class":66},"(active ",[56,739,740],{"class":77},"&&",[56,742,743],{"class":66}," { color: ",[56,745,746],{"class":70},"'red.700'",[56,748,749],{"class":66}," }) })\n",[56,751,752],{"class":58,"line":201},[56,753,690],{"emptyLinePlaceholder":689},[56,755,756],{"class":58,"line":221},[56,757,695],{"class":661},[56,759,760,762,764,766,768],{"class":58,"line":245},[56,761,105],{"class":66},[56,763,78],{"class":77},[56,765,110],{"class":70},[56,767,84],{"class":77},[56,769,770],{"class":70}," \"fs_xl\"\n",[137,772,774],{"id":773},"two-conditions-not-four-strings","Two conditions, not four strings",[13,776,777],{},"Add a second condition and you might expect four strings, one for every combination. That's not what happens:",[46,779,781],{"className":96,"code":780,"language":98,"meta":51,"style":51},"\u002F\u002F you write\ncss({\n  fontSize: 'xl',\n  color: active ? 'red.700' : 'gray.700',\n  padding: compact ? '2' : '4',\n})\n\n\u002F\u002F your bundle ships\n\"fs_xl\" + \" \" + (active ? \"c_red.700\" : \"c_gray.700\") + \" \" + (compact ? \"p_2\" : \"p_4\")\n",[53,782,783,787,794,804,819,836,841,845,849],{"__ignoreMap":51},[56,784,785],{"class":58,"line":59},[56,786,662],{"class":661},[56,788,789,791],{"class":58,"line":175},[56,790,63],{"class":62},[56,792,793],{"class":66},"({\n",[56,795,796,799,801],{"class":58,"line":201},[56,797,798],{"class":66},"  fontSize: ",[56,800,71],{"class":70},[56,802,803],{"class":66},",\n",[56,805,806,809,811,813,815,817],{"class":58,"line":221},[56,807,808],{"class":66},"  color: active ",[56,810,78],{"class":77},[56,812,81],{"class":70},[56,814,84],{"class":77},[56,816,87],{"class":70},[56,818,803],{"class":66},[56,820,821,824,826,829,831,834],{"class":58,"line":245},[56,822,823],{"class":66},"  padding: compact ",[56,825,78],{"class":77},[56,827,828],{"class":70}," '2'",[56,830,84],{"class":77},[56,832,833],{"class":70}," '4'",[56,835,803],{"class":66},[56,837,838],{"class":58,"line":255},[56,839,840],{"class":66},"})\n",[56,842,843],{"class":58,"line":272},[56,844,690],{"emptyLinePlaceholder":689},[56,846,847],{"class":58,"line":308},[56,848,695],{"class":661},[56,850,851,854,857,860,862,865,867,870,872,875,878,881,883,885,888,890,893,895,898],{"class":58,"line":333},[56,852,853],{"class":70},"\"fs_xl\"",[56,855,856],{"class":77}," +",[56,858,859],{"class":70}," \" \"",[56,861,856],{"class":77},[56,863,864],{"class":66}," (active ",[56,866,78],{"class":77},[56,868,869],{"class":70}," \"c_red.700\"",[56,871,84],{"class":77},[56,873,874],{"class":70}," \"c_gray.700\"",[56,876,877],{"class":66},") ",[56,879,880],{"class":77},"+",[56,882,859],{"class":70},[56,884,856],{"class":77},[56,886,887],{"class":66}," (compact ",[56,889,78],{"class":77},[56,891,892],{"class":70}," \"p_2\"",[56,894,84],{"class":77},[56,896,897],{"class":70}," \"p_4\"",[56,899,900],{"class":66},")\n",[13,902,903,904,906],{},"Each condition gets its own small ternary, and the pieces are joined. Atoms that every branch shares, like ",[53,905,644],{}," here, are pulled out and written once. Each new condition adds one ternary, so the output grows linearly.",[13,908,909,910,912,913,916],{},"That works because each atom is independent. ",[53,911,567],{}," doesn't care what ",[53,914,915],{},"padding"," is.",[137,918,920],{"id":919},"when-it-does-multiply","When it does multiply",[13,922,923],{},"Recipes are different, and so are patterns with default values. A recipe's default variants and compound variants depend on the whole selection, not one variant at a time. So for these, Panda builds every combination as a decision tree:",[46,925,927],{"className":96,"code":926,"language":98,"meta":51,"style":51},"\u002F\u002F you write\nbadge({ tone: danger ? 'danger' : 'neutral', size: big ? 'lg' : 'sm' })\n\n\u002F\u002F your bundle ships\n\"badge\" + \" \" + (danger\n  ? (big ? \"badge--tone_danger badge--size_lg\" : \"badge--tone_danger badge--size_sm\")\n  : big ? \"badge--tone_neutral badge--size_lg\" : \"badge--tone_neutral badge--size_sm\")\n",[53,928,929,933,966,970,974,988,1008],{"__ignoreMap":51},[56,930,931],{"class":58,"line":59},[56,932,662],{"class":661},[56,934,935,938,941,943,946,948,951,954,956,959,961,964],{"class":58,"line":175},[56,936,937],{"class":62},"badge",[56,939,940],{"class":66},"({ tone: danger ",[56,942,78],{"class":77},[56,944,945],{"class":70}," 'danger'",[56,947,84],{"class":77},[56,949,950],{"class":70}," 'neutral'",[56,952,953],{"class":66},", size: big ",[56,955,78],{"class":77},[56,957,958],{"class":70}," 'lg'",[56,960,84],{"class":77},[56,962,963],{"class":70}," 'sm'",[56,965,90],{"class":66},[56,967,968],{"class":58,"line":201},[56,969,690],{"emptyLinePlaceholder":689},[56,971,972],{"class":58,"line":221},[56,973,695],{"class":661},[56,975,976,979,981,983,985],{"class":58,"line":245},[56,977,978],{"class":70},"\"badge\"",[56,980,856],{"class":77},[56,982,859],{"class":70},[56,984,856],{"class":77},[56,986,987],{"class":66}," (danger\n",[56,989,990,993,996,998,1001,1003,1006],{"class":58,"line":255},[56,991,992],{"class":77},"  ?",[56,994,995],{"class":66}," (big ",[56,997,78],{"class":77},[56,999,1000],{"class":70}," \"badge--tone_danger badge--size_lg\"",[56,1002,84],{"class":77},[56,1004,1005],{"class":70}," \"badge--tone_danger badge--size_sm\"",[56,1007,900],{"class":66},[56,1009,1010,1013,1016,1018,1021,1023,1026],{"class":58,"line":272},[56,1011,1012],{"class":77},"  :",[56,1014,1015],{"class":66}," big ",[56,1017,78],{"class":77},[56,1019,1020],{"class":70}," \"badge--tone_neutral badge--size_lg\"",[56,1022,84],{"class":77},[56,1024,1025],{"class":70}," \"badge--tone_neutral badge--size_sm\"",[56,1027,900],{"class":66},[13,1029,1030],{},"That gets big fast. Two conditions make four strings, five make thirty-two, and every one of them is a full class string. At some point the rewrite stops paying off: the strings Panda would inline end up bigger than the short recipe call they replace. So Panda caps it at 16 combinations. A recipe call with more than that stays a runtime call, which is the smaller option.",[13,1032,1033],{},"There's also a separate cap for any single call: past 64 conditional sites, Panda doesn't rewrite it at all.",[137,1035,1037],{"id":1036},"when-the-tree-has-an-unknown-in-it","When the tree has an unknown in it",[13,1039,1040],{},"A call can't become a fixed string if some value in it is open. But Panda doesn't give up on the whole call. It rewrites what it can and leaves only the unknown part to the runtime:",[46,1042,1044],{"className":96,"code":1043,"language":98,"meta":51,"style":51},"\u002F\u002F you write\ncss({ fontSize: 'xl', width: props.width })\n\n\u002F\u002F your bundle ships\n__pcx(\"fs_xl\", css({ width: props.width }))\n",[53,1045,1046,1050,1061,1065,1069],{"__ignoreMap":51},[56,1047,1048],{"class":58,"line":59},[56,1049,662],{"class":661},[56,1051,1052,1054,1056,1058],{"class":58,"line":175},[56,1053,63],{"class":62},[56,1055,67],{"class":66},[56,1057,71],{"class":70},[56,1059,1060],{"class":66},", width: props.width })\n",[56,1062,1063],{"class":58,"line":201},[56,1064,690],{"emptyLinePlaceholder":689},[56,1066,1067],{"class":58,"line":221},[56,1068,695],{"class":661},[56,1070,1071,1074,1076,1078,1080,1082],{"class":58,"line":245},[56,1072,1073],{"class":62},"__pcx",[56,1075,545],{"class":66},[56,1077,853],{"class":70},[56,1079,287],{"class":66},[56,1081,63],{"class":62},[56,1083,1084],{"class":66},"({ width: props.width }))\n",[13,1086,1087,1089],{},[53,1088,1073],{}," is a tiny helper the transform imports to join the two halves.",[13,1091,1092,1093,1095],{},"Property-level ",[53,1094,740],{}," lands in the same place:",[46,1097,1099],{"className":96,"code":1098,"language":98,"meta":51,"style":51},"\u002F\u002F you write\ncss({ fontSize: 'xl', color: active && 'red.700' })\n\n\u002F\u002F your bundle ships\n__pcx(\"fs_xl\", css({ color: active && 'red.700' }))\n",[53,1100,1101,1105,1121,1125,1129],{"__ignoreMap":51},[56,1102,1103],{"class":58,"line":59},[56,1104,662],{"class":661},[56,1106,1107,1109,1111,1113,1115,1117,1119],{"class":58,"line":175},[56,1108,63],{"class":62},[56,1110,67],{"class":66},[56,1112,71],{"class":70},[56,1114,74],{"class":66},[56,1116,740],{"class":77},[56,1118,81],{"class":70},[56,1120,90],{"class":66},[56,1122,1123],{"class":58,"line":201},[56,1124,690],{"emptyLinePlaceholder":689},[56,1126,1127],{"class":58,"line":221},[56,1128,695],{"class":661},[56,1130,1131,1133,1135,1137,1139,1141,1144,1146,1148],{"class":58,"line":245},[56,1132,1073],{"class":62},[56,1134,545],{"class":66},[56,1136,853],{"class":70},[56,1138,287],{"class":66},[56,1140,63],{"class":62},[56,1142,1143],{"class":66},"({ color: active ",[56,1145,740],{"class":77},[56,1147,81],{"class":70},[56,1149,1150],{"class":66}," }))\n",[13,1152,1153,1154,1157,1158,1161,1162,1164,1165,287,1168,1171],{},"The spread version above did get rewritten, so why not this one? The difference is the falsy side. ",[53,1155,1156],{},"active && { color: 'red.700' }"," is either an object or nothing to merge. But ",[53,1159,1160],{},"active && 'red.700'"," evaluates to whatever ",[53,1163,459],{}," is when it's falsy: ",[53,1166,1167],{},"false",[53,1169,1170],{},"0",", an empty string. Panda can't turn an unknown value like that into a fixed class, so it hands it to the runtime.",[13,1173,1174],{},"Two more cases keep the whole call at runtime:",[376,1176,1177,1183],{},[379,1178,1179,1182],{},[382,1180,1181],{},"Two conditions writing the same property."," In an object, the last write wins. Separate atomic classes can't express \"the last one wins\", so Panda leaves the call alone.",[379,1184,1185,1188],{},[382,1186,1187],{},"Conditions that live in another file."," When a conditional value comes through an import, Panda knows both branches, so the stylesheet still gets both. But the condition itself is in the other file, so there's nothing local to copy into the rewrite.",[137,1190,1192],{"id":1191},"what-this-means-for-your-code","What this means for your code",[13,1194,1195],{},"Most of this happens without you thinking about it. A few habits keep more calls fully rewritten:",[376,1197,1198,1215,1227,1233,1239],{},[379,1199,1200,1203,1204,1207,1208,1211,1212,135],{},[382,1201,1202],{},"Ternaries and conditional spreads compile away."," Prefer ",[53,1205,1206],{},"...(active && { color: 'red.700' })"," or ",[53,1209,1210],{},"active ? 'red.700' : undefined"," over ",[53,1213,1214],{},"color: active && 'red.700'",[379,1216,1217,1226],{},[382,1218,1219,419,1222,1225],{},[53,1220,1221],{},"??",[53,1223,1224],{},"||"," on a runtime value keep that value at runtime."," Only the fallback gets CSS. If you know all the possible values, use a recipe or a lookup that Panda can read.",[379,1228,1229,1232],{},[382,1230,1231],{},"Keep the condition next to the call."," A condition imported from another file still gets its CSS, but not the rewrite.",[379,1234,1235,1238],{},[382,1236,1237],{},"Give runtime values their own property."," Everything else in the call still becomes classes.",[379,1240,1241,1244],{},[382,1242,1243],{},"One variant beats five booleans."," A recipe with many conditional variants can hit the 16-combination cap. A single variant with several values doesn't multiply.",[13,1246,1247],{},"None of these are required. A call that can't be rewritten still works, it just keeps its runtime form.",[137,1249,1251],{"id":1250},"one-tree-two-outputs","One tree, two outputs",[13,1253,1254],{},"Both outputs come from one model of your style, so they always agree.",[13,1256,1257],{},[22,1258,1259,1260,419,1263,1266,1267,287,1269,287,1272,287,1276,287,1279,135],{},"Next in the series: how Panda makes variants fast, and what ",[53,1261,1262],{},"cva",[53,1264,1265],{},"sva"," do with the same combination logic. If you missed the earlier parts: ",[26,1268,29],{"href":28},[26,1270,1271],{"href":515},"Every style is an atom",[26,1273,1275],{"href":1274},"\u002Fblog\u002Flook-it-up-once","Look it up once",[26,1277,1278],{"href":35},"Panda never runs your code",[26,1280,1282],{"href":1281},"\u002Fblog\u002Fwhat-runtime-means-in-panda","What runtime means in Panda",[1284,1285,1286],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}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 .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":51,"searchDepth":175,"depth":175,"links":1288},[1289,1290,1291,1292,1293,1294,1295,1296,1297,1298],{"id":139,"depth":175,"text":140},{"id":152,"depth":175,"text":153},{"id":444,"depth":175,"text":445},{"id":508,"depth":175,"text":509},{"id":629,"depth":175,"text":630},{"id":773,"depth":175,"text":774},{"id":919,"depth":175,"text":920},{"id":1036,"depth":175,"text":1037},{"id":1191,"depth":175,"text":1192},{"id":1250,"depth":175,"text":1251},null,"2026-11-04","Before Panda CSS writes a single class, it turns your style into a tree. How that tree feeds both the stylesheet and the rewritten code, and when a call can't be rewritten.",false,{},"\u002Fblog\u002Fthe-ir-behind-your-ternary","9min",{"title":5,"description":1301},"The IR behind your ternary: how Panda CSS turns styles into a StyleTree","Panda internals","blog\u002Fthe-ir-behind-your-ternary","7vY8tMoRVK1tWstgWTYrDLcddFGykCkXO9uEheA45K0",{"series":1308,"part":245,"total":245},1793824276144]