// conditional element type
+ // undefined/null/false -> default element ()
+ // any other value is read at runtime, default when empty
```
### `props` (Pass-Through to `as` Component)
@@ -310,11 +338,20 @@ globalCss({ body: { margin: 0 }, "*": { boxSizing: "border-box" } });
const spin = keyframes({ from: { transform: "rotate(0)" }, to: { transform: "rotate(360deg)" } });
+
+// A const holding a keyframes name or a css() class is a build-time value
+const card = css({ p: 4 });
+css({ animationName: spin, selectors: { [`.${card}:hover &`]: { m: 1 } } });
```
+- Only a `const` declared in the same file works this way; an imported keyframes/class name is not known at build time.
+- `import * as Devup from "@devup-ui/react"` works (`Devup.css`, `Devup.keyframes`, `Devup.styled.div`, ``).
+- `styled()` takes any base: tag, Devup component, `motion.div`, `forwardRef(...)`, a variable. `null`/number/boolean/`undefined` bases are build errors.
+- Compiled imports are removed: a top-level alias (`const myCss = css`, `const Row = Flex`) compiles and is removed, but any other runtime read (`export const C = Box`, `[Box]`, `styled('div')` alone, an alias inside a function) is a **build error**.
+
### Dynamic Values with Custom Components
-`css()` only accepts **static values**. For dynamic values on custom components, use ``:
+`css()`, `globalCss()`, `keyframes()` and `stylex.create()` only accept values known at build time - literals, theme tokens, imported constants and module-level `const`s (templates, arithmetic and `Math.*` calls over them fold). Object, array and enum constants read as if written in place (`css(base)`, `{ ...base, color: 'red' }`, `_hover: hover`, `space[2]`, `Size.M`, ``), a later property replacing an earlier one. The build only runs code whose result is certain: `const`s, functions and enums this file declares, computing from literals and constants with exact built-ins (`String`, `Number`, `JSON`, `Object`, `Array`, string/array methods, `Math.abs/ceil/floor/round/trunc/sign/max/min/sqrt/fround/imul/clz32` and `Math` constants) - `const double = (n) => n * 2; css({ w: double(SIZE) })` is static. Imports are only read as the literal, object or array their module declares; code of another module never runs (`darken(0.1, PRIMARY)` with an imported `darken` is not computed). Not run: other globals (`window`, `Date`, `Intl`, ...), `Math.random` and approximate `Math` functions (`sin`, `pow`, ...), `**`, `toString(radix)`, `toLocale*`/`localeCompare`/`normalize`, `this`, `new`, classes, regex, `try`, getters, async/generators, JSX, `obj[key]()`, and functions writing module-level bindings - elements and `styled()` keep such values as CSS variables, while `css()`/`globalCss()`/`keyframes()` report a build error (as do `css()`/`styled()` given a whole style object computed that way). An object, array or enum constant that visible code changes (member assignment, `delete`, `++`, `push`/`sort`, `Object.assign`, changing elements in `for...of`/`forEach`, a method using `this`, passing it to an unknown function) is not a constant: elements read its members at runtime, and `css(obj)`, `styled.div(obj)` or `{...obj}` on an element is a build error naming where it changes. JSX props (except `ref`), `export default`, `module.exports` and `Object.freeze` only read it. Never mutate objects styles read; use theme tokens or props for values that change. A value known only at runtime (a prop, state, a parameter), and styles written where the build cannot read an object (a spread of an unknown object, `_hover={x}`, a computed key), are a **build error**. For dynamic values on custom components, use ``:
```tsx
// WRONG - css() cannot handle dynamic values
@@ -365,7 +402,7 @@ const spin = keyframes({ from: { transform: "rotate(0)" }, to: { transform: "rot
```
- **Colors**: Use with `$` prefix in JSX props: ``
-- **Typography**: Use with `$` prefix: ``
+- **Typography**: Use the preset name without `$`: ``. Under selectors or at-rules (`_hover={{ typography: "heading" }}`) the preset applies only under that condition.
- **Length**: Responsive length tokens: ``, ``
- **Shadow**: Responsive shadow tokens: ``
- **extends**: Inherit from base config files (deep merge, last wins)
@@ -548,6 +585,7 @@ One rule explains `Dynamic Values = CSS Variables`, `$token Scope` and
|------|--------|
| `` | Static class |
| `` | Static class per value - **preferred** |
+| `` where `PRIMARY` is a module-level or imported `const` string/number | Static class |
| `` where `colors` is declared elsewhere | CSS variable |
| `` | CSS variable (genuinely dynamic - correct) |
| `const s = { a: css({ ... }) }` then `className={s[v]}` | Neither - see below |
diff --git a/crates/devup-mcp/src/server/skills/manifest.json b/crates/devup-mcp/src/server/skills/manifest.json
index 06a911d6..c327b0d6 100644
--- a/crates/devup-mcp/src/server/skills/manifest.json
+++ b/crates/devup-mcp/src/server/skills/manifest.json
@@ -10,16 +10,16 @@
"usedFor": "The TSX devup_figma_export returns is devup-ui code. Without this the agent does not know its components are compile-time placeholders, that $token means devup.json, or that a style prop takes a responsive array.",
"repo": "dev-five-git/devup-ui",
"path": "SKILL.md",
- "commit": "c7295916e43657ee357e35f2682b78900c5232c2",
- "committedAt": "2026-09-21T14:05:45Z",
+ "commit": "cebcfb2a3f94649f297315e702dd468026474ff6",
+ "committedAt": "2026-09-30T02:49:17Z",
"documents": [
{
"path": "SKILL.md",
- "bytes": 23101,
- "sha256": "12787e610016e90ef9e483bd2b82e3c9312aec4b106fed29f07c816e5b0c7fba"
+ "bytes": 29525,
+ "sha256": "cd750ecb6b49340a2cf4c386ef7c69eeff4d495d115f58223b963430da9f87a2"
}
],
- "sourceUrl": "https://github.com/dev-five-git/devup-ui/blob/c7295916e43657ee357e35f2682b78900c5232c2/SKILL.md",
+ "sourceUrl": "https://github.com/dev-five-git/devup-ui/blob/cebcfb2a3f94649f297315e702dd468026474ff6/SKILL.md",
"latestUrl": "https://github.com/dev-five-git/devup-ui/blob/HEAD/SKILL.md"
},
{