feat: move and expand Ebox playground references
Keep the runner generic, evaluate executable property expressions with ETAF-compatible quote semantics, and add the complete Grid reference beside the migrated Basic, Comprehensive, Flex, and Responsive fixtures.
This commit is contained in:
parent
748a578c31
commit
1e0568c7f9
@ -4,7 +4,7 @@
|
||||
- Status: Active
|
||||
- Last refreshed: 2026-08-05
|
||||
- Primary product surfaces: The `.ebox` files under `examples/`, the buffer opened by `ebox-playground-open`, and the generic file mode.
|
||||
- Evidence reviewed: `ebox-playground.el`, `examples/public-layout-gallery.ebox`, `tests/ebox-playground-tests.el`, `README.md`, `README.zh-CN.md`, and the rendered current example.
|
||||
- Evidence reviewed: `ebox-playground.el`, the `.ebox` fixtures under `examples/`, `tests/ebox-playground-tests.el`, `README.md`, `README.zh-CN.md`, and rendered gallery/reference previews.
|
||||
|
||||
## Brand
|
||||
- Personality: Precise, modern, restrained, and educational.
|
||||
@ -44,7 +44,7 @@
|
||||
- Existing components to reuse: `ebox-create`, `ebox-column`, `ebox-row`, `ebox-flex`, `ebox-grid`, and `ebox-spacer`.
|
||||
- New/changed components: Header band, capability section band, fixed/fractional track cards, placement cards, and public-contract footer.
|
||||
- Variants and states: Static semantic color families only.
|
||||
- Token/component ownership: Palette values and example composition live in `.ebox` fixtures; the runner owns only parsing and rendering.
|
||||
- Token/component ownership: Palette values and example composition live in `.ebox` fixtures; the runner owns only parsing and rendering. The migrated references remain data files, so adding a layout does not add a fixture-specific Elisp branch.
|
||||
|
||||
## Accessibility
|
||||
- Target standard: High contrast and readable labels in ordinary GUI Emacs themes.
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
- 状态:有效
|
||||
- 最近更新:2026-08-05
|
||||
- 主要产品界面:`examples/` 下的 `.ebox` 文件、`ebox-playground-open` 打开的缓冲区,以及通用文件模式。
|
||||
- 已审阅证据:`ebox-playground.el`、`examples/public-layout-gallery.ebox`、`tests/ebox-playground-tests.el`、`README.md`、`README.zh-CN.md` 和当前示例的实际渲染。
|
||||
- 已审阅证据:`ebox-playground.el`、`examples/` 下的 `.ebox` fixture、`tests/ebox-playground-tests.el`、`README.md`、`README.zh-CN.md` 以及画廊/参考文件的实际渲染。
|
||||
|
||||
## 品牌
|
||||
- 个性:精确、现代、克制、适合教学。
|
||||
@ -44,7 +44,7 @@
|
||||
- 复用的现有组件:`ebox-create`、`ebox-column`、`ebox-row`、`ebox-flex`、`ebox-grid` 和 `ebox-spacer`。
|
||||
- 新增/调整的组件:标题带、能力分区标题带、固定/分数轨道卡片、放置卡片和公开契约页脚。
|
||||
- 变体与状态:仅使用静态语义色组。
|
||||
- Token/组件归属:配色值和示例组合放在 `.ebox` fixture 中;运行器只负责解析和渲染。
|
||||
- Token/组件归属:配色值和示例组合放在 `.ebox` fixture 中;运行器只负责解析和渲染。迁移来的参考仍然是数据文件,新增布局不需要在 Elisp 中增加针对 fixture 的分支。
|
||||
|
||||
## 无障碍
|
||||
- 目标标准:在常见 GUI Emacs 主题下保持高对比度和标签可读性。
|
||||
|
||||
10
README.md
10
README.md
@ -1,6 +1,6 @@
|
||||
# ebox-playground
|
||||
|
||||
`ebox-playground` is the independent, generic file runner for Ebox DSL examples. It uses only public Ebox APIs; concrete layouts live in readable `.ebox` fixtures under `examples/`. The maintained gallery demonstrates fixed and fractional tracks, explicit Grid placement, and public Column/Flex/Grid composition with a restrained terracotta, sage, blue, and violet palette.
|
||||
`ebox-playground` is the independent, generic file runner for Ebox DSL examples. It uses only public Ebox APIs; concrete layouts live in readable `.ebox` fixtures under `examples/`. The migrated low-level fixtures include the original Basic, Comprehensive, Flex, and Responsive references, while `grid-reference.ebox` provides a complete Grid property gallery with the same restrained terracotta, sage, blue, violet, ochre, and teal visual language.
|
||||
|
||||
The gallery owns one definite 720 px canvas so its nested Grid examples cannot each reinterpret the surrounding viewport width. It fits a compact GUI Emacs window with at least 760 px of body width. `etaf-playground` remains the separate higher-level Component and Runtime showcase.
|
||||
|
||||
@ -15,4 +15,12 @@ The package also owns the `.ebox` file boundary. Visiting an Ebox DSL file selec
|
||||
(add-to-list 'auto-mode-alist '("\\.ebox\\'" . ebox-dsl-mode))
|
||||
```
|
||||
|
||||
The reference fixtures live directly under `examples/`. For example:
|
||||
|
||||
```elisp
|
||||
(ebox-playground-open-file
|
||||
(expand-file-name "examples/grid-reference.ebox"
|
||||
ebox-playground-directory))
|
||||
```
|
||||
|
||||
Run `make check EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs` from this directory.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# ebox-playground
|
||||
|
||||
`ebox-playground` 是 Ebox DSL 的独立通用文件运行器,只使用 Ebox 公共 API;具体布局都放在 `examples/` 下易读的 `.ebox` fixture 中。维护中的画廊通过这些源文件展示固定与分数轨道、显式 Grid 放置,以及公开的 Column/Flex/Grid 组合能力,并使用克制的陶土色、鼠尾草绿、蓝色与紫色配色。
|
||||
`ebox-playground` 是 Ebox DSL 的独立通用文件运行器,只使用 Ebox 公共 API;具体布局都放在 `examples/` 下易读的 `.ebox` fixture 中。迁移后的低层 fixture 包含原有的 Basic、Comprehensive、Flex 和 Responsive 参考;`grid-reference.ebox` 则用同一套克制的陶土色、鼠尾草绿、蓝色、赭石色和青绿色视觉语言,完整展示 Grid 属性。
|
||||
|
||||
画廊统一拥有一个明确的 720 px 画布,因此嵌套 Grid 不会各自重新解释外层视口宽度。只要 GUI Emacs 的正文区域不小于 760 px,它就能完整显示。高层 Component/Runtime 展示仍由独立的 `etaf-playground` 提供。
|
||||
|
||||
@ -15,4 +15,12 @@
|
||||
(add-to-list 'auto-mode-alist '("\\.ebox\\'" . ebox-dsl-mode))
|
||||
```
|
||||
|
||||
参考 fixture 直接位于 `examples/` 下。例如:
|
||||
|
||||
```elisp
|
||||
(ebox-playground-open-file
|
||||
(expand-file-name "examples/grid-reference.ebox"
|
||||
ebox-playground-directory))
|
||||
```
|
||||
|
||||
在该目录运行 `make check EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs`。
|
||||
|
||||
@ -31,8 +31,9 @@
|
||||
|
||||
(defun ebox-playground--source-form ()
|
||||
"Read the single Ebox DSL form from the current buffer."
|
||||
(ebox-playground--read-form
|
||||
(buffer-substring-no-properties (point-min) (point-max))))
|
||||
(ebox-playground--evaluate-form
|
||||
(ebox-playground--read-form
|
||||
(buffer-substring-no-properties (point-min) (point-max)))))
|
||||
|
||||
;;;###autoload
|
||||
(define-derived-mode ebox-dsl-mode emacs-lisp-mode "EboxDSL"
|
||||
@ -71,6 +72,40 @@
|
||||
:type 'file
|
||||
:group 'ebox-playground)
|
||||
|
||||
(defun ebox-playground--static-value-p (value)
|
||||
"Return non-nil when VALUE is a literal or explicitly quoted form."
|
||||
(or (null value) (numberp value) (stringp value) (characterp value)
|
||||
(keywordp value) (eq value t)
|
||||
(and (consp value) (memq (car value) '(quote function)))))
|
||||
|
||||
(defun ebox-playground--evaluate-value (value)
|
||||
"Evaluate executable DSL VALUE while preserving literal data values."
|
||||
(if (ebox-playground--static-value-p value)
|
||||
(if (and (consp value) (memq (car value) '(quote function)))
|
||||
(eval value nil)
|
||||
value)
|
||||
(eval value nil)))
|
||||
|
||||
(defun ebox-playground--evaluate-items (items)
|
||||
"Evaluate property values and recurse into child forms in ITEMS."
|
||||
(let (result)
|
||||
(while items
|
||||
(let ((item (pop items)))
|
||||
(if (keywordp item)
|
||||
(progn
|
||||
(unless items
|
||||
(error "Ebox playground: missing value for %S" item))
|
||||
(push item result)
|
||||
(push (ebox-playground--evaluate-value (pop items)) result))
|
||||
(push (ebox-playground--evaluate-form item) result))))
|
||||
(nreverse result)))
|
||||
|
||||
(defun ebox-playground--evaluate-form (form)
|
||||
"Evaluate property expressions in one structural DSL FORM."
|
||||
(if (and (consp form) (symbolp (car form)))
|
||||
(cons (car form) (ebox-playground--evaluate-items (cdr form)))
|
||||
form))
|
||||
|
||||
(defun ebox-playground--read-form (source)
|
||||
"Read one Ebox DSL form from SOURCE."
|
||||
(when (string-empty-p (string-trim source))
|
||||
@ -99,8 +134,9 @@
|
||||
(defun ebox-playground-view (&optional file)
|
||||
"Build the Ebox DSL form in FILE without buffer side effects."
|
||||
(ebox-build
|
||||
(ebox-playground--read-file
|
||||
(expand-file-name (or file ebox-playground-default-file)))))
|
||||
(ebox-playground--evaluate-form
|
||||
(ebox-playground--read-file
|
||||
(expand-file-name (or file ebox-playground-default-file))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun ebox-playground-open (&optional buffer-name)
|
||||
|
||||
@ -2,4 +2,6 @@
|
||||
|
||||
The `.ebox` files in this directory are the concrete layouts consumed by the generic `ebox-playground` runner. They are intentionally ordinary, reader-valid Ebox DSL forms so authors can copy, edit, and open them directly.
|
||||
|
||||
`public-layout-gallery.ebox` is the default fixture used by `M-x ebox-playground-open`. To render another fixture, visit it and press `C-c C-c`, or call `ebox-playground-open-file`.
|
||||
The file itself is the data form: structural forms stay unquoted, while literal list and symbol property values use quote just as they do in `etaf-view` (for example, `:gap '(1 (16))` and `:justify-content 'center`). An unquoted property value is an executable Elisp expression and is evaluated by the runner. The reader itself keeps read-time evaluation disabled.
|
||||
|
||||
`public-layout-gallery.ebox` is the default fixture used by `M-x ebox-playground-open`. The migrated low-level references live directly beside it: `basic.ebox`, `comprehensive.ebox`, `flex-reference.ebox`, `responsive-reference.ebox`, and `grid-reference.ebox`. The Grid reference covers track templates, implicit tracks, auto-flow, gaps, placement, spans, item alignment, and content alignment. To render another fixture, visit it and press `C-c C-c`, or call `ebox-playground-open-file`.
|
||||
|
||||
@ -2,4 +2,6 @@
|
||||
|
||||
此目录下的 `.ebox` 文件是通用 `ebox-playground` 运行器读取的具体布局。它们保持为普通、可读、可被 reader 读取的 Ebox DSL form,便于直接复制、编辑和打开。
|
||||
|
||||
`public-layout-gallery.ebox` 是 `M-x ebox-playground-open` 使用的默认 fixture。要渲染其他 fixture,可以访问该文件后按 `C-c C-c`,或调用 `ebox-playground-open-file`。
|
||||
文件本身就是 data form:结构表单保持不加 quote;list 和 symbol 类型的字面量属性值要和 `etaf-view` 一样加 quote,例如 `:gap '(1 (16))`、`:justify-content 'center`。未加 quote 的属性值会被运行器当作可执行的 Elisp 表达式求值;读取器本身仍然关闭 reader 求值。
|
||||
|
||||
`public-layout-gallery.ebox` 是 `M-x ebox-playground-open` 使用的默认 fixture。迁移来的低层参考和它并列放在 `examples/` 下:`basic.ebox`、`comprehensive.ebox`、`flex-reference.ebox`、`responsive-reference.ebox` 和 `grid-reference.ebox`。其中 Grid 参考覆盖轨道模板、隐式轨道、auto-flow、gap、placement、span、item 对齐和 content 对齐。要渲染其他 fixture,可以访问该文件后按 `C-c C-c`,或调用 `ebox-playground-open-file`。
|
||||
|
||||
7
examples/basic.ebox
Normal file
7
examples/basic.ebox
Normal file
@ -0,0 +1,7 @@
|
||||
(box :content "Playground file"
|
||||
:box-sizing 'border-box
|
||||
:padding '(1 (12))
|
||||
:border t
|
||||
:border-color "#2563EB"
|
||||
:bgcolor "#EFF6FF"
|
||||
:color "#1E3A8A")
|
||||
45
examples/comprehensive.ebox
Normal file
45
examples/comprehensive.ebox
Normal file
@ -0,0 +1,45 @@
|
||||
(column
|
||||
(box :content "Ebox comprehensive DSL showcase\nThe outer sections omit :width so Playground viewport sizing drives the layout."
|
||||
:padding '(1 (16)) :border "#334155"
|
||||
:bgcolor "#F8FAFC" :color "#0F172A" :text-align 'center)
|
||||
|
||||
(spacer :height 1)
|
||||
|
||||
(box :content "Width rule in this file\nContainer sections use auto width. Fixed widths remain only where the example demonstrates exact item sizing, basis, min-width, or max-width."
|
||||
:padding '(0 (14)) :border "#64748B"
|
||||
:bgcolor "#F8FAFC" :color "#111827" :wrap-mode 'word)
|
||||
|
||||
(spacer :height 1)
|
||||
|
||||
(flex
|
||||
:margin '(1 0 0 1) :padding '(1 (8))
|
||||
:border "#475569" :bgcolor "#F8FAFC"
|
||||
:flex-flow '(row wrap)
|
||||
:justify-content 'space-between :align-items 'center
|
||||
:align-content 'flex-start :row-gap 1 :column-gap '(12)
|
||||
(item
|
||||
:order -1 :flex-basis '(270) :align-self 'flex-start
|
||||
(box :content "item order -1\n:flex-basis 270\nalign-self start"
|
||||
:width '(270) :padding '(0 (8))
|
||||
:border "#BE185D" :bgcolor "#FCE7F3" :color "#831843"
|
||||
:wrap-mode 'word))
|
||||
(item
|
||||
:flex '(1 1 (220))
|
||||
(box :content "item :flex (1 1 220)\ngrow shrink basis"
|
||||
:width '(220) :height 4
|
||||
:padding '(0 (8)) :border "#1D4ED8"
|
||||
:bgcolor "#DBEAFE" :color "#111827" :wrap-mode 'word))
|
||||
(item
|
||||
:flex-grow 2 :flex-shrink 1 :flex-basis '(240)
|
||||
:align-self 'center
|
||||
(box :content "item grow 2\nshrink 1\nbasis 240"
|
||||
:width '(240) :height 4 :padding '(0 (8))
|
||||
:border "#B45309" :bgcolor "#FEF3C7" :color "#78350F"
|
||||
:wrap-mode 'word))
|
||||
(item :flex-shrink 3
|
||||
:flex-basis '(190)
|
||||
:align-self 'flex-end
|
||||
(box :content "item shrink 3\nbasis 190\nalign-self flex-end"
|
||||
:width '(190) :height 4 :padding '(0 (8))
|
||||
:border "#15803D" :bgcolor "#DCFCE7" :color "#14532D"
|
||||
:wrap-mode 'word))))
|
||||
463
examples/flex-reference.ebox
Normal file
463
examples/flex-reference.ebox
Normal file
@ -0,0 +1,463 @@
|
||||
(column ;; :height (viewport-height)
|
||||
:width '(viewport)
|
||||
(box :content "Ebox CSS Flex Reference\nA modern, self-explaining DSL gallery for CSS flex container and item properties."
|
||||
:padding '(1 (24)) :border "#2F3437"
|
||||
:bgcolor "#FAF7F0" :color "#1F2328" :text-align 'center)
|
||||
|
||||
(spacer :height 1)
|
||||
|
||||
(box :content "Container property: :flex-direction\nMain axis selection. Reverse values swap main-start and main-end while keeping source order intact."
|
||||
:padding '(0 (18)) :border "#D97757"
|
||||
:bgcolor "#FFF5ED" :color "#3D2B1F")
|
||||
(flex :flex-flow '(row wrap) :row-gap 1 :column-gap '(12) :padding '(0 (12))
|
||||
:border "#D97757" :border-top-p nil
|
||||
:bgcolor "#FFF8F2"
|
||||
(column
|
||||
(box :content "row" :width '(220) :padding '(0 (10)) :border "#D97757"
|
||||
:bgcolor "#FFFDF8" :color "#3D3A35" :text-align 'center)
|
||||
(flex :width '(220) :height 4 :padding '(0 (8)) :border "#D97757"
|
||||
:border-top-p nil
|
||||
:bgcolor "#FFF8F2" :flex-direction 'row :column-gap '(10) :align-items 'center
|
||||
(item (box :content "A" :width '(42) :height 1 :bgcolor "#F7C8B3" :text-align 'center))
|
||||
(item (box :content "B" :width '(42) :height 1 :bgcolor "#F0A88F" :text-align 'center))
|
||||
(item (box :content "C" :width '(42) :height 1 :bgcolor "#D97757" :color "#FFFFFF" :text-align 'center))))
|
||||
(column
|
||||
(box :content "row-reverse" :width '(220) :padding '(0 (10)) :border "#D97757"
|
||||
:bgcolor "#FFFDF8" :color "#3D3A35" :text-align 'center)
|
||||
(flex :width '(220) :height 4 :padding '(0 (8)) :border "#D97757"
|
||||
:border-top-p nil
|
||||
:bgcolor "#FFF8F2" :flex-direction 'row-reverse :column-gap '(10) :align-items 'center
|
||||
(item (box :content "A" :width '(42) :height 1 :bgcolor "#F7C8B3" :text-align 'center))
|
||||
(item (box :content "B" :width '(42) :height 1 :bgcolor "#F0A88F" :text-align 'center))
|
||||
(item (box :content "C" :width '(42) :height 1 :bgcolor "#D97757" :color "#FFFFFF" :text-align 'center))))
|
||||
(column
|
||||
(box :content "column" :width '(220) :padding '(0 (10)) :border "#D97757"
|
||||
:bgcolor "#FFFDF8" :color "#3D3A35" :text-align 'center)
|
||||
(flex :width '(220) :height 6 :padding '(0 (8)) :border "#D97757"
|
||||
:border-top-p nil
|
||||
:bgcolor "#FFF8F2" :flex-direction 'column :row-gap 1 :align-items 'stretch
|
||||
(item (box :content "A" :height 1 :bgcolor "#F7C8B3" :text-align 'center))
|
||||
(item (box :content "B" :height 1 :bgcolor "#F0A88F" :text-align 'center))
|
||||
(item (box :content "C" :height 1 :bgcolor "#D97757" :color "#FFFFFF" :text-align 'center))))
|
||||
(column
|
||||
(box :content "column-reverse" :width '(220) :padding '(0 (10)) :border "#D97757"
|
||||
:bgcolor "#FFFDF8" :color "#3D3A35" :text-align 'center)
|
||||
(flex :width '(220) :height 6 :padding '(0 (8)) :border "#D97757"
|
||||
:border-top-p nil
|
||||
:bgcolor "#FFF8F2" :flex-direction 'column-reverse :row-gap 1 :align-items 'stretch
|
||||
(item (box :content "A" :height 1 :bgcolor "#F7C8B3" :text-align 'center))
|
||||
(item (box :content "B" :height 1 :bgcolor "#F0A88F" :text-align 'center))
|
||||
(item (box :content "C" :height 1 :bgcolor "#D97757" :color "#FFFFFF" :text-align 'center)))))
|
||||
|
||||
(spacer :height 1)
|
||||
|
||||
(box :content "Container property: :flex-wrap\nLine creation. nowrap keeps one flex line; wrap creates new lines; wrap-reverse stacks lines from the opposite cross side."
|
||||
:padding '(0 (18)) :border "#5E7F6A"
|
||||
:bgcolor "#F3FAF4" :color "#24352A")
|
||||
(flex :flex-flow '(row wrap) :row-gap 1 :column-gap '(12) :padding '(0 (12))
|
||||
:border "#5E7F6A" :border-top-p nil
|
||||
:bgcolor "#F8FCF8"
|
||||
(column
|
||||
(box :content "nowrap" :max-width '(293) :padding '(0 (10)) :border "#5E7F6A"
|
||||
:bgcolor "#FFFDF8" :color "#3D3A35" :text-align 'center)
|
||||
(flex :max-width '(293) :padding '(0 (8)) :border "#5E7F6A"
|
||||
:border-top-p nil
|
||||
:bgcolor "#F8FCF8" :flex-wrap 'nowrap :column-gap '(8) :align-items 'center
|
||||
(item :flex-shrink 1 (box :content "A" :width '(92) :height 1 :bgcolor "#DCEBDD" :text-align 'center))
|
||||
(item :flex-shrink 1 (box :content "B" :width '(92) :height 1 :bgcolor "#BFD6C2" :text-align 'center))
|
||||
(item :flex-shrink 1 (box :content "C" :width '(92) :height 1 :bgcolor "#8FAF95" :text-align 'center))))
|
||||
(column
|
||||
(box :content "wrap" :max-width '(293) :padding '(0 (10)) :border "#5E7F6A"
|
||||
:bgcolor "#FFFDF8" :color "#3D3A35" :text-align 'center)
|
||||
(flex :max-width '(293) :padding '(0 (8)) :border "#5E7F6A"
|
||||
:border-top-p nil
|
||||
:bgcolor "#F8FCF8" :flex-wrap 'wrap :column-gap '(8) :row-gap 1
|
||||
(item :flex-shrink 0 (box :content "A 118" :width '(118) :height 1 :bgcolor "#DCEBDD" :text-align 'center))
|
||||
(item :flex-shrink 0 (box :content "B 118" :width '(118) :height 1 :bgcolor "#BFD6C2" :text-align 'center))
|
||||
(item :flex-shrink 0 (box :content "C 118" :width '(118) :height 1 :bgcolor "#8FAF95" :text-align 'center))))
|
||||
(column
|
||||
(box :content "wrap-reverse" :max-width '(293) :padding '(0 (10)) :border "#5E7F6A"
|
||||
:bgcolor "#FFFDF8" :color "#3D3A35" :text-align 'center)
|
||||
(flex :max-width '(293) :padding '(0 (8)) :border "#5E7F6A"
|
||||
:border-top-p nil
|
||||
:bgcolor "#F8FCF8" :flex-wrap 'wrap-reverse :column-gap '(8) :row-gap 1
|
||||
(item :flex-shrink 0 (box :content "A 118" :width '(118) :height 1 :bgcolor "#DCEBDD" :text-align 'center))
|
||||
(item :flex-shrink 0 (box :content "B 118" :width '(118) :height 1 :bgcolor "#BFD6C2" :text-align 'center))
|
||||
(item :flex-shrink 0 (box :content "C 118" :width '(118) :height 1 :bgcolor "#8FAF95" :text-align 'center)))))
|
||||
|
||||
(spacer :height 1)
|
||||
|
||||
(box :content "Container property: :flex-flow\nShorthand for direction and wrapping. These examples use one property to set both behaviors."
|
||||
:padding '(0 (18)) :border "#6F6A95"
|
||||
:bgcolor "#F7F4FC" :color "#2F2B45")
|
||||
(flex :flex-flow '(row wrap) :row-gap 1 :column-gap '(12) :padding '(0 (12))
|
||||
:border "#6F6A95" :border-top-p nil
|
||||
:bgcolor "#FBF9FF"
|
||||
(column
|
||||
(box :content ":flex-flow (row wrap)" :max-width '(440) :padding '(0 (10))
|
||||
:border "#6F6A95" :bgcolor "#FFFDF8" :color "#3D3A35" :text-align 'center)
|
||||
(flex :max-width '(440) :padding '(0 (8)) :border "#6F6A95"
|
||||
:border-top-p nil
|
||||
:bgcolor "#FBF9FF" :flex-flow '(row wrap) :gap '(1 (12))
|
||||
(item (box :content "A" :width '(170) :height 1 :bgcolor "#E4DEF4" :text-align 'center))
|
||||
(item (box :content "B" :width '(170) :height 1 :bgcolor "#CBC2E3" :text-align 'center))
|
||||
(item (box :content "C wraps" :width '(170) :height 1 :bgcolor "#AFA3D1" :text-align 'center))))
|
||||
(column
|
||||
(box :content ":flex-flow (column wrap)" :max-width '(440) :padding '(0 (10))
|
||||
:border "#6F6A95" :bgcolor "#FFFDF8" :color "#3D3A35" :text-align 'center)
|
||||
(flex :max-width '(440) :padding '(0 (8)) :border "#6F6A95"
|
||||
:border-top-p nil
|
||||
:bgcolor "#FBF9FF" :flex-flow '(column wrap) :gap '(1 (12))
|
||||
(item (box :content "A" :width '(140) :height 1 :bgcolor "#E4DEF4" :text-align 'center))
|
||||
(item (box :content "B" :width '(140) :height 1 :bgcolor "#CBC2E3" :text-align 'center))
|
||||
(item (box :content "C new column" :width '(140) :height 1 :bgcolor "#AFA3D1" :text-align 'center)))))
|
||||
|
||||
(spacer :height 1)
|
||||
|
||||
(box :content "Container property: :justify-content\nMain-axis packing after sizing. Distributed values change the space before, between, and after items."
|
||||
:padding '(0 (18)) :border "#3F6D88"
|
||||
:bgcolor "#F1F8FB" :color "#20313A")
|
||||
(flex :flex-flow '(row wrap) :row-gap 1 :column-gap '(12) :padding '(0 (12))
|
||||
:border "#3F6D88" :border-top-p nil
|
||||
:bgcolor "#F6FBFD"
|
||||
(column
|
||||
(box :content "flex-start" :width '(146) :padding '(0 (4)) :border "#3F6D88" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(146) :border "#3F6D88" :border-top-p nil :bgcolor "#F6FBFD" :justify-content 'flex-start
|
||||
(item (box :content "A" :width '(28) :height 1 :bgcolor "#CAE6F0" :text-align 'center))
|
||||
(item (box :content "B" :width '(28) :height 1 :bgcolor "#A8D2E2" :text-align 'center))))
|
||||
(column
|
||||
(box :content "center" :width '(146) :padding '(0 (4)) :border "#3F6D88" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(146) :border "#3F6D88" :border-top-p nil :bgcolor "#F6FBFD" :justify-content 'center
|
||||
(item (box :content "A" :width '(28) :height 1 :bgcolor "#CAE6F0" :text-align 'center))
|
||||
(item (box :content "B" :width '(28) :height 1 :bgcolor "#A8D2E2" :text-align 'center))))
|
||||
(column
|
||||
(box :content "flex-end" :width '(146) :padding '(0 (4)) :border "#3F6D88" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(146) :border "#3F6D88" :border-top-p nil :bgcolor "#F6FBFD" :justify-content 'flex-end
|
||||
(item (box :content "A" :width '(28) :height 1 :bgcolor "#CAE6F0" :text-align 'center))
|
||||
(item (box :content "B" :width '(28) :height 1 :bgcolor "#A8D2E2" :text-align 'center))))
|
||||
(column
|
||||
(box :content "space-between" :width '(146) :padding '(0 (4)) :border "#3F6D88" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(146) :border "#3F6D88" :border-top-p nil :bgcolor "#F6FBFD" :justify-content 'space-between
|
||||
(item (box :content "A" :width '(28) :height 1 :bgcolor "#CAE6F0" :text-align 'center))
|
||||
(item (box :content "B" :width '(28) :height 1 :bgcolor "#A8D2E2" :text-align 'center))))
|
||||
(column
|
||||
(box :content "space-around" :width '(146) :padding '(0 (4)) :border "#3F6D88" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(146) :border "#3F6D88" :border-top-p nil :bgcolor "#F6FBFD" :justify-content 'space-around
|
||||
(item (box :content "A" :width '(28) :height 1 :bgcolor "#CAE6F0" :text-align 'center))
|
||||
(item (box :content "B" :width '(28) :height 1 :bgcolor "#A8D2E2" :text-align 'center))))
|
||||
(column
|
||||
(box :content "space-evenly" :width '(146) :padding '(0 (4)) :border "#3F6D88" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(146) :border "#3F6D88" :border-top-p nil :bgcolor "#F6FBFD" :justify-content 'space-evenly
|
||||
(item (box :content "A" :width '(28) :height 1 :bgcolor "#CAE6F0" :text-align 'center))
|
||||
(item (box :content "B" :width '(28) :height 1 :bgcolor "#A8D2E2" :text-align 'center))))
|
||||
(column
|
||||
(box :content "start" :width '(176) :padding '(0 (4)) :border "#3F6D88" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(176) :border "#3F6D88" :border-top-p nil :bgcolor "#F6FBFD" :justify-content 'start
|
||||
(item (box :content "start" :width '(70) :height 1 :bgcolor "#CAE6F0" :text-align 'center))))
|
||||
(column
|
||||
(box :content "end" :width '(176) :padding '(0 (4)) :border "#3F6D88" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(176) :border "#3F6D88" :border-top-p nil :bgcolor "#F6FBFD" :justify-content 'end
|
||||
(item (box :content "end" :width '(70) :height 1 :bgcolor "#A8D2E2" :text-align 'center))))
|
||||
(column
|
||||
(box :content "left" :width '(176) :padding '(0 (4)) :border "#3F6D88" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(176) :border "#3F6D88" :border-top-p nil :bgcolor "#F6FBFD" :justify-content 'left
|
||||
(item (box :content "left" :width '(70) :height 1 :bgcolor "#7DB8CE" :text-align 'center))))
|
||||
(column
|
||||
(box :content "right" :width '(176) :padding '(0 (4)) :border "#3F6D88" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(176) :border "#3F6D88" :border-top-p nil :bgcolor "#F6FBFD" :justify-content 'right
|
||||
(item (box :content "right" :width '(70) :height 1 :bgcolor "#5F9CB5" :text-align 'center))))
|
||||
(column
|
||||
(box :content "normal" :width '(176) :padding '(0 (4)) :border "#3F6D88" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(176) :border "#3F6D88" :border-top-p nil :bgcolor "#F6FBFD" :justify-content 'normal
|
||||
(item (box :content "normal" :width '(70) :height 1 :bgcolor "#3F6D88" :color "#FFFFFF" :text-align 'center)))))
|
||||
|
||||
(spacer :height 1)
|
||||
|
||||
(box :content "Container property: :align-items\nCross-axis alignment inside each flex line. Stretch/normal enlarge auto-sized items; start/end/center move shorter ones."
|
||||
:padding '(0 (18)) :border "#9A6B43"
|
||||
:bgcolor "#FFF7EE" :color "#3A2A1D")
|
||||
(flex :flex-flow '(row wrap) :row-gap 1 :column-gap '(12) :padding '(0 (12))
|
||||
:border "#9A6B43" :border-top-p nil
|
||||
:bgcolor "#FFFAF5"
|
||||
(column
|
||||
(box :content "flex-start" :width '(176) :padding '(0 (4)) :border "#9A6B43" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(176) :height 5 :border "#9A6B43" :border-top-p nil :bgcolor "#FFFAF5" :align-items 'flex-start
|
||||
(item (box :content "short" :width '(68) :height 1 :bgcolor "#F1D0AF" :text-align 'center))
|
||||
(item (box :content "tall\nitem\nsets line" :width '(78) :height 3 :bgcolor "#D9AD83" :text-align 'center))))
|
||||
(column
|
||||
(box :content "center" :width '(176) :padding '(0 (4)) :border "#9A6B43" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(176) :height 5 :border "#9A6B43" :border-top-p nil :bgcolor "#FFFAF5" :align-items 'center
|
||||
(item (box :content "short" :width '(68) :height 1 :bgcolor "#F1D0AF" :text-align 'center))
|
||||
(item (box :content "tall\nitem\nsets line" :width '(78) :height 3 :bgcolor "#D9AD83" :text-align 'center))))
|
||||
(column
|
||||
(box :content "flex-end" :width '(176) :padding '(0 (4)) :border "#9A6B43" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(176) :height 5 :border "#9A6B43" :border-top-p nil :bgcolor "#FFFAF5" :align-items 'flex-end
|
||||
(item (box :content "short" :width '(68) :height 1 :bgcolor "#F1D0AF" :text-align 'center))
|
||||
(item (box :content "tall\nitem\nsets line" :width '(78) :height 3 :bgcolor "#D9AD83" :text-align 'center))))
|
||||
(column
|
||||
(box :content "stretch" :width '(176) :padding '(0 (4)) :border "#9A6B43" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(176) :height 5 :border "#9A6B43" :border-top-p nil :bgcolor "#FFFAF5" :align-items 'stretch
|
||||
(item (box :content "auto height stretches" :width '(72) :bgcolor "#F1D0AF" :text-align 'center))
|
||||
(item (box :content "line height" :width '(78) :height 3 :bgcolor "#D9AD83" :text-align 'center))))
|
||||
(column
|
||||
(box :content "baseline" :width '(176) :padding '(0 (4)) :border "#9A6B43" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(176) :height 5 :border "#9A6B43" :border-top-p nil :bgcolor "#FFFAF5" :align-items 'baseline
|
||||
(item (box :content "baseline" :width '(90) :height 1 :bgcolor "#BA8456" :text-align 'center))))
|
||||
(column
|
||||
(box :content "start" :width '(146) :padding '(0 (4)) :border "#9A6B43" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(146) :height 4 :border "#9A6B43" :border-top-p nil :bgcolor "#FFFAF5" :align-items 'start
|
||||
(item (box :content "start" :width '(62) :height 1 :bgcolor "#F1D0AF" :text-align 'center))))
|
||||
(column
|
||||
(box :content "end" :width '(146) :padding '(0 (4)) :border "#9A6B43" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(146) :height 4 :border "#9A6B43" :border-top-p nil :bgcolor "#FFFAF5" :align-items 'end
|
||||
(item (box :content "end" :width '(62) :height 1 :bgcolor "#D9AD83" :text-align 'center))))
|
||||
(column
|
||||
(box :content "self-start" :width '(146) :padding '(0 (4)) :border "#9A6B43" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(146) :height 4 :border "#9A6B43" :border-top-p nil :bgcolor "#FFFAF5" :align-items 'self-start
|
||||
(item (box :content "self-start" :width '(78) :height 1 :bgcolor "#BA8456" :text-align 'center))))
|
||||
(column
|
||||
(box :content "self-end" :width '(146) :padding '(0 (4)) :border "#9A6B43" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(146) :height 4 :border "#9A6B43" :border-top-p nil :bgcolor "#FFFAF5" :align-items 'self-end
|
||||
(item (box :content "self-end" :width '(70) :height 1 :bgcolor "#9A6B43" :color "#FFFFFF" :text-align 'center))))
|
||||
(column
|
||||
(box :content "normal" :width '(146) :padding '(0 (4)) :border "#9A6B43" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(146) :height 4 :border "#9A6B43" :border-top-p nil :bgcolor "#FFFAF5" :align-items 'normal
|
||||
(item (box :content "normal" :width '(62) :bgcolor "#7A5132" :color "#FFFFFF" :text-align 'center))))
|
||||
(column
|
||||
(box :content "stretch note" :width '(146) :padding '(0 (4)) :border "#9A6B43" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(box :content "normal behaves stretch-like for auto cross size in this DSL." :width '(146)
|
||||
:height 4 :padding '(0 (8)) :border "#9A6B43" :border-top-p nil
|
||||
:bgcolor "#FFFAF5" :color "#3A2A1D")))
|
||||
|
||||
(spacer :height 1)
|
||||
|
||||
(box :content "Container property: :align-content\nCross-axis packing between multiple flex lines. It has no visible effect on a nowrap single-line container."
|
||||
:padding '(0 (18)) :border "#7C6A2F"
|
||||
:bgcolor "#FBF8E8" :color "#362F16")
|
||||
(flex :flex-flow '(row wrap) :row-gap 1 :column-gap '(12) :padding '(0 (12))
|
||||
:border "#7C6A2F" :border-top-p nil
|
||||
:bgcolor "#FFFDF0"
|
||||
(column
|
||||
(box :content "flex-start" :width '(176) :padding '(0 (4)) :border "#7C6A2F" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(176) :height 7 :border "#7C6A2F" :border-top-p nil :bgcolor "#FFFDF0"
|
||||
:flex-wrap 'wrap :align-content 'flex-start :row-gap 1 :column-gap '(8)
|
||||
(item (box :content "A" :width '(78) :height 1 :bgcolor "#EEE1A8" :text-align 'center))
|
||||
(item (box :content "B" :width '(78) :height 1 :bgcolor "#D9C46D" :text-align 'center))
|
||||
(item (box :content "C" :width '(78) :height 1 :bgcolor "#B89B3D" :text-align 'center))))
|
||||
(column
|
||||
(box :content "center" :width '(176) :padding '(0 (4)) :border "#7C6A2F" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(176) :height 7 :border "#7C6A2F" :border-top-p nil :bgcolor "#FFFDF0"
|
||||
:flex-wrap 'wrap :align-content 'center :row-gap 1 :column-gap '(8)
|
||||
(item (box :content "A" :width '(78) :height 1 :bgcolor "#EEE1A8" :text-align 'center))
|
||||
(item (box :content "B" :width '(78) :height 1 :bgcolor "#D9C46D" :text-align 'center))
|
||||
(item (box :content "C" :width '(78) :height 1 :bgcolor "#B89B3D" :text-align 'center))))
|
||||
(column
|
||||
(box :content "flex-end" :width '(176) :padding '(0 (4)) :border "#7C6A2F" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(176) :height 7 :border "#7C6A2F" :border-top-p nil :bgcolor "#FFFDF0"
|
||||
:flex-wrap 'wrap :align-content 'flex-end :row-gap 1 :column-gap '(8)
|
||||
(item (box :content "A" :width '(78) :height 1 :bgcolor "#EEE1A8" :text-align 'center))
|
||||
(item (box :content "B" :width '(78) :height 1 :bgcolor "#D9C46D" :text-align 'center))
|
||||
(item (box :content "C" :width '(78) :height 1 :bgcolor "#B89B3D" :text-align 'center))))
|
||||
(column
|
||||
(box :content "space-between" :width '(176) :padding '(0 (4)) :border "#7C6A2F" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(176) :height 7 :border "#7C6A2F" :border-top-p nil :bgcolor "#FFFDF0"
|
||||
:flex-wrap 'wrap :align-content 'space-between :row-gap 1 :column-gap '(8)
|
||||
(item (box :content "A" :width '(78) :height 1 :bgcolor "#EEE1A8" :text-align 'center))
|
||||
(item (box :content "B" :width '(78) :height 1 :bgcolor "#D9C46D" :text-align 'center))
|
||||
(item (box :content "C" :width '(78) :height 1 :bgcolor "#B89B3D" :text-align 'center))))
|
||||
(column
|
||||
(box :content "space-around" :width '(176) :padding '(0 (4)) :border "#7C6A2F" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(176) :height 7 :border "#7C6A2F" :border-top-p nil :bgcolor "#FFFDF0"
|
||||
:flex-wrap 'wrap :align-content 'space-around :row-gap 1 :column-gap '(8)
|
||||
(item (box :content "A" :width '(78) :height 1 :bgcolor "#EEE1A8" :text-align 'center))
|
||||
(item (box :content "B" :width '(78) :height 1 :bgcolor "#D9C46D" :text-align 'center))
|
||||
(item (box :content "C" :width '(78) :height 1 :bgcolor "#B89B3D" :text-align 'center))))
|
||||
(column
|
||||
(box :content "space-evenly" :width '(176) :padding '(0 (4)) :border "#7C6A2F" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(176) :height 7 :border "#7C6A2F" :border-top-p nil :bgcolor "#FFFDF0"
|
||||
:flex-wrap 'wrap :align-content 'space-evenly :row-gap 1 :column-gap '(8)
|
||||
(item (box :content "A" :width '(78) :height 1 :bgcolor "#EEE1A8" :text-align 'center))
|
||||
(item (box :content "B" :width '(78) :height 1 :bgcolor "#D9C46D" :text-align 'center))
|
||||
(item (box :content "C" :width '(78) :height 1 :bgcolor "#B89B3D" :text-align 'center))))
|
||||
(column
|
||||
(box :content "stretch" :width '(176) :padding '(0 (4)) :border "#7C6A2F" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(176) :height 7 :border "#7C6A2F" :border-top-p nil :bgcolor "#FFFDF0"
|
||||
:flex-wrap 'wrap :align-content 'stretch :row-gap 1 :column-gap '(8)
|
||||
(item (box :content "A" :width '(78) :height 1 :bgcolor "#EEE1A8" :text-align 'center))
|
||||
(item (box :content "B" :width '(78) :height 1 :bgcolor "#D9C46D" :text-align 'center))
|
||||
(item (box :content "C" :width '(78) :height 1 :bgcolor "#B89B3D" :text-align 'center))))
|
||||
(column
|
||||
(box :content "start" :width '(176) :padding '(0 (4)) :border "#7C6A2F" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(176) :height 7 :border "#7C6A2F" :border-top-p nil :bgcolor "#FFFDF0"
|
||||
:flex-wrap 'wrap :align-content 'start :row-gap 1 :column-gap '(8)
|
||||
(item (box :content "A" :width '(78) :height 1 :bgcolor "#EEE1A8" :text-align 'center))
|
||||
(item (box :content "B" :width '(78) :height 1 :bgcolor "#D9C46D" :text-align 'center))
|
||||
(item (box :content "C" :width '(78) :height 1 :bgcolor "#B89B3D" :text-align 'center))))
|
||||
(column
|
||||
(box :content "end" :width '(176) :padding '(0 (4)) :border "#7C6A2F" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(176) :height 7 :border "#7C6A2F" :border-top-p nil :bgcolor "#FFFDF0"
|
||||
:flex-wrap 'wrap :align-content 'end :row-gap 1 :column-gap '(8)
|
||||
(item (box :content "A" :width '(78) :height 1 :bgcolor "#EEE1A8" :text-align 'center))
|
||||
(item (box :content "B" :width '(78) :height 1 :bgcolor "#D9C46D" :text-align 'center))
|
||||
(item (box :content "C" :width '(78) :height 1 :bgcolor "#B89B3D" :text-align 'center))))
|
||||
(column
|
||||
(box :content "baseline" :width '(176) :padding '(0 (4)) :border "#7C6A2F" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(176) :height 7 :border "#7C6A2F" :border-top-p nil :bgcolor "#FFFDF0"
|
||||
:flex-wrap 'wrap :align-content 'baseline :row-gap 1 :column-gap '(8)
|
||||
(item (box :content "A" :width '(78) :height 1 :bgcolor "#EEE1A8" :text-align 'center))
|
||||
(item (box :content "B" :width '(78) :height 1 :bgcolor "#D9C46D" :text-align 'center))
|
||||
(item (box :content "C" :width '(78) :height 1 :bgcolor "#B89B3D" :text-align 'center))))
|
||||
(column
|
||||
(box :content "normal" :width '(176) :padding '(0 (4)) :border "#7C6A2F" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(176) :height 7 :border "#7C6A2F" :border-top-p nil :bgcolor "#FFFDF0"
|
||||
:flex-wrap 'wrap :align-content 'normal :row-gap 1 :column-gap '(8)
|
||||
(item (box :content "A" :width '(78) :height 1 :bgcolor "#EEE1A8" :text-align 'center))
|
||||
(item (box :content "B" :width '(78) :height 1 :bgcolor "#D9C46D" :text-align 'center))
|
||||
(item (box :content "C" :width '(78) :height 1 :bgcolor "#B89B3D" :text-align 'center))))
|
||||
(column
|
||||
(box :content "nowrap note" :width '(176) :padding '(0 (4)) :border "#7C6A2F" :bgcolor "#FFFDF8" :text-align 'center)
|
||||
(flex :width '(176) :height 7 :border "#7C6A2F" :border-top-p nil :bgcolor "#FFFDF0"
|
||||
:flex-wrap 'nowrap :align-content 'normal :row-gap 1 :column-gap '(8)
|
||||
(item (box :content "single line" :width '(96) :height 1 :bgcolor "#EEE1A8" :text-align 'center)))))
|
||||
|
||||
(spacer :height 1)
|
||||
|
||||
(box :content "Container properties: :gap, :row-gap, :column-gap\n:gaps define spacing between flex items and flex lines. Explicit row/column values override matching sides."
|
||||
:padding '(0 (18)) :border "#3D7068"
|
||||
:bgcolor "#F1FAF8" :color "#1D3935")
|
||||
(flex :flex-flow '(row wrap) :row-gap 1 :column-gap '(12) :padding '(0 (12))
|
||||
:border "#3D7068" :border-top-p nil
|
||||
:bgcolor "#F7FCFB"
|
||||
(column
|
||||
(box :content ":gap (1 (14))" :max-width '(293) :padding '(0 (10)) :border "#3D7068"
|
||||
:bgcolor "#FFFDF8" :color "#3D3A35" :text-align 'center)
|
||||
(flex :max-width '(293)
|
||||
:border "#3D7068" :border-top-p nil :bgcolor "#F7FCFB"
|
||||
:flex-wrap 'wrap :gap '(1 (14))
|
||||
(item (box :content "A" :width '(104) :height 1 :bgcolor "#CDEBE5" :text-align 'center))
|
||||
(item (box :content "B" :width '(104) :height 1 :bgcolor "#9FD5CB" :text-align 'center))
|
||||
(item (box :content "C" :width '(104) :height 1 :bgcolor "#71BDB0" :text-align 'center))))
|
||||
(column
|
||||
(box :content ":row-gap 2" :max-width '(293) :padding '(0 (10)) :border "#3D7068"
|
||||
:bgcolor "#FFFDF8" :color "#3D3A35" :text-align 'center)
|
||||
(flex :max-width '(293) :border "#3D7068" :border-top-p nil :bgcolor "#F7FCFB"
|
||||
:flex-wrap 'wrap :row-gap 2 :column-gap '(8)
|
||||
(item (box :content "A" :width '(104) :height 1 :bgcolor "#CDEBE5" :text-align 'center))
|
||||
(item (box :content "B" :width '(104) :height 1 :bgcolor "#9FD5CB" :text-align 'center))
|
||||
(item (box :content "C" :width '(104) :height 1 :bgcolor "#71BDB0" :text-align 'center))))
|
||||
(column
|
||||
(box :content ":column-gap (32)" :max-width '(293) :padding '(0 (10)) :border "#3D7068"
|
||||
:bgcolor "#FFFDF8" :color "#3D3A35" :text-align 'center)
|
||||
(flex :max-width '(293) :border "#3D7068" :border-top-p nil :bgcolor "#F7FCFB"
|
||||
:flex-wrap 'wrap :row-gap 1 :column-gap '(32)
|
||||
(item (box :content "A" :width '(104) :height 1 :bgcolor "#CDEBE5" :text-align 'center))
|
||||
(item (box :content "B" :width '(104) :height 1 :bgcolor "#9FD5CB" :text-align 'center))
|
||||
(item (box :content "C" :width '(104) :height 1 :bgcolor "#71BDB0" :text-align 'center)))))
|
||||
|
||||
(spacer :height 1)
|
||||
|
||||
(box :content "Item property: :order\nVisual ordering sorts by :order, then source order. The labels expose both values."
|
||||
:padding '(0 (18)) :border "#8E4A63"
|
||||
:bgcolor "#FFF4F7" :color "#3A1F2A")
|
||||
(flex :height 5 :padding '(0 (12)) :border "#8E4A63"
|
||||
:border-top-p nil
|
||||
:bgcolor "#FFF8FA" :column-gap '(12) :align-items 'center
|
||||
(item :order 3 (box :content "source 1\n:order 3" :width '(150) :height 2 :bgcolor "#F2C4D2" :text-align 'center))
|
||||
(item :order 1 (box :content "source 2\n:order 1" :width '(150) :height 2 :bgcolor "#DEA4B7" :text-align 'center))
|
||||
(item :order 2 (box :content "source 3\n:order 2" :width '(150) :height 2 :bgcolor "#C87F9A" :text-align 'center))
|
||||
(item :order 1 (box :content "source 4\nsame order" :width '(150) :height 2 :bgcolor "#A95F7C" :color "#FFFFFF" :text-align 'center)))
|
||||
|
||||
(spacer :height 1)
|
||||
|
||||
(box :content "Item sizing: :flex-grow, :flex-shrink, :flex-basis, and child :width\nFlex starts from basis or width/content, then distributes positive or negative space."
|
||||
:padding '(0 (18)) :border "#2F5F7C"
|
||||
:bgcolor "#F1F8FC" :color "#1C303D")
|
||||
(column
|
||||
(box :content "Grow factors: same basis, different growth weights."
|
||||
:padding '(0 (12)) :border "#2F5F7C" :border-top-p nil
|
||||
:bgcolor "#FFFDF8" :color "#3D3A35")
|
||||
(flex :padding '(0 (12)) :border "#2F5F7C"
|
||||
:border-top-p nil
|
||||
:bgcolor "#F8FCFE" :column-gap '(10)
|
||||
(item :flex-grow 1 :flex-basis '(120) (box :content "grow 1\nbasis 120" :height 2 :bgcolor "#C7E3F0" :text-align 'center))
|
||||
(item :flex-grow 2 :flex-basis '(120) (box :content "grow 2\nbasis 120" :height 2 :bgcolor "#96C7DD" :text-align 'center))
|
||||
(item :flex-grow 3 :flex-basis '(120) (box :content "grow 3\nbasis 120" :height 2 :bgcolor "#5FA4C2" :text-align 'center))))
|
||||
(column
|
||||
(box :content "Shrink factors: overflowing bases lose space by weighted shrink."
|
||||
:padding '(0 (12)) :border "#2F5F7C" :border-top-p nil
|
||||
:bgcolor "#FFFDF8" :color "#3D3A35")
|
||||
(flex :padding '(0 (12)) :border "#2F5F7C"
|
||||
:border-top-p nil
|
||||
:bgcolor "#F8FCFE" :column-gap '(10)
|
||||
(item :flex-shrink 1 :flex-basis '(320) (box :content "shrink 1\nbasis 320" :height 2 :bgcolor "#C7E3F0" :text-align 'center))
|
||||
(item :flex-shrink 3 :flex-basis '(320) (box :content "shrink 3\nbasis 320" :height 2 :bgcolor "#96C7DD" :text-align 'center))
|
||||
(item :flex-shrink 5 :flex-basis '(320) (box :content "shrink 5\nbasis 320" :height 2 :bgcolor "#5FA4C2" :text-align 'center))))
|
||||
(column
|
||||
(box :content "Basis versus width: explicit basis overrides width; auto basis uses width/content."
|
||||
:padding '(0 (12)) :border "#2F5F7C" :border-top-p nil
|
||||
:bgcolor "#FFFDF8" :color "#3D3A35")
|
||||
(flex :padding '(0 (12)) :border "#2F5F7C"
|
||||
:border-top-p nil
|
||||
:bgcolor "#F8FCFE" :column-gap '(10)
|
||||
(item :flex-basis '(120) (box :content "basis 120\nwidth 240" :width '(240) :height 2 :bgcolor "#C7E3F0" :text-align 'center))
|
||||
(item :flex-basis 'auto (box :content "basis auto\nwidth 240" :width '(240) :height 2 :bgcolor "#96C7DD" :text-align 'center))
|
||||
(item :flex '(1 1 (160)) (box :content "flex tuple\nbasis 160" :width '(240) :height 2 :bgcolor "#5FA4C2" :text-align 'center))))
|
||||
(column
|
||||
(box :content "Intrinsic basis keywords: content, min-content, and max-content derive size from text."
|
||||
:padding '(0 (12)) :border "#2F5F7C" :border-top-p nil
|
||||
:bgcolor "#FFFDF8" :color "#3D3A35")
|
||||
(flex :padding '(0 (12)) :border "#2F5F7C"
|
||||
:border-top-p nil
|
||||
:bgcolor "#F8FCFE" :flex-wrap 'wrap :row-gap 1 :column-gap '(10)
|
||||
(item :flex-shrink 0 :flex-basis 'content
|
||||
(box :content "content\nnatural text" :width '(180) :height 2 :bgcolor "#C7E3F0" :text-align 'center))
|
||||
(item :flex-shrink 0 :flex-basis 'min-content
|
||||
(box :content "min-content\nwrap choices" :width '(180) :height 2 :bgcolor "#96C7DD" :text-align 'center))
|
||||
(item :flex-shrink 0 :flex-basis 'max-content
|
||||
(box :content "max-content\nkeeps phrase width" :width '(180) :height 2 :bgcolor "#5FA4C2" :text-align 'center))))
|
||||
|
||||
(spacer :height 1)
|
||||
|
||||
(box :content "Item property: :flex shorthand\nSupported forms: number, none, auto, initial, and (grow shrink basis). Longhands can override shorthand parts."
|
||||
:padding '(0 (18)) :border "#52612F"
|
||||
:bgcolor "#F8FAEF" :color "#293116")
|
||||
(flex :height 7 :padding '(0 (12)) :border "#52612F"
|
||||
:border-top-p nil
|
||||
:bgcolor "#FCFDF6" :flex-wrap 'wrap :row-gap 1 :column-gap '(8) :align-items 'center
|
||||
(item :flex 1 (box :content ":flex 1\n= 1 1 0" :bgcolor "#DDE8B2" :text-align 'center))
|
||||
(item :flex 'none (box :content ":flex none\n= 0 0 auto" :width '(140) :bgcolor "#C5D681" :text-align 'center))
|
||||
(item :flex 'auto (box :content ":flex auto\n= 1 1 auto" :width '(140) :bgcolor "#AABE59" :text-align 'center))
|
||||
(item :flex 'initial (box :content ":flex initial\n= 0 1 auto" :width '(140) :bgcolor "#8D9E3C" :text-align 'center))
|
||||
(item :flex '(2 1 (120)) :flex-basis '(160)
|
||||
(box :content ":flex (2 1 120)\nthen basis 160" :bgcolor "#66762D" :color "#FFFFFF" :text-align 'center)))
|
||||
|
||||
(spacer :height 1)
|
||||
|
||||
(box :content "Item property: :align-self\nPer-item cross-axis override. auto inherits :align-items; other values replace the container setting."
|
||||
:padding '(0 (18)) :border "#7B4D38"
|
||||
:bgcolor "#FFF6F0" :color "#392319")
|
||||
(flex :height 7 :padding '(0 (12)) :border "#7B4D38"
|
||||
:border-top-p nil
|
||||
:bgcolor "#FFFAF7" :align-items 'flex-start
|
||||
:flex-wrap 'wrap :row-gap 1 :column-gap '(10)
|
||||
(item :align-self 'auto (box :content "auto\ninherits start" :width '(118) :height 2 :bgcolor "#EFC7B6" :text-align 'center))
|
||||
(item :align-self 'flex-start (box :content "flex-start" :width '(118) :height 2 :bgcolor "#DBA58D" :text-align 'center))
|
||||
(item :align-self 'center (box :content "center" :width '(118) :height 2 :bgcolor "#BF7F63" :text-align 'center))
|
||||
(item :align-self 'flex-end (box :content "flex-end" :width '(118) :height 2 :bgcolor "#9D6048" :color "#FFFFFF" :text-align 'center))
|
||||
(item :align-self 'stretch (box :content "stretch\nauto cross" :width '(118) :bgcolor "#7B4D38" :color "#FFFFFF" :text-align 'center))
|
||||
(item :align-self 'normal (box :content "normal\nstretch-like" :width '(118) :bgcolor "#5D3929" :color "#FFFFFF" :text-align 'center)))
|
||||
(flex :height 6 :padding '(0 (12)) :border "#7B4D38"
|
||||
:border-top-p nil
|
||||
:bgcolor "#FFFAF7" :align-items 'flex-start
|
||||
:flex-wrap 'wrap :row-gap 1 :column-gap '(10)
|
||||
(item :align-self 'start (box :content "start" :width '(118) :height 2 :bgcolor "#EFC7B6" :text-align 'center))
|
||||
(item :align-self 'end (box :content "end" :width '(118) :height 2 :bgcolor "#DBA58D" :text-align 'center))
|
||||
(item :align-self 'self-start (box :content "self-start" :width '(118) :height 2 :bgcolor "#BF7F63" :text-align 'center))
|
||||
(item :align-self 'self-end (box :content "self-end" :width '(118) :height 2 :bgcolor "#9D6048" :color "#FFFFFF" :text-align 'center))
|
||||
(item :align-self 'baseline (box :content "baseline" :width '(118) :height 2 :bgcolor "#7B4D38" :color "#FFFFFF" :text-align 'center)))
|
||||
|
||||
(spacer :height 1)
|
||||
|
||||
(box :content "Summary\nUse direction and wrap to create lines, basis/width to choose starting sizes, grow/shrink to distribute space, then justify/align properties to pack items and lines."
|
||||
:padding '(1 (24)) :border "#2F3437"
|
||||
:bgcolor "#FAF7F0" :color "#1F2328" :text-align 'center))
|
||||
289
examples/grid-reference.ebox
Normal file
289
examples/grid-reference.ebox
Normal file
@ -0,0 +1,289 @@
|
||||
(column
|
||||
(box :content "Ebox CSS Grid Reference\nA visual guide to every Grid property in the public Ebox DSL."
|
||||
:width '(720)
|
||||
:padding '(1 (20))
|
||||
:border "#2E3740"
|
||||
:color "#20252B"
|
||||
:bgcolor "#FFFDF8"
|
||||
:face 'bold
|
||||
:text-align 'center)
|
||||
(spacer :height 1)
|
||||
|
||||
(box :content "01 TRACK SIZING\nFixed pixels, intrinsic auto tracks, and fractional space share one definite canvas."
|
||||
:width '(720)
|
||||
:padding '(0 (16))
|
||||
:border "#B85C3C"
|
||||
:border-bottom-p nil
|
||||
:color "#4C271D"
|
||||
:bgcolor "#F1D4C9"
|
||||
:wrap-mode 'word)
|
||||
(grid
|
||||
:width '(720)
|
||||
:grid-template-columns '((176) auto 1fr)
|
||||
:grid-template-rows '(2)
|
||||
:gap '(1 (10))
|
||||
:justify-content 'space-between
|
||||
:align-content 'center
|
||||
:border "#B85C3C"
|
||||
:bgcolor "#FFF9F4"
|
||||
(box :content "FIXED\n176 PX"
|
||||
:padding '(0 (8))
|
||||
:color "#542A1D"
|
||||
:bgcolor "#F1D4C9"
|
||||
:text-align 'center)
|
||||
(box :content "AUTO\nINTRINSIC"
|
||||
:padding '(0 (8))
|
||||
:color "#31543C"
|
||||
:bgcolor "#DCEBDD"
|
||||
:text-align 'center)
|
||||
(box :content "1FR\nREMAINDER"
|
||||
:padding '(0 (8))
|
||||
:color "#28485B"
|
||||
:bgcolor "#D9EAF2"
|
||||
:text-align 'center))
|
||||
(spacer :height 1)
|
||||
|
||||
(box :content "02 TRACK FUNCTIONS\n`minmax` protects a readable minimum while `repeat` expands a compact template."
|
||||
:width '(720)
|
||||
:padding '(0 (16))
|
||||
:border "#537A63"
|
||||
:border-bottom-p nil
|
||||
:color "#26402F"
|
||||
:bgcolor "#DCEBDD"
|
||||
:wrap-mode 'word)
|
||||
(grid
|
||||
:width '(720)
|
||||
:grid-template-columns '((minmax (150) (220)) (repeat 1 (fr 1)) 1fr)
|
||||
:grid-template-rows '(2 2)
|
||||
:grid-row-gap 1
|
||||
:grid-column-gap '(12)
|
||||
:justify-content 'start
|
||||
:align-content 'stretch
|
||||
:border "#537A63"
|
||||
:bgcolor "#F7FBF7"
|
||||
(box :content "MINMAX\n150 → 220"
|
||||
:padding '(0 (8))
|
||||
:color "#26402F"
|
||||
:bgcolor "#DCEBDD"
|
||||
:text-align 'center)
|
||||
(box :content "REPEAT\n(fr 1)"
|
||||
:padding '(0 (8))
|
||||
:color "#26402F"
|
||||
:bgcolor "#C8DDCB"
|
||||
:text-align 'center)
|
||||
(box :content "1FR\nSYMBOL"
|
||||
:padding '(0 (8))
|
||||
:color "#26402F"
|
||||
:bgcolor "#B5D0BA"
|
||||
:text-align 'center)
|
||||
(box :content "EXPLICIT ROW 2\nTRACK TEMPLATE"
|
||||
:padding '(0 (8))
|
||||
:color "#26402F"
|
||||
:bgcolor "#EDF5EE"
|
||||
:text-align 'center)
|
||||
(box :content "EXPLICIT ROW 2\nREPEAT + 1FR"
|
||||
:padding '(0 (8))
|
||||
:color "#26402F"
|
||||
:bgcolor "#E3F0E5"
|
||||
:text-align 'center)
|
||||
(box :content "MINMAX\nMAX 220"
|
||||
:padding '(0 (8))
|
||||
:color "#26402F"
|
||||
:bgcolor "#D4E6D7"
|
||||
:text-align 'center))
|
||||
(spacer :height 1)
|
||||
|
||||
(box :content "03 IMPLICIT TRACKS + AUTO-FLOW\nDeclared tracks establish the map; auto rows, auto columns, and flow fill the rest."
|
||||
:width '(720)
|
||||
:padding '(0 (16))
|
||||
:border "#416E8A"
|
||||
:border-bottom-p nil
|
||||
:color "#203A4A"
|
||||
:bgcolor "#D9EAF2"
|
||||
:wrap-mode 'word)
|
||||
(box :content "ROW FLOW · :grid-auto-rows 2"
|
||||
:width '(720)
|
||||
:padding '(0 (12))
|
||||
:border "#416E8A"
|
||||
:border-bottom-p nil
|
||||
:color "#203A4A"
|
||||
:bgcolor "#EEF7FB"
|
||||
:text-align 'center)
|
||||
(grid
|
||||
:width '(720)
|
||||
:grid-template-columns '((220) (220) (220))
|
||||
:grid-template-rows '(2)
|
||||
:grid-auto-rows 2
|
||||
:grid-auto-flow 'row
|
||||
:gap '(1 (10))
|
||||
:border "#416E8A"
|
||||
:bgcolor "#F6FBFD"
|
||||
(box :content "ROW 1 / A" :padding '(0 (8)) :color "#203A4A" :bgcolor "#D9EAF2" :text-align 'center)
|
||||
(box :content "ROW 1 / B" :padding '(0 (8)) :color "#203A4A" :bgcolor "#C3DFEA" :text-align 'center)
|
||||
(box :content "ROW 1 / C" :padding '(0 (8)) :color "#203A4A" :bgcolor "#A9D0DE" :text-align 'center)
|
||||
(box :content "AUTO ROW 2 / A" :padding '(0 (8)) :color "#203A4A" :bgcolor "#E5F2F7" :text-align 'center)
|
||||
(box :content "AUTO ROW 2 / B" :padding '(0 (8)) :color "#203A4A" :bgcolor "#D7EAF1" :text-align 'center)
|
||||
(box :content "AUTO ROW 2 / C" :padding '(0 (8)) :color "#203A4A" :bgcolor "#C8E1EB" :text-align 'center))
|
||||
(spacer :height 1)
|
||||
(box :content "COLUMN FLOW · :grid-auto-columns ((220))"
|
||||
:width '(720)
|
||||
:padding '(0 (12))
|
||||
:border "#416E8A"
|
||||
:border-bottom-p nil
|
||||
:color "#203A4A"
|
||||
:bgcolor "#EEF7FB"
|
||||
:text-align 'center)
|
||||
(grid
|
||||
:width '(720)
|
||||
:grid-template-columns '((220))
|
||||
:grid-template-rows '(2 2)
|
||||
:grid-auto-columns '((220))
|
||||
:grid-auto-flow 'column
|
||||
:row-gap 1
|
||||
:column-gap '(10)
|
||||
:border "#416E8A"
|
||||
:bgcolor "#F6FBFD"
|
||||
(box :content "COL 1 / ROW 1" :padding '(0 (8)) :color "#203A4A" :bgcolor "#D9EAF2" :text-align 'center)
|
||||
(box :content "COL 1 / ROW 2" :padding '(0 (8)) :color "#203A4A" :bgcolor "#C3DFEA" :text-align 'center)
|
||||
(box :content "AUTO COL 2 / ROW 1" :padding '(0 (8)) :color "#203A4A" :bgcolor "#A9D0DE" :text-align 'center)
|
||||
(box :content "AUTO COL 2 / ROW 2" :padding '(0 (8)) :color "#203A4A" :bgcolor "#E5F2F7" :text-align 'center))
|
||||
(spacer :height 1)
|
||||
|
||||
(box :content "04 PLACEMENT + SPANS\nGrid items can target one-based rows and columns, span tracks, or fall back to auto-placement."
|
||||
:width '(720)
|
||||
:padding '(0 (16))
|
||||
:border "#6A5C8B"
|
||||
:border-bottom-p nil
|
||||
:color "#332B4B"
|
||||
:bgcolor "#E7E2F1"
|
||||
:wrap-mode 'word)
|
||||
(grid
|
||||
:width '(720)
|
||||
:grid-template-columns '((170) (170) (170) 1fr)
|
||||
:grid-template-rows '(2 2 2)
|
||||
:gap '(1 (10))
|
||||
:justify-content 'center
|
||||
:align-content 'center
|
||||
:border "#6A5C8B"
|
||||
:bgcolor "#FBF9FF"
|
||||
(grid-item :grid-column '(1 :span 3) :grid-row 1
|
||||
(box :content "COLUMN 1 → 3\n:grid-column (1 :span 3)"
|
||||
:padding '(0 (8)) :color "#332B4B" :bgcolor "#E7E2F1" :text-align 'center))
|
||||
(grid-item :grid-column 4 :grid-row 1
|
||||
(box :content "C4\nEXPLICIT"
|
||||
:padding '(0 (8)) :color "#332B4B" :bgcolor "#D8D0E8" :text-align 'center))
|
||||
(grid-item :grid-column 1 :grid-row 2 :grid-row-span 2
|
||||
(box :content "R2–R3\nROW SPAN"
|
||||
:padding '(0 (8)) :color "#332B4B" :bgcolor "#CBC2E3" :text-align 'center))
|
||||
(grid-item :grid-column 2 :grid-row 2 :grid-column-span 2
|
||||
(box :content "C2–C3\nCOLUMN SPAN"
|
||||
:padding '(0 (8)) :color "#332B4B" :bgcolor "#B9ADD8" :text-align 'center))
|
||||
(grid-item :grid-column 4 :grid-row 2
|
||||
(box :content "R2 C4\nPLACED"
|
||||
:padding '(0 (8)) :color "#332B4B" :bgcolor "#AFA3D1" :text-align 'center))
|
||||
(box :content "AUTO\nREMAINDER"
|
||||
:padding '(0 (8)) :color "#332B4B" :bgcolor "#EDE9F6" :text-align 'center))
|
||||
(spacer :height 1)
|
||||
|
||||
(box :content "05 ITEM ALIGNMENT\n`:justify-items` controls the inline axis; `:align-items` controls the block axis inside each cell."
|
||||
:width '(720)
|
||||
:padding '(0 (16))
|
||||
:border "#B07836"
|
||||
:border-bottom-p nil
|
||||
:color "#513718"
|
||||
:bgcolor "#F3E4C7"
|
||||
:wrap-mode 'word)
|
||||
(box :content "START / START"
|
||||
:width '(720) :padding '(0 (12)) :border "#B07836" :border-bottom-p nil
|
||||
:color "#513718" :bgcolor "#FBF4E6" :text-align 'center)
|
||||
(grid
|
||||
:width '(720) :height 3
|
||||
:grid-template-columns '((220) (220) (220)) :grid-template-rows '(3)
|
||||
:gap '(1 (10)) :justify-items 'start :align-items 'start
|
||||
:border "#B07836" :bgcolor "#FFF9ED"
|
||||
(box :content "START" :padding '(0 (8)) :color "#513718" :bgcolor "#F3E4C7" :text-align 'center)
|
||||
(box :content "INLINE START" :padding '(0 (8)) :color "#513718" :bgcolor "#EAD2A6" :text-align 'center)
|
||||
(box :content "BLOCK START" :padding '(0 (8)) :color "#513718" :bgcolor "#E1C18A" :text-align 'center))
|
||||
(box :content "CENTER / CENTER"
|
||||
:width '(720) :padding '(0 (12)) :border "#B07836" :border-bottom-p nil
|
||||
:color "#513718" :bgcolor "#FBF4E6" :text-align 'center)
|
||||
(grid
|
||||
:width '(720) :height 3
|
||||
:grid-template-columns '((220) (220) (220)) :grid-template-rows '(3)
|
||||
:gap '(1 (10)) :justify-items 'center :align-items 'center
|
||||
:border "#B07836" :bgcolor "#FFF9ED"
|
||||
(box :content "CENTER" :padding '(0 (8)) :color "#513718" :bgcolor "#F3E4C7" :text-align 'center)
|
||||
(box :content "INLINE CENTER" :padding '(0 (8)) :color "#513718" :bgcolor "#EAD2A6" :text-align 'center)
|
||||
(box :content "BLOCK CENTER" :padding '(0 (8)) :color "#513718" :bgcolor "#E1C18A" :text-align 'center))
|
||||
(box :content "END / STRETCH"
|
||||
:width '(720) :padding '(0 (12)) :border "#B07836" :border-bottom-p nil
|
||||
:color "#513718" :bgcolor "#FBF4E6" :text-align 'center)
|
||||
(grid
|
||||
:width '(720) :height 3
|
||||
:grid-template-columns '((220) (220) (220)) :grid-template-rows '(3)
|
||||
:gap '(1 (10)) :justify-items 'end :align-items 'stretch
|
||||
:border "#B07836" :bgcolor "#FFF9ED"
|
||||
(box :content "END" :padding '(0 (8)) :color "#513718" :bgcolor "#F3E4C7" :text-align 'center)
|
||||
(box :content "INLINE END" :padding '(0 (8)) :color "#513718" :bgcolor "#EAD2A6" :text-align 'center)
|
||||
(box :content "BLOCK STRETCH" :padding '(0 (8)) :color "#513718" :bgcolor "#E1C18A" :text-align 'center))
|
||||
(spacer :height 1)
|
||||
|
||||
(box :content "06 CONTENT ALIGNMENT\nWhen tracks do not consume the full canvas, `:justify-content` and `:align-content` distribute the leftover space."
|
||||
:width '(720)
|
||||
:padding '(0 (16))
|
||||
:border "#2F7180"
|
||||
:border-bottom-p nil
|
||||
:color "#1E4148"
|
||||
:bgcolor "#CFE8EA"
|
||||
:wrap-mode 'word)
|
||||
(box :content "CENTER / CENTER"
|
||||
:width '(720) :padding '(0 (12)) :border "#2F7180" :border-bottom-p nil
|
||||
:color "#1E4148" :bgcolor "#EEF9F9" :text-align 'center)
|
||||
(grid
|
||||
:width '(720) :height 8
|
||||
:grid-template-columns '((140) (140) (140)) :grid-template-rows '(2 2)
|
||||
:gap '(1 (10)) :justify-content 'center :align-content 'center
|
||||
:justify-items 'center :align-items 'center
|
||||
:border "#2F7180" :bgcolor "#F6FCFC"
|
||||
(box :content "A" :padding '(0 (8)) :color "#1E4148" :bgcolor "#CFE8EA" :text-align 'center)
|
||||
(box :content "B" :padding '(0 (8)) :color "#1E4148" :bgcolor "#B5DDE0" :text-align 'center)
|
||||
(box :content "C" :padding '(0 (8)) :color "#1E4148" :bgcolor "#9ACED2" :text-align 'center)
|
||||
(box :content "D" :padding '(0 (8)) :color "#1E4148" :bgcolor "#DDF1F2" :text-align 'center)
|
||||
(box :content "E" :padding '(0 (8)) :color "#1E4148" :bgcolor "#C7E7E9" :text-align 'center)
|
||||
(box :content "F" :padding '(0 (8)) :color "#1E4148" :bgcolor "#ADD9DC" :text-align 'center))
|
||||
(box :content "SPACE-BETWEEN / SPACE-AROUND"
|
||||
:width '(720) :padding '(0 (12)) :border "#2F7180" :border-bottom-p nil
|
||||
:color "#1E4148" :bgcolor "#EEF9F9" :text-align 'center)
|
||||
(grid
|
||||
:width '(720) :height 8
|
||||
:grid-template-columns '((140) (140) (140)) :grid-template-rows '(2 2)
|
||||
:gap '(1 (10)) :justify-content 'space-between :align-content 'space-around
|
||||
:justify-items 'center :align-items 'center
|
||||
:border "#2F7180" :bgcolor "#F6FCFC"
|
||||
(box :content "SPACE" :padding '(0 (8)) :color "#1E4148" :bgcolor "#CFE8EA" :text-align 'center)
|
||||
(box :content "BETWEEN" :padding '(0 (8)) :color "#1E4148" :bgcolor "#B5DDE0" :text-align 'center)
|
||||
(box :content "AROUND" :padding '(0 (8)) :color "#1E4148" :bgcolor "#9ACED2" :text-align 'center)
|
||||
(box :content "ROW 2" :padding '(0 (8)) :color "#1E4148" :bgcolor "#DDF1F2" :text-align 'center))
|
||||
(box :content "END / SPACE-EVENLY"
|
||||
:width '(720) :padding '(0 (12)) :border "#2F7180" :border-bottom-p nil
|
||||
:color "#1E4148" :bgcolor "#EEF9F9" :text-align 'center)
|
||||
(grid
|
||||
:width '(720) :height 8
|
||||
:grid-template-columns '((140) (140) (140)) :grid-template-rows '(2 2)
|
||||
:gap '(1 (10)) :justify-content 'end :align-content 'space-evenly
|
||||
:justify-items 'center :align-items 'center
|
||||
:border "#2F7180" :bgcolor "#F6FCFC"
|
||||
(box :content "END" :padding '(0 (8)) :color "#1E4148" :bgcolor "#CFE8EA" :text-align 'center)
|
||||
(box :content "EVEN" :padding '(0 (8)) :color "#1E4148" :bgcolor "#B5DDE0" :text-align 'center)
|
||||
(box :content "LY" :padding '(0 (8)) :color "#1E4148" :bgcolor "#9ACED2" :text-align 'center)
|
||||
(box :content "TRACKS" :padding '(0 (8)) :color "#1E4148" :bgcolor "#DDF1F2" :text-align 'center))
|
||||
(spacer :height 1)
|
||||
|
||||
(box :content "GRID TOOLKIT :grid-template-columns · :grid-template-rows · :grid-auto-columns · :grid-auto-rows · :grid-auto-flow · :gap · :grid-row-gap · :grid-column-gap · :justify-items · :align-items · :justify-content · :align-content · :grid-column · :grid-row · :grid-column-span · :grid-row-span"
|
||||
:width '(720)
|
||||
:padding '(0 (16))
|
||||
:border "#2E3740"
|
||||
:color "#FFFFFF"
|
||||
:bgcolor "#3D4B55"
|
||||
:wrap-mode 'word
|
||||
:text-align 'center))
|
||||
@ -1,98 +1,98 @@
|
||||
(column
|
||||
(box :content "Ebox Playground\nPixel-precise layout, composed only from public nodes."
|
||||
:width (720)
|
||||
:padding (1 (18))
|
||||
:width '(720)
|
||||
:padding '(1 (18))
|
||||
:border "#8F432F"
|
||||
:color "#252A2E"
|
||||
:bgcolor "#FFFDF8"
|
||||
:face bold
|
||||
:text-align center)
|
||||
:face 'bold
|
||||
:text-align 'center)
|
||||
(spacer :height 1)
|
||||
(box :content "01 FIXED + FRACTIONAL\nA definite Grid width divides into one exact track and one flexible track."
|
||||
:width (720)
|
||||
:padding (0 (16))
|
||||
:width '(720)
|
||||
:padding '(0 (16))
|
||||
:border "#C97252"
|
||||
:border-bottom-p nil
|
||||
:color "#252A2E"
|
||||
:bgcolor "#F1D4C9"
|
||||
:wrap-mode word)
|
||||
:wrap-mode 'word)
|
||||
(grid
|
||||
:width (718)
|
||||
:grid-template-columns ((220) 1fr)
|
||||
:gap (1 (12))
|
||||
:width '(720)
|
||||
:grid-template-columns '((220) 1fr)
|
||||
:gap '(1 (12))
|
||||
:border "#C97252"
|
||||
:bgcolor "#FFF9F5"
|
||||
(box :content "FIXED TRACK\n220 px stays exact"
|
||||
:width (220) :padding (1 0) :text-align center
|
||||
:width '(220) :padding '(1 0) :text-align 'center
|
||||
:color "#252A2E" :bgcolor "#F1D4C9")
|
||||
(box :content "FRACTIONAL TRACK\n1fr receives the remaining width"
|
||||
:width (486) :padding (1 0) :text-align center
|
||||
:width '(486) :padding '(1 0) :text-align 'center
|
||||
:color "#252A2E" :bgcolor "#F9E8E0")
|
||||
(box :content "The Grid owns one definite width; its tracks divide that space without competing viewport calculations."
|
||||
:grid-column (1 :span 2) :width (718) :padding (1 0)
|
||||
:grid-column '(1 :span 2) :width '(718) :padding '(1 0)
|
||||
:color "#663322" :bgcolor "#FFFDF8"
|
||||
:text-align center :wrap-mode word))
|
||||
:text-align 'center :wrap-mode 'word))
|
||||
(spacer :height 1)
|
||||
(box :content "02 EXPLICIT PLACEMENT\nSpan columns, target cells, and leave the remaining nodes to auto placement."
|
||||
:width (720)
|
||||
:padding (0 (16))
|
||||
:width '(720)
|
||||
:padding '(0 (16))
|
||||
:border "#6D8A73"
|
||||
:border-bottom-p nil
|
||||
:color "#252A2E"
|
||||
:bgcolor "#DCEBDD"
|
||||
:wrap-mode word)
|
||||
:wrap-mode 'word)
|
||||
(grid
|
||||
:width (718)
|
||||
:grid-template-columns ((210) (210) 1fr)
|
||||
:gap (1 (10))
|
||||
:width '(720)
|
||||
:grid-template-columns '((210) (210) 1fr)
|
||||
:gap '(1 (10))
|
||||
:border "#6D8A73"
|
||||
:bgcolor "#F7FBF7"
|
||||
(box :content "SPAN 1 → 3" :grid-column (1 :span 2)
|
||||
:width (430) :padding (1 0) :text-align center
|
||||
(box :content "SPAN 1 → 3" :grid-column '(1 :span 2)
|
||||
:width '(430) :padding '(1 0) :text-align 'center
|
||||
:color "#24422D" :bgcolor "#DCEBDD")
|
||||
(box :content "COLUMN 3" :grid-column 3 :grid-row 1
|
||||
:width (278) :padding (1 0) :text-align center
|
||||
:width '(278) :padding '(1 0) :text-align 'center
|
||||
:color "#24422D" :bgcolor "#C8DDCB")
|
||||
(box :content "ROW 2 / COL 1" :grid-column 1 :grid-row 2
|
||||
:width (210) :padding (1 0) :text-align center
|
||||
:width '(210) :padding '(1 0) :text-align 'center
|
||||
:color "#24422D" :bgcolor "#EDF5EE")
|
||||
(box :content "AUTO PLACED" :width (210) :padding (1 0)
|
||||
:text-align center :color "#24422D" :bgcolor "#E3F0E5")
|
||||
(box :content "STABLE CELLS" :width (278) :padding (1 0)
|
||||
:text-align center :color "#24422D" :bgcolor "#D4E6D7"))
|
||||
(box :content "AUTO PLACED" :width '(210) :padding '(1 0)
|
||||
:text-align 'center :color "#24422D" :bgcolor "#E3F0E5")
|
||||
(box :content "STABLE CELLS" :width '(278) :padding '(1 0)
|
||||
:text-align 'center :color "#24422D" :bgcolor "#D4E6D7"))
|
||||
(spacer :height 1)
|
||||
(box :content "03 PUBLIC COMPOSITION\nColumn, Flex, and Grid share the same public node contract."
|
||||
:width (720)
|
||||
:padding (0 (16))
|
||||
:width '(720)
|
||||
:padding '(0 (16))
|
||||
:border "#4E7890"
|
||||
:border-bottom-p nil
|
||||
:color "#252A2E"
|
||||
:bgcolor "#D9EAF2"
|
||||
:wrap-mode word)
|
||||
:wrap-mode 'word)
|
||||
(flex
|
||||
:width (720)
|
||||
:flex-flow (row wrap)
|
||||
:gap (1 (12))
|
||||
:padding (1 (12))
|
||||
:width '(720)
|
||||
:flex-flow '(row wrap)
|
||||
:gap '(1 (12))
|
||||
:padding '(1 (12))
|
||||
:border "#4E7890"
|
||||
:bgcolor "#F7FAFC"
|
||||
(box :content "COLUMN\nvertical composition"
|
||||
:flex-grow 1 :flex-shrink 1 :flex-basis (200)
|
||||
:min-width (180) :padding (1 (12))
|
||||
:flex-grow 1 :flex-shrink 1 :flex-basis '(200)
|
||||
:min-width '(180) :padding '(1 (12))
|
||||
:color "#193846" :bgcolor "#D9EAF2")
|
||||
(box :content "FLEX\nwrap and distribute"
|
||||
:flex-grow 1 :flex-shrink 1 :flex-basis (200)
|
||||
:min-width (180) :padding (1 (12))
|
||||
:flex-grow 1 :flex-shrink 1 :flex-basis '(200)
|
||||
:min-width '(180) :padding '(1 (12))
|
||||
:color "#3F3655" :bgcolor "#E7E2F1")
|
||||
(box :content "GRID\nplace in two dimensions"
|
||||
:flex-grow 1 :flex-shrink 1 :flex-basis (200)
|
||||
:min-width (180) :padding (1 (12))
|
||||
:flex-grow 1 :flex-shrink 1 :flex-basis '(200)
|
||||
:min-width '(180) :padding '(1 (12))
|
||||
:color "#6B3020" :bgcolor "#F1D4C9"))
|
||||
(spacer :height 1)
|
||||
(box :content "PUBLIC CONTRACT ebox-create · ebox-column · ebox-flex · ebox-grid · ebox-spacer"
|
||||
:width (720)
|
||||
:padding (0 (16))
|
||||
:width '(720)
|
||||
:padding '(0 (16))
|
||||
:border "#8D887F"
|
||||
:color "#4D5651"
|
||||
:bgcolor "#EEEAE2"
|
||||
:wrap-mode word))
|
||||
:wrap-mode 'word))
|
||||
|
||||
65
examples/responsive-reference.ebox
Normal file
65
examples/responsive-reference.ebox
Normal file
@ -0,0 +1,65 @@
|
||||
(column
|
||||
:margin-left 1 :margin-top 1 :padding '(1 2 1 2) :bgcolor "linen"
|
||||
(box :content "Ebox Responsive Layout\nDrag the preview window: sections stretch to the current viewport, cards reflow, and text wraps without changing the window layout."
|
||||
:padding '(1 (18)) :border "#334155" :text-align 'center
|
||||
:color "#000" :bgcolor "ghost white")
|
||||
(spacer :height 1)
|
||||
|
||||
(box :content "No explicit viewport width here\nThis page mostly omits :width. The Playground binds the current preview width while rendering, so auto width behaves like a responsive container."
|
||||
:padding '(0 (16)) :border "#0F766E"
|
||||
:bgcolor "#F0FDFA" :color "#134E4A" :wrap-mode 'word)
|
||||
(spacer :height 1)
|
||||
|
||||
(box :content "Adaptive toolbar\nButtons below keep stable sizes. The row packs as many as fit and then wraps."
|
||||
:padding '(0 (16)) :border "#EA580C" :border-bottom-p nil
|
||||
:bgcolor "#FFF7ED" :color "#431407" :wrap-mode 'word)
|
||||
(flex :flex-flow '(row wrap) :column-gap '(8) :row-gap 1
|
||||
:padding '(1 (8)) :border "#FDBA74" :bgcolor "#FFFBF5"
|
||||
(box :content "Render" :width '(96) :padding '(0 (8))
|
||||
:border "#EA580C" :bgcolor "#FED7AA" :color "#111827"
|
||||
:text-align 'center)
|
||||
(box :content "Save" :width '(88) :padding '(0 (8))
|
||||
:border "#D97706" :bgcolor "#FEF3C7" :color "#111827"
|
||||
:text-align 'center)
|
||||
(box :content "Format" :width '(96) :padding '(0 (8))
|
||||
:border "#16A34A" :bgcolor "#DCFCE7" :color "#14532D"
|
||||
:text-align 'center)
|
||||
(box :content "Sample" :width '(104) :padding '(0 (8))
|
||||
:border "#0284C7" :bgcolor "#E0F2FE" :color "#0C4A6E"
|
||||
:text-align 'center)
|
||||
(box :content "Write" :width '(88) :padding '(0 (8))
|
||||
:border "#9333EA" :bgcolor "#F3E8FF" :color "#3B0764"
|
||||
:text-align 'center))
|
||||
(spacer :height 1)
|
||||
|
||||
(box :content "Responsive cards\nEach card starts from a flex-basis, grows when space is available, and wraps to new rows when the preview becomes narrow."
|
||||
:padding '(0 (16)) :border "#2563EB" :border-bottom-p nil
|
||||
:bgcolor "#EFF6FF" :color "#1E3A8A" :wrap-mode 'word)
|
||||
(flex :flex-flow '(row wrap) :column-gap '(12) :row-gap 1
|
||||
:padding '(1 (8)) :border "#93C5FD" :bgcolor "#F8FBFF"
|
||||
:justify-content 'center
|
||||
(item :flex '(1 1 (210))
|
||||
(box :content "Overview\nThe row uses the current preview width automatically."
|
||||
:min-width '(180) :max-width '(280)
|
||||
:padding '(0 (10)) ;; :border "#2563EB"
|
||||
:bgcolor "#DBEAFE" :color "#111827" :wrap-mode 'word))
|
||||
(item :flex '(1 1 (210))
|
||||
(box :content "Editor\nDrag slowly or quickly; resize rendering is debounced."
|
||||
:min-width '(180) :max-width '(300)
|
||||
:padding '(0 (10)) ;; :border "#4F46E5"
|
||||
:bgcolor "#E0E7FF" :color "#111827" :wrap-mode 'word))
|
||||
(item :flex '(1 1 (210))
|
||||
(box :content "Preview\nThe preview buffer rerenders after the viewport settles."
|
||||
:min-width '(180) :max-width '(320)
|
||||
:padding '(0 (10)) ;; :border "#7C3AED"
|
||||
:bgcolor "#EDE9FE" :color "#111827" :wrap-mode 'word))
|
||||
(item :flex '(1 1 (210))
|
||||
(box :content "Flow\nCards keep readable widths instead of overflowing."
|
||||
:min-width '(180) :max-width '(280)
|
||||
:padding '(0 (10)) ;; :border "#0891B2"
|
||||
:bgcolor "#CFFAFE" :color "#164E63" :wrap-mode 'word)))
|
||||
(spacer :height 1)
|
||||
|
||||
(box :content "What to watch\nNarrow preview: cards stack and text wraps. Wide preview: cards share a row and expand up to max-width. The source/preview split is preserved."
|
||||
:padding '(0 (16)) :border "#475569"
|
||||
:bgcolor "#F8FAFC" :color "#0F172A" :wrap-mode 'word))
|
||||
@ -1,8 +1,22 @@
|
||||
;;; ebox-playground-tests.el --- Public Ebox example tests -*- lexical-binding: t; -*-
|
||||
|
||||
(require 'ert)
|
||||
(require 'cl-lib)
|
||||
(require 'ebox-playground)
|
||||
|
||||
(defconst ebox-playground-test--fixtures
|
||||
'("basic.ebox" "comprehensive.ebox" "flex-reference.ebox"
|
||||
"responsive-reference.ebox" "grid-reference.ebox")
|
||||
"Migrated and maintained `.ebox' fixtures in the playground package.")
|
||||
|
||||
(defun ebox-playground-test--dynamic-width ()
|
||||
"Return a list-valued width from executable DSL property code."
|
||||
'(240))
|
||||
|
||||
(defun ebox-playground-test--dynamic-color ()
|
||||
"Return a color from executable DSL property code."
|
||||
"#123456")
|
||||
|
||||
(ert-deftest ebox-playground-uses-only-public-layout-apis ()
|
||||
"The example should build and render through the public Ebox entry point."
|
||||
(let* ((node (ebox-playground-view))
|
||||
@ -22,7 +36,37 @@
|
||||
(should (file-readable-p ebox-playground-default-file))
|
||||
(should (string-suffix-p ".ebox" ebox-playground-default-file))
|
||||
(should-not (string-match-p "FIXED TRACK" runner))
|
||||
(should-not (string-match-p "PUBLIC COMPOSITION" runner))))
|
||||
(should-not (string-match-p "PUBLIC COMPOSITION" runner))
|
||||
(should-not (string-match-p "GRID TOOLKIT" runner))))
|
||||
|
||||
(ert-deftest ebox-playground-migrated-fixtures-render-at-the-canvas-width ()
|
||||
"Every migrated fixture should render through the generic file boundary."
|
||||
(let ((ebox-viewport-width 720))
|
||||
(dolist (file ebox-playground-test--fixtures)
|
||||
(let* ((path (expand-file-name (concat "examples/" file)
|
||||
ebox-playground-directory))
|
||||
(text (substring-no-properties
|
||||
(ebox-render (ebox-playground-view path))))
|
||||
(widths (mapcar #'ebox-string-pixel-width
|
||||
(ebox-string-lines text))))
|
||||
(should (file-readable-p path))
|
||||
(should (stringp text))
|
||||
(should (cl-every (lambda (width) (<= width 720)) widths))))))
|
||||
|
||||
(ert-deftest ebox-playground-grid-reference-covers-public-properties ()
|
||||
"The Grid reference should name every public Grid property in the fixture."
|
||||
(let ((source (with-temp-buffer
|
||||
(insert-file-contents
|
||||
(expand-file-name "examples/grid-reference.ebox"
|
||||
ebox-playground-directory))
|
||||
(buffer-string))))
|
||||
(dolist (property '(:grid-template-columns :grid-template-rows
|
||||
:grid-auto-columns :grid-auto-rows :grid-auto-flow
|
||||
:grid-row-gap :grid-column-gap :gap
|
||||
:justify-items :align-items :justify-content
|
||||
:align-content :grid-column :grid-row
|
||||
:grid-column-span :grid-row-span))
|
||||
(should (string-match-p (regexp-quote (symbol-name property)) source)))))
|
||||
|
||||
(ert-deftest ebox-playground-opens-and-closes-buffer ()
|
||||
"The public open and close commands should own their buffer lifecycle."
|
||||
@ -59,7 +103,7 @@
|
||||
(unwind-protect
|
||||
(with-temp-buffer
|
||||
(setq buffer-file-name "/tmp/ebox-playground-render-test.ebox")
|
||||
(insert "(box :content \"Rendered from .ebox\" :width (240))")
|
||||
(insert "(box :content \"Rendered from .ebox\" :width '(240))")
|
||||
(ebox-dsl-mode)
|
||||
(ebox-dsl-render)
|
||||
(with-current-buffer preview
|
||||
@ -67,6 +111,20 @@
|
||||
(when (get-buffer preview)
|
||||
(kill-buffer preview)))))
|
||||
|
||||
(ert-deftest ebox-playground-evaluates-property-expressions ()
|
||||
"Evaluate executable property values while preserving quoted constants."
|
||||
(let* ((form (ebox-playground--evaluate-form
|
||||
'(box :content "Dynamic property values"
|
||||
:width (ebox-playground-test--dynamic-width)
|
||||
:color (ebox-playground-test--dynamic-color)
|
||||
:padding '(0 (4))
|
||||
:text-align 'center)))
|
||||
(node (ebox-build form)))
|
||||
(should (equal (plist-get node :width) 240))
|
||||
(should (equal (plist-get node :color) "#123456"))
|
||||
(should (equal (plist-get node :padding-left-pixel) 4))
|
||||
(should (eq (plist-get node :text-align) 'center))))
|
||||
|
||||
(provide 'ebox-playground-tests)
|
||||
|
||||
;;; ebox-playground-tests.el ends here
|
||||
|
||||
Loading…
Reference in New Issue
Block a user