[{"data":1,"prerenderedAt":745},["ShallowReactive",2],{"landing-copy":3,"\u002Fdocs\u002Fv1\u002Fgetting-started\u002Ftailwind-css":65,"nav:v1":603},{"id":4,"extension":5,"meta":6,"sections":7,"stem":62,"tagline":63,"__hash__":64},"landing\u002Flanding.yml","yml",{},[8,18,22,29,33,40,47,51,57],{"id":9,"headline":10,"body":11,"cta":12,"secondary":15},"hero","The bare minimum for elegant interfaces.","Three classes, no framework, {css.kB}. A CSS and JavaScript library with no reset, no font, no runtime dependencies and no rule outside a `pui-` class; the browser does the work.",{"label":13,"to":14},"Get started","\u002Fdocs",{"label":16,"to":17},"Migrating from 0.x","\u002Fdocs\u002Fgetting-started\u002Fmigrating-from-0-x",{"id":19,"headline":20,"body":21},"size","{css.kB}. Measured, not promised.","`perfectui.css` is {css.bytes} bytes gzip; the optional JavaScript loader is {js.bytes}. The bars below are the same measurement run on the published builds of the alternatives.",{"id":23,"headline":24,"body":25,"cta":26},"classes","A shape, a style, a colour.","Every element is up to three classes you can combine freely: what it is, how the colour is applied, which colour. Seven colours and four styles give 28 looks per shape, and adding a colour never multiplies your classes.",{"label":27,"to":28},"See the components","\u002Fdocs\u002Fcomponents\u002Fbutton",{"id":30,"headline":31,"body":32},"overlays","Overlays without a plugin.","Modals are `\u003Cdialog>`, menus are `popover`, tooltips are `interestfor`, accordions are `\u003Cdetails>`. The optional loader downloads a fallback only when a browser is missing one of them.",{"id":34,"headline":35,"body":36,"cta":37},"mode-theme","One attribute for dark mode. One variable for your colour.","With no attribute, perfectui follows the operating system. Set `data-pui-mode` to choose, and `--pui-theme` to make every component yours.",{"label":38,"to":39},"Dark mode docs","\u002Fdocs\u002Fcustomization\u002Fdark-mode",{"id":41,"headline":42,"body":43,"cta":44},"tailwind","Your utilities always win.","One `@layer` line keeps Tailwind's reset below perfectui and every utility above it.",{"label":45,"to":46},"Tailwind guide","\u002Fdocs\u002Fgetting-started\u002Ftailwind-css",{"id":48,"headline":49,"body":50},"nothing-to-undo","Nothing you have to undo.","No reset to override, no font to remove, no `!important` to beat, no initialiser to call after rendering, no guard for server rendering. ESM only, nothing on `window`.",{"id":52,"headline":53,"body":54,"cta":55},"migration","Coming from 0.x?","1.0 is a rewrite: every class is prefixed, styles and colours are separate classes, and the browser replaced the JavaScript. The guide lists every change.",{"label":56,"to":17},"Read the migration guide",{"id":58,"headline":59,"body":60,"cta":61},"install","Install it your way.","A package for npm, yarn, pnpm or bun, or two tags from a CDN. Import everything or only the components you use.",{"label":13,"to":14},"landing","Components the browser already knows how to run.","QsxvMnCQ8bgawTVgX6YLkvZoqMKaQbFt0j1urNnrKQw",{"id":66,"title":67,"body":68,"changed":593,"description":594,"extension":595,"from":593,"meta":596,"navigation":279,"path":597,"seo":598,"since":593,"stem":599,"tags":600,"to":593,"__hash__":602},"docs_v1\u002Fdocs\u002Fv1\u002F01.getting-started\u002F03.tailwind-css.md","Tailwind CSS",{"type":69,"value":70,"toc":586},"minimark",[71,80,85,93,115,122,171,174,178,197,246,249,316,326,376,390,394,405,408,455,458,462,473,509,563,572,576,582],[72,73,74,75,79],"p",{},"Perfect UI does ",[76,77,78],"strong",{},"not"," depend on Tailwind, and Tailwind is not required to use it.",[81,82,84],"h2",{"id":83},"how-the-cascade-decides","How the cascade decides",[72,86,87,88,92],{},"Every rule Perfect UI ships lives inside a cascade layer, ",[89,90,91],"code",{},"@layer pui.*",". Two rules of the cascade decide who wins, before specificity is even compared:",[94,95,96,100],"ol",{},[97,98,99],"li",{},"CSS outside any layer beats every layer.",[97,101,102,103,106,107,110,111,114],{},"Between layers, the layer ",[76,104,105],{},"declared last"," wins. A layer is declared the first time its name appears, in an ",[89,108,109],{},"@layer a, b, c;"," statement or in an ",[89,112,113],{},"@layer"," block.",[72,116,117,118,121],{},"Your own CSS, written outside any layer, always beats the library with no ",[89,119,120],{},"!important",":",[123,124,129],"pre",{"className":125,"code":126,"language":127,"meta":128,"style":128},"language-css shiki shiki-themes perfectui-site",".checkout-button {\n  border-radius: 0; \u002F* beats pui-btn without !important *\u002F\n}\n","css","",[89,130,131,147,165],{"__ignoreMap":128},[132,133,136,140,144],"span",{"class":134,"line":135},"line",1,[132,137,139],{"class":138},"s8qk9",".",[132,141,143],{"class":142},"sz6eq","checkout-button",[132,145,146],{"class":138}," {\n",[132,148,150,153,155,159,162],{"class":134,"line":149},2,[132,151,152],{"class":142},"  border-radius",[132,154,121],{"class":138},[132,156,158],{"class":157},"s8AH5"," 0",[132,160,161],{"class":138},";",[132,163,164],{"class":138}," \u002F* beats pui-btn without !important *\u002F\n",[132,166,168],{"class":134,"line":167},3,[132,169,170],{"class":138},"}\n",[72,172,173],{},"Tailwind is different, and the version matters.",[81,175,177],{"id":176},"tailwind-v4-declare-the-layer-order-once","Tailwind v4: declare the layer order once",[72,179,180,181,184,185,188,189,192,193,196],{},"Tailwind v4 puts its own CSS in layers too: ",[89,182,183],{},"theme",", ",[89,186,187],{},"base"," (Preflight, its reset), ",[89,190,191],{},"components"," and ",[89,194,195],{},"utilities",". With two libraries in layers, the import order silently decides who wins, and both orders break something:",[198,199,200,216],"table",{},[201,202,203],"thead",{},[204,205,206,210,213],"tr",{},[207,208,209],"th",{},"Import order",[207,211,212],{},"Preflight vs the library",[207,214,215],{},"Utilities vs the library",[217,218,219,235],"tbody",{},[204,220,221,225,228],{},[222,223,224],"td",{},"Tailwind first, Perfect UI second",[222,226,227],{},"the library wins",[222,229,230,231,234],{},"the library wins: ",[89,232,233],{},"rounded-none"," is ignored",[204,236,237,240,243],{},[222,238,239],{},"Perfect UI first, Tailwind second",[222,241,242],{},"Preflight wins: buttons lose their fill and radius",[222,244,245],{},"utilities win",[72,247,248],{},"Declare the order yourself, as the first line of the stylesheet, and both problems disappear: Preflight sits below the library and utilities sit above it.",[123,250,252],{"className":125,"code":251,"language":127,"meta":128,"style":128},"\u002F* app.css *\u002F\n@layer theme, base, pui, components, utilities;\n\n@import \"tailwindcss\";\n@import \"@chrissgon\u002Fperfectui\u002Fperfectui.css\";\n",[89,253,254,259,275,281,300],{"__ignoreMap":128},[132,255,256],{"class":134,"line":135},[132,257,258],{"class":138},"\u002F* app.css *\u002F\n",[132,260,261,264,268,272],{"class":134,"line":149},[132,262,263],{"class":138},"@",[132,265,267],{"class":266},"sz5At","layer",[132,269,271],{"class":270},"stV6K"," theme, base, pui, components, utilities",[132,273,274],{"class":138},";\n",[132,276,277],{"class":134,"line":167},[132,278,280],{"emptyLinePlaceholder":279},true,"\n",[132,282,284,286,289,292,295,298],{"class":134,"line":283},4,[132,285,263],{"class":138},[132,287,288],{"class":266},"import",[132,290,291],{"class":138}," \"",[132,293,294],{"class":157},"tailwindcss",[132,296,297],{"class":138},"\"",[132,299,274],{"class":138},[132,301,303,305,307,309,312,314],{"class":134,"line":302},5,[132,304,263],{"class":138},[132,306,288],{"class":266},[132,308,291],{"class":138},[132,310,311],{"class":157},"@chrissgon\u002Fperfectui\u002Fperfectui.css",[132,313,297],{"class":138},[132,315,274],{"class":138},[72,317,318,321,322,325],{},[89,319,320],{},"pui"," in the list places every ",[89,323,324],{},"pui.*"," layer of the library at once, so its internal order is kept. Then utilities win as expected:",[327,328,329],"example",{},[123,330,334],{"className":331,"code":332,"language":333,"meta":128,"style":128},"language-html shiki shiki-themes perfectui-site","\u003C!-- keeps the solid theme fill from Perfect UI; the corners and width come from Tailwind -->\n\u003Cbutton class=\"pui-btn pui-solid pui-theme rounded-none w-full\">Save\u003C\u002Fbutton>\n","html",[89,335,336,341],{"__ignoreMap":128},[132,337,338],{"class":134,"line":135},[132,339,340],{"class":138},"\u003C!-- keeps the solid theme fill from Perfect UI; the corners and width come from Tailwind -->\n",[132,342,343,346,349,352,355,357,360,362,365,368,371,373],{"class":134,"line":149},[132,344,345],{"class":138},"\u003C",[132,347,348],{"class":266},"button",[132,350,351],{"class":142}," class",[132,353,354],{"class":138},"=",[132,356,297],{"class":138},[132,358,359],{"class":157},"pui-btn pui-solid pui-theme rounded-none w-full",[132,361,297],{"class":138},[132,363,364],{"class":138},">",[132,366,367],{"class":270},"Save",[132,369,370],{"class":138},"\u003C\u002F",[132,372,348],{"class":266},[132,374,375],{"class":138},">\n",[72,377,378,379,382,383,386,387,389],{},"If you import the component stylesheets one by one (",[89,380,381],{},"core.css"," plus ",[89,384,385],{},"components\u002F*.css","), the same line works, because every file of the library uses ",[89,388,324],{}," layers.",[81,391,393],{"id":392},"tailwind-v3-turn-preflight-off","Tailwind v3: turn Preflight off",[72,395,396,397,400,401,404],{},"Tailwind v3 writes its CSS outside any layer. Its utilities therefore beat the library, which is what you want, but so does Preflight, which resets every ",[89,398,399],{},"\u003Cbutton>"," to a transparent background: a ",[89,402,403],{},"pui-btn pui-solid"," loses its fill.",[72,406,407],{},"Turn Preflight off, since Perfect UI does not need it:",[123,409,413],{"className":410,"code":411,"language":412,"meta":128,"style":128},"language-js shiki shiki-themes perfectui-site","\u002F\u002F tailwind.config.js\nexport default {\n  corePlugins: { preflight: false }\n};\n","js",[89,414,415,420,430,450],{"__ignoreMap":128},[132,416,417],{"class":134,"line":135},[132,418,419],{"class":138},"\u002F\u002F tailwind.config.js\n",[132,421,422,425,428],{"class":134,"line":149},[132,423,424],{"class":266},"export",[132,426,427],{"class":266}," default",[132,429,146],{"class":138},[132,431,432,435,437,440,443,445,448],{"class":134,"line":167},[132,433,434],{"class":270},"  corePlugins",[132,436,121],{"class":138},[132,438,439],{"class":138}," {",[132,441,442],{"class":270}," preflight",[132,444,121],{"class":138},[132,446,447],{"class":270}," false ",[132,449,170],{"class":138},[132,451,452],{"class":134,"line":283},[132,453,454],{"class":138},"};\n",[72,456,457],{},"If the rest of your page needs Preflight, keep it and add the fill back only where you use Perfect UI buttons with your own unlayered rule; there is no layer order to declare in v3.",[81,459,461],{"id":460},"dark-mode","Dark mode",[72,463,464,465,468,469,472],{},"Perfect UI switches modes with ",[89,466,467],{},"data-pui-mode"," on ",[89,470,471],{},"\u003Chtml>",". Point Tailwind's dark variant at the same attribute so both react together:",[123,474,476],{"className":125,"code":475,"language":127,"meta":128,"style":128},"\u002F* Tailwind v4 *\u002F\n@import \"tailwindcss\";\n@custom-variant dark (&:where([data-pui-mode=\"dark\"], [data-pui-mode=\"dark\"] *));\n",[89,477,478,483,497],{"__ignoreMap":128},[132,479,480],{"class":134,"line":135},[132,481,482],{"class":138},"\u002F* Tailwind v4 *\u002F\n",[132,484,485,487,489,491,493,495],{"class":134,"line":149},[132,486,263],{"class":138},[132,488,288],{"class":266},[132,490,291],{"class":138},[132,492,294],{"class":157},[132,494,297],{"class":138},[132,496,274],{"class":138},[132,498,499,501,504,507],{"class":134,"line":167},[132,500,263],{"class":138},[132,502,503],{"class":266},"custom-variant",[132,505,506],{"class":270}," dark (&:where([data-pui-mode=\"dark\"], [data-pui-mode=\"dark\"] *))",[132,508,274],{"class":138},[123,510,512],{"className":410,"code":511,"language":412,"meta":128,"style":128},"\u002F\u002F Tailwind v3\nexport default {\n  darkMode: [\"selector\", '[data-pui-mode=\"dark\"]']\n};\n",[89,513,514,519,527,559],{"__ignoreMap":128},[132,515,516],{"class":134,"line":135},[132,517,518],{"class":138},"\u002F\u002F Tailwind v3\n",[132,520,521,523,525],{"class":134,"line":149},[132,522,424],{"class":266},[132,524,427],{"class":266},[132,526,146],{"class":138},[132,528,529,532,534,537,539,542,544,547,550,553,556],{"class":134,"line":167},[132,530,531],{"class":270},"  darkMode",[132,533,121],{"class":138},[132,535,536],{"class":270}," [",[132,538,297],{"class":138},[132,540,541],{"class":157},"selector",[132,543,297],{"class":138},[132,545,546],{"class":138},",",[132,548,549],{"class":138}," '",[132,551,552],{"class":157},"[data-pui-mode=\"dark\"]",[132,554,555],{"class":138},"'",[132,557,558],{"class":270},"]\n",[132,560,561],{"class":134,"line":283},[132,562,454],{"class":138},[72,564,565,566,571],{},"See ",[567,568,570],"a",{"href":569},"\u002Fdocs\u002Fv1\u002Fcustomization\u002Fdark-mode","Dark Mode"," for how the attribute is set and persisted.",[81,573,575],{"id":574},"preflight","Preflight",[72,577,578,579,581],{},"Preflight is Tailwind's reset. Perfect UI ships no reset and styles no bare elements, but Preflight styles bare elements that Perfect UI components use, such as ",[89,580,399],{},", so it can remove a component's fill or radius when it wins the cascade. With Tailwind v4 the layer declaration above keeps it below the library; with Tailwind v3 turn it off. Measured with Tailwind 4.3.3 and 3.4.17 against Perfect UI 1.0.0-beta.1.",[583,584,585],"style",{},"html pre.shiki code .s8qk9, html code.shiki .s8qk9{--shiki-default:var(--site-code-punct)}html pre.shiki code .sz6eq, html code.shiki .sz6eq{--shiki-default:var(--site-code-attr)}html pre.shiki code .s8AH5, html code.shiki .s8AH5{--shiki-default:var(--site-code-value)}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 .sz5At, html code.shiki .sz5At{--shiki-default:var(--site-code-tag)}html pre.shiki code .stV6K, html code.shiki .stV6K{--shiki-default:var(--site-code-text)}",{"title":128,"searchDepth":149,"depth":149,"links":587},[588,589,590,591,592],{"id":83,"depth":149,"text":84},{"id":176,"depth":149,"text":177},{"id":392,"depth":149,"text":393},{"id":460,"depth":149,"text":461},{"id":574,"depth":149,"text":575},null,"Perfect UI and Tailwind complement each other: Perfect UI gives you components, Tailwind gives you layout, spacing and typography utilities.","md",{},"\u002Fdocs\u002Fv1\u002Fgetting-started\u002Ftailwind-css",{"title":67,"description":594},"docs\u002Fv1\u002F01.getting-started\u002F03.tailwind-css",[601],"guide","CkJlMU2eUFowKxGfqzxRT033c-DcGT1_jEy7lnIrwEg",[604],{"title":605,"path":14,"stem":606,"children":607,"page":634},"Docs","docs",[608],{"title":609,"path":610,"stem":611,"children":612,"page":634},"V1","\u002Fdocs\u002Fv1","docs\u002Fv1",[613,635,646,659,708],{"title":614,"path":615,"stem":616,"children":617,"page":634},"Getting Started","\u002Fdocs\u002Fv1\u002Fgetting-started","docs\u002Fv1\u002F01.getting-started",[618,622,626,627,630],{"title":619,"path":620,"stem":621},"Installation","\u002Fdocs\u002Fv1\u002Fgetting-started\u002Finstallation","docs\u002Fv1\u002F01.getting-started\u002F01.installation",{"title":623,"path":624,"stem":625},"TypeScript","\u002Fdocs\u002Fv1\u002Fgetting-started\u002Ftypescript","docs\u002Fv1\u002F01.getting-started\u002F02.typescript",{"title":67,"path":597,"stem":599},{"title":16,"path":628,"stem":629},"\u002Fdocs\u002Fv1\u002Fgetting-started\u002Fmigrating-from-0-x","docs\u002Fv1\u002F01.getting-started\u002F04.migrating-from-0-x",{"title":631,"path":632,"stem":633},"License","\u002Fdocs\u002Fv1\u002Fgetting-started\u002Flicense","docs\u002Fv1\u002F01.getting-started\u002F05.license",false,{"title":636,"path":637,"stem":638,"children":639,"page":634},"Customization","\u002Fdocs\u002Fv1\u002Fcustomization","docs\u002Fv1\u002F02.customization",[640,642],{"title":570,"path":569,"stem":641},"docs\u002Fv1\u002F02.customization\u002F01.dark-mode",{"title":643,"path":644,"stem":645},"Theme Color","\u002Fdocs\u002Fv1\u002Fcustomization\u002Ftheme-color","docs\u002Fv1\u002F02.customization\u002F02.theme-color",{"title":647,"path":648,"stem":649,"children":650,"page":634},"General","\u002Fdocs\u002Fv1\u002Fgeneral","docs\u002Fv1\u002F03.general",[651,655],{"title":652,"path":653,"stem":654},"Layout Group","\u002Fdocs\u002Fv1\u002Fgeneral\u002Flayout-group","docs\u002Fv1\u002F03.general\u002F01.layout-group",{"title":656,"path":657,"stem":658},"Float","\u002Fdocs\u002Fv1\u002Fgeneral\u002Ffloat","docs\u002Fv1\u002F03.general\u002F02.float",{"title":660,"path":661,"stem":662,"children":663,"page":634},"Components","\u002Fdocs\u002Fv1\u002Fcomponents","docs\u002Fv1\u002F04.components",[664,668,672,676,680,684,688,692,696,700,704],{"title":665,"path":666,"stem":667},"Accordion","\u002Fdocs\u002Fv1\u002Fcomponents\u002Faccordion","docs\u002Fv1\u002F04.components\u002F01.accordion",{"title":669,"path":670,"stem":671},"Badge","\u002Fdocs\u002Fv1\u002Fcomponents\u002Fbadge","docs\u002Fv1\u002F04.components\u002F02.badge",{"title":673,"path":674,"stem":675},"Button","\u002Fdocs\u002Fv1\u002Fcomponents\u002Fbutton","docs\u002Fv1\u002F04.components\u002F03.button",{"title":677,"path":678,"stem":679},"Card","\u002Fdocs\u002Fv1\u002Fcomponents\u002Fcard","docs\u002Fv1\u002F04.components\u002F04.card",{"title":681,"path":682,"stem":683},"Chip","\u002Fdocs\u002Fv1\u002Fcomponents\u002Fchip","docs\u002Fv1\u002F04.components\u002F05.chip",{"title":685,"path":686,"stem":687},"Dropdown","\u002Fdocs\u002Fv1\u002Fcomponents\u002Fdropdown","docs\u002Fv1\u002F04.components\u002F06.dropdown",{"title":689,"path":690,"stem":691},"List","\u002Fdocs\u002Fv1\u002Fcomponents\u002Flist","docs\u002Fv1\u002F04.components\u002F07.list",{"title":693,"path":694,"stem":695},"Modal","\u002Fdocs\u002Fv1\u002Fcomponents\u002Fmodal","docs\u002Fv1\u002F04.components\u002F08.modal",{"title":697,"path":698,"stem":699},"Table","\u002Fdocs\u002Fv1\u002Fcomponents\u002Ftable","docs\u002Fv1\u002F04.components\u002F09.table",{"title":701,"path":702,"stem":703},"Timeline","\u002Fdocs\u002Fv1\u002Fcomponents\u002Ftimeline","docs\u002Fv1\u002F04.components\u002F10.timeline",{"title":705,"path":706,"stem":707},"Tooltip","\u002Fdocs\u002Fv1\u002Fcomponents\u002Ftooltip","docs\u002Fv1\u002F04.components\u002F11.tooltip",{"title":709,"path":710,"stem":711,"children":712,"page":634},"Forms","\u002Fdocs\u002Fv1\u002Fforms","docs\u002Fv1\u002F05.forms",[713,717,721,725,729,733,737,741],{"title":714,"path":715,"stem":716},"Field Group","\u002Fdocs\u002Fv1\u002Fforms\u002Ffield-group","docs\u002Fv1\u002F05.forms\u002F01.field-group",{"title":718,"path":719,"stem":720},"Input","\u002Fdocs\u002Fv1\u002Fforms\u002Finput","docs\u002Fv1\u002F05.forms\u002F02.input",{"title":722,"path":723,"stem":724},"Input Group","\u002Fdocs\u002Fv1\u002Fforms\u002Finput-group","docs\u002Fv1\u002F05.forms\u002F03.input-group",{"title":726,"path":727,"stem":728},"Textarea","\u002Fdocs\u002Fv1\u002Fforms\u002Ftextarea","docs\u002Fv1\u002F05.forms\u002F04.textarea",{"title":730,"path":731,"stem":732},"Select","\u002Fdocs\u002Fv1\u002Fforms\u002Fselect","docs\u002Fv1\u002F05.forms\u002F05.select",{"title":734,"path":735,"stem":736},"Checkbox","\u002Fdocs\u002Fv1\u002Fforms\u002Fcheckbox","docs\u002Fv1\u002F05.forms\u002F06.checkbox",{"title":738,"path":739,"stem":740},"Radio","\u002Fdocs\u002Fv1\u002Fforms\u002Fradio","docs\u002Fv1\u002F05.forms\u002F07.radio",{"title":742,"path":743,"stem":744},"Switch","\u002Fdocs\u002Fv1\u002Fforms\u002Fswitch","docs\u002Fv1\u002F05.forms\u002F08.switch",1790369303495]