Mixins / foldkit-mixins
The stylesheet as a file
Written into every page, the stylesheet is sent again with each response and
parsed again by the server's checks of the page. foldkit-mixins/vite writes
it once, as a hashed file in the browser build, and gives the server its
address; the page links it:
// vite.config.ts
import { styles } from 'foldkit-mixins/vite'
export default defineConfig({
plugins: [styles({ sheet: '/src/style.ts' })],
})// the server entry: a link in the document's head, so the first paint waits for it
import { href } from 'virtual:foldkit-styles'
const head = `<link rel="stylesheet" href="${href}" data-foldkit-styles-href>`sheet is a module that exports the stylesheet text as stylesheet
(Style.stylesheet(...), or an AppStyle.make result). The file is that
sheet followed by Style.complete(sheet)'s addition: every class and global
rule the process compiled that the sheet does not hold. The plugin bundles the
sheet module (every module it imports is kept, since compiling a Style is a
side effect), so import the application's styled modules from it. Declare the
virtual module for TypeScript (declare module 'virtual:foldkit-styles' { export const href: string }).
- Build.
assets/styles-<hash>.cssis written by theclientbuild, named by its content;hrefcarries Vite'sbase, which must be absolute. A?urlimport in the sheet (a font) is the address the browser build gives it. - Dev.
hrefis/__foldkit-styles.css, served by the dev server from the modules it has loaded and read again after an edit, so the server entry has one code path. - Browser. The
data-foldkit-styles-hrefmark tells the injector the link is a stylesheet: once it loads, the injector reads its rules and skips every class and global rule it holds; a class drawn before it loads waits for it. A sheet the browser withholds (cross-origin without CORS) counts as empty, so its classes are injected again rather than lost. - Without the plugin,
Style.usedIn(html)still writes what one page uses.
@foldkit/ui
foldkit-mixins-ui adapts @foldkit/ui components that expose attribute bundles or a consumer
render seam. Button, Input, Checkbox, Disclosure, Dialog, Popover, Tooltip, Tabs, RadioGroup,
Calendar and others are covered. The Slider is drawn by foldkit-mixins-ui itself, for one number
or a range, rather than adapted.
Some components build their entire element tree internally and expose no attachment seam; those cannot be adapted without changing the component API. Others simply do not have an adapter yet. See the guide for the current boundary.
Status
The API is still settling (0.2.x). This package replaces none of Foldkit's state or effect
machinery — Commands, Subscriptions, Mounts, ManagedResources, Models or Submodels. Its job is
narrower: make view customization explicit, typed and composable.
See also
- Inside-out view composition — the mental model and when to use it.
foldkit-mixins-surface— bind a Surface projection and Message subset to a SlotView.foldkit-mixins-ui— adapters for@foldkit/ui.examples/mixins— a focused runnable trace.examples/todo-app— a whole application styled this way.