CoUI MockupWindow#
ํ๋ง๋๋ก (๋น๊ฐ๋ฐ์์ฉ)#
MockupWindow๋ ํ๋ฉด ์์ "๋งฅ(macOS) ์ปดํจํฐ ์ฐฝ ๋ชจ์์ ์ก์"๋ฅผ ๊ทธ๋ ค์ฃผ๋ ๋ถํ์ ๋๋ค. ์ผ์ชฝ ์์ ๋นจ๊ฐยท๋ ธ๋ยท์ด๋ก ์ 3๊ฐ(์ ํธ๋ฑ ๋ฒํผ)๊ฐ ๋ฌ๋ฆฐ ์ฐฝ ํ ๋๋ฆฌ๋ฅผ ๋ง๋ค๊ณ , ๊ทธ ์์ ์ํ๋ ๋ด์ฉ(์คํฌ๋ฆฐ์ท, ๋ฐ๋ชจ ํ๋ฉด, ์ค๋ช ๋ฑ)์ ๋ฃ์ด ๋ณด์ฌ์ค๋๋ค. ์ง์ง ์ฐฝ์ด ์๋๋ผ "์ฐฝ์ฒ๋ผ ๋ณด์ด๊ฒ ํ๋ ์ฅ์ ํ๋ ์"์ด๋ผ์, ์ ๋ค์ ๋๋ฌ๋ ์๋ฌด ์ผ๋ ์ผ์ด๋์ง ์์ต๋๋ค. ๋๋ฉ ํ์ด์ง์์ ์ ํ ํ๋ฉด์ ๊ทธ๋ด๋ฏํ๊ฒ ์ฐ์ถํ ๋ ์ฐ๋ ์ฌ์ง ์ก์๋ผ๊ณ ์๊ฐํ๋ฉด ๋ฉ๋๋ค.
๋ฌด์์ยท์ธ์ (๋น๊ฐ๋ฐ์์ฉ)#
- ๋ฌด์์ ํด์ฃผ๋์: ๋ด์ฉ๋ฌผ ์์ "์ ๋ชฉ ํ์์ค + ์ ํธ๋ฑ ์ 3๊ฐ"๊ฐ ๋ถ์ ๋ฐ์คํฌํฑ ์ฐฝ ํ๋ ์์ ์์ ์ค๋๋ค. ํ ๋๋ฆฌยท๋ฅ๊ทผ ๋ชจ์๋ฆฌยท๋ฐฐ๊ฒฝ์๊น์ง ์์์ ํต์ผ๋ ๋ชจ์์ผ๋ก ๋์ต๋๋ค.
- ์ธ์ ์ฐ์ด๋์: ๋๋ฉ/์๊ฐ ํ์ด์ง์์ ์ฑ ํ๋ฉด์ ์ฐฝ ์์ ๋ด์ ๋ณด์ฌ์ค ๋, ๋ฌธ์ยทํฌํธํด๋ฆฌ์ค์์ ๋ฐ๋ชจ ํ๋ฉด์ ์ฐ์ถํ ๋, ๋์์ธ ์์์์ "์ด๊ฑด ๋ฐ์คํฌํฑ ์ฑ ํ๋ฉด์ด๋ค"๋ผ๊ณ ํํํ๊ณ ์ถ์ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
- ๋๋ฆฌ๋ ๊ฑด๊ฐ์: ์๋์. ๋นจ๊ฐยท๋ ธ๋ยท์ด๋ก ์ ์ ์์ํ ์ฅ์์ด๋ผ ํด๋ฆญ/ํญํด๋ ๋์ํ์ง ์์ต๋๋ค.
- ๊พธ๋ฐ ์ ์๋์: ๋ฐฐ๊ฒฝ์, ํ ๋๋ฆฌ์, ๋ชจ์๋ฆฌ ๋ฅ๊ธ๊ธฐ, ์ ๋ชฉ ํ์์ค ๋์ด, ์ ํฌ๊ธฐยท์๊น์ง ์ธ๋ถ ์ค์ ํ ๊ณณ(mockupWindowStyle)์์ ๋ฐ๊ฟ ์ ์์ต๋๋ค.
- ํ ๋ฒ ์ ํด๋๋ฉด ํต์ผ๋ฉ๋๋ค: ์ฑ(Flutter)๊ณผ ์น ์์ชฝ์์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ๋ง๋ค์ด์ง๊ณ , ํ๋ก์ ํธ ์ ์ฒด์ ๊ธฐ๋ณธ ๋ชจ์์ ํ๊ณณ(ํ ๋ง)์์ ์ ํด๋ ์๋ ์์ต๋๋ค.
- ํ์ ๋ถํ๋ ์์ต๋๋ค: ๋ธ๋ผ์ฐ์ ์ฐฝ(MockupBrowser), ํด๋ํฐ ํ๋ ์(MockupPhone), ์ฝ๋ ํ๋ฉด(MockupCode)๋ ๊ฐ์ ๊ณ์ด์ "์ฐ์ถ์ฉ ์ก์"์ ๋๋ค.
ํต์ฌ ์ฉ์ด (๋น๊ฐ๋ฐ์์ฉ)#
| ์ฉ์ด | ์ฌ์ด ์ค๋ช |
|---|---|
| MockupWindow | ๋งฅ ์คํ์ผ ์ฐฝ ๋ชจ์์ ํ๋ด ๋ด๋ ์ฅ์์ฉ ์ก์ ๋ถํ |
| title bar (์ ๋ชฉ ํ์์ค) | ์ฐฝ ๋งจ ์์ ๊ฐ๋ก ๋ โ ์ ํธ๋ฑ ์ 3๊ฐ๊ฐ ๋ค์ด๊ฐ๋ ์๋ฆฌ |
| traffic light (์ ํธ๋ฑ ์ ) | ์ผ์ชฝ ์ ๋นจ๊ฐ(๋ซ๊ธฐ)ยท๋ ธ๋(์ต์ํ)ยท์ด๋ก(์ต๋ํ) ์ฅ์ ์ 3๊ฐ |
| child | ์ฐฝ ์์ ๋ฃ๋ ๋ด์ฉ๋ฌผ (์คํฌ๋ฆฐ์ท, ํ ์คํธ, ๋ฐ๋ชจ ํ๋ฉด ๋ฑ) |
| mockupWindowStyle | ์ด ์ฐฝ ํ๋๋ง ๋ค๋ฅด๊ฒ(์ยทํฌ๊ธฐยท๋ชจ์๋ฆฌ ๋ฑ) ๊พธ๋ฏธ๋ ์ธ๋ถ ์ค์ ์นธ |
| theme / theming | ํ๋ก์ ํธ ์ ์ฒด ์ฐฝ ์ก์์ ๊ณตํต ์ ์ฉ๋๋ ๊ธฐ๋ณธ ๋ชจ์ ์ค์ |
| Flutter | ๋ชจ๋ฐ์ผ/์ฑ ํ๋ฉด์ ๋ง๋๋ ๊ธฐ์ |
| Web | ์น ๋ธ๋ผ์ฐ์ ์ฉ ํ๋ฉด์ ๋ง๋๋ ๊ธฐ์ |
| Legacy / Deprecated | ์๋ ๋ฐฉ์์ด๋ผ ์ ์ฝ๋์์๋ ์ฐ์ง ๋ง์์ผ ํ๋, ๊ณง ์ฌ๋ผ์ง ํญ๋ชฉ |
Overview#
MockupWindow is the unified cross-platform OS-window mockup: an outer frame with a title bar carrying three macOS-style traffic-light dots (close/minimize/maximize) above a content slot. It is a pure display component โ the dots are decorative, there are no callbacks, and there are
no semantic enums (no variant, no size). The entire surface is:
-
childโ optional window content (Widget?on Flutter,Component?on Web). -
mockupWindowStyleโ the single per-instance style slot (CoreMockupWindowStyle), covering every chrome/colour/dimensional knob.
It implements the shared CoreMockupWindowContract<W> from coui_core, so Flutter and Web take the same style type and resolve through the same chain. Sibling mockups in the same family:
MockupBrowser, MockupPhone, MockupCode โ all recolourable at once via the shared
CoreMockupTheme.
Rendered structure (both platforms):
frame (background, border, borderRadius, clipped)
โโ title bar (height, horizontal padding, bottom border)
โ โโ dot: close (red #FF5F57)
โ โโ dot: minimize (amber #FFBD2E)
โ โโ dot: maximize (green #28C840)
โโ content (child)
Flutter (coui_flutter)#
Import#
import 'package:coui_flutter/coui_flutter.dart';
Single barrel only โ never import src/ paths.
Basic Usage#
MockupWindow(
child: const Padding(
padding: EdgeInsets.all(16),
child: Text('Window content'),
),
)
child is optional โ omit it to render just the empty frame with its title bar:
const MockupWindow()
The frame clips its content (clipBehavior: antiAlias), so images or colored children are trimmed to the rounded corners automatically. The column is
mainAxisSize: min / crossAxisAlignment: stretch โ the window hugs its content height and stretches content to the frame width.
Screenshot / demo frame pattern#
MockupWindow(
child: SizedBox(
height: 300,
child: Center(child: Text('App preview')),
),
)
Per-instance Style (mockupWindowStyle)#
mockupWindowStyle takes a CoreMockupWindowStyle. All fields are optional; anything unset falls back through the theme chain to the design-system defaults.
MockupWindow(
mockupWindowStyle: const CoreMockupWindowStyle(
borderRadius: CoreBorderRadius.all(CoreRadius.radius8),
titleBarHeight: 32,
trafficLightSize: 10,
),
child: const Text('Compact window'),
)
Recolour example (token-bound frame + custom dots):
MockupWindow(
mockupWindowStyle: const CoreMockupWindowStyle(
backgroundColor: CoreColor.token(CoreColors.surface),
borderColor: CoreColor.token(CoreColors.outline),
trafficLightCloseColor: CoreColor(0xFF888888),
trafficLightMinimizeColor: CoreColor(0xFF888888),
trafficLightMaximizeColor: CoreColor(0xFF888888),
),
child: const Text('Monochrome chrome'),
)
Flutter-specific behavior notes#
-
All dimensional values (radius, title-bar spacing/padding/height, dot size/radius) are pre-multiplied by
theme.scalingin the resolver โ the widget paints them as-is. -
Colours resolve through
theme.colorSchemeto paint-readyColors; the title bar's bottom divider uses the same resolvedborderColoras the outer frame. -
Dot spacing flows into
Row.spacing(titleBarSpacingis a scalar, logical px).
Web (coui_web / Jaspr)#
Import#
import 'package:coui_web/coui_web.dart';
Basic Usage#
child is a Jaspr Component:
MockupWindow(
child: div([text('Window content')], classes: 'p-4'),
)
Multiple content blocks (children)#
Web additionally accepts a children: List<Component>? โ rendered before child
inside the frame:
MockupWindow(
children: [
div([text('Toolbar')], classes: 'p-2'),
div([text('Body')], classes: 'p-4'),
],
)
Per-instance Style (same CoreMockupWindowStyle)#
MockupWindow(
mockupWindowStyle: const CoreMockupWindowStyle(
borderRadius: CoreBorderRadius.all(CoreRadius.radius8),
),
child: div([text('Custom radius')]),
)
Colour channels are class-XOR-inline: a token colour (default or token override, e.g. the surface
background / outline border) emits a Tailwind bg-*/border-* class and stays dark-mode reactive; a raw
CoreColor(0xFF...) override goes inline. The traffic-light defaults are raw macOS palette values, so they render as inline
background-color. All dimensional values (radius, gap, padding, height, dot size) are always inline rem โ never utility classes.
Web-only constructor extras#
The Web constructor also accepts tag (root element tag, default 'div'), id,
classes, css (Jaspr Styles), attributes, and eventHandlers. User
classes are merged after the resolved class string; user css is combined after the resolved inline styles. The component also provides
copyWith(...).
MockupWindow(
classes: 'max-w-3xl mx-auto',
child: div([text('Hero demo')]),
)
Note: the Web root carries w-full โ it fills its container's width (constrain it with a wrapper or
classes as above), whereas the Flutter frame just follows its parent constraints.
Parameters#
| Parameter | Type (Flutter) | Type (Web) | Default | Notes |
|---|---|---|---|---|
child |
Widget? |
Component? |
null |
Window content (optional โ empty frame is valid) |
mockupWindowStyle |
CoreMockupWindowStyle? |
CoreMockupWindowStyle? |
null |
Single per-instance chrome/colour/dimension slot |
Web-only: children (List<Component>?, rendered before child),
tag (default 'div'), id, classes, css
(Jaspr Styles), attributes, eventHandlers, plus copyWith(...).
There are no variant / size enums on this component โ MockupWindow
is a single-form display frame; every visual knob lives on the style slot below.
Style slot โ CoreMockupWindowStyle (full field set + defaults)#
Constructor fields (all optional) and their design-system defaults (statics on CoreMockupWindowStyle, shared by Flutter and Web):
| Field | Type | Default (static) | Value |
|---|---|---|---|
backgroundColor |
CoreColor? |
defaultBackgroundColor |
token surface |
borderColor |
CoreColor? |
defaultBorderColor |
token outline (frame + title-bar divider) |
borderRadius |
CoreBorderRadius? |
defaultBorderRadius |
CoreBorderRadius.all(CoreRadius.radius16) |
titleBarSpacing |
double? |
defaultTitleBarSpacing |
CoreSpace.space8 (gap between dots, logical px) |
titleBarPadding |
CoreEdgeInsets? |
defaultTitleBarPadding |
CoreEdgeInsets.symmetric(horizontal: CoreSpace.space12) |
titleBarHeight |
double? |
defaultTitleBarHeight |
CoreSpace.space40 (logical px) |
trafficLightSize |
double? |
defaultTrafficLightSize |
CoreSpace.space12 (logical px) |
trafficLightBorderRadius |
CoreBorderRadius? |
defaultTrafficLightBorderRadius |
CoreBorderRadius.all(CoreRadius.radius9999) (perfect circle) |
trafficLightCloseColor |
CoreColor? |
defaultTrafficLightCloseColor |
raw CoreColor(0xFFFF5F57) (macOS red) |
trafficLightMinimizeColor |
CoreColor? |
defaultTrafficLightMinimizeColor |
raw CoreColor(0xFFFFBD2E) (macOS yellow) |
trafficLightMaximizeColor |
CoreColor? |
defaultTrafficLightMaximizeColor |
raw CoreColor(0xFF28C840) (macOS green) |
CoreMockupWindowStyle also exposes merge(other) and copyWith(...).
Project-level theming#
Two theme slots participate, both { style }-shaped:
-
CoreMockupWindowTheme(coreComponentTheme.mockupWindow) โ window-specific project defaults, carries a fullCoreMockupWindowStyle. -
CoreMockupTheme(coreComponentTheme.mockup) โ shared across all mockup variants (Browser/Code/Phone/Window). ItsCoreMockupStyleexposes onlybackgroundColor/borderColor/frameColor/borderRadius; the Window resolver consumes the first three minusframeColor(phone-only) โ i.e. background, border, and radius can be recoloured for every mockup frame at once.
Resolve chain (lowest โ highest priority; identical on both platforms):
CoreMockupWindowStyle design-system defaults
โ CoreMockupTheme.style // shared cross-variant (bg/border/radius only)
โ CoreMockupWindowTheme.style // ํ๋ก์ ํธ ๊ณตํต
โ widget.mockupWindowStyle // ์ธ์คํด์ค๋ณ
const CoreMockupWindowTheme(
style: CoreMockupWindowStyle(
borderRadius: CoreBorderRadius.all(CoreRadius.radius8),
titleBarHeight: 32,
),
)
Register it on the app theme's coreComponentTheme.mockupWindow slot; the shared recolour goes on
coreComponentTheme.mockup (CoreMockupTheme(style: CoreMockupStyle(...))). Both platform resolvers read the same two slots.
Flutter โ Web Differences#
| Aspect | Flutter | Web |
|---|---|---|
| Widget class | MockupWindow (StatelessWidget, CoreMockupWindowContract<Widget>) |
MockupWindow (UiComponent, CoreMockupWindowContract<Component>) |
| Child type | Widget? |
Component? + extra children: List<Component>? |
| Content order | title bar โ child |
title bar โ ...children โ child |
| Render | Container + Column, clipBehavior: antiAlias |
element (default
<div>
, configurable
tag
) with Tailwind className + inline styles,
overflow-hidden relative
|
| Width behavior | follows parent constraints | root gets w-full (fills container) |
| Dimensions | pre-multiplied by theme.scaling, painted as logical px |
emitted as inline rem CSS |
| Colours | resolved via theme.colorScheme to paint-ready Color |
token โ Tailwind class (dark-mode reactive); raw ARGB โ inline CSS |
| Extra ctor params | โ |
tag
,
id
,
classes
,
css
,
attributes
,
eventHandlers
; also
copyWith(...)
|
Shared on both: mockupWindowStyle: CoreMockupWindowStyle, CoreMockupWindowTheme
/ shared CoreMockupTheme resolve chain, decorative-only traffic lights (no callbacks anywhere).
v0.127 Migration (Legacy)#
v0.127 is a de-prefix hard break: the widget class was renamed and no Co-prefixed alias remains.
Core* contract names (CoreMockupWindowStyle, CoreMockupWindowTheme,
CoreMockupTheme, CoreMockupWindowContract) are unchanged.
| โ Legacy (pre-0.127, removed) | โ v0.127 |
|---|---|
โ CoMockupWindow(child: โฆ) | MockupWindow(child: โฆ) |
โ CoMockupBrowser(โฆ) (sibling) | MockupBrowser(โฆ) |
โ CoMockupPhone(โฆ) (sibling) | MockupPhone(โฆ) |
โ CoMockupCode(โฆ) (sibling) | MockupCode(โฆ) |
Additional migration notes:
-
Migration is rename-only for this component: โ
CoMockupWindow(...)โMockupWindow(...)with identical parameters (child,mockupWindowStyle). -
App-shell exceptions that keep the prefix:
CoUIApp,CoUILocalizations,CoUIScrollBehavior. -
Import stays the single barrel:
package:coui_flutter/coui_flutter.dart/package:coui_web/coui_web.dartโ neversrc/paths.