diff --git a/src/uix/morfo/components/flex.ts b/src/uix/morfo/components/flex.ts new file mode 100644 index 000000000..eaf9b09f7 --- /dev/null +++ b/src/uix/morfo/components/flex.ts @@ -0,0 +1,29 @@ +import type { Morfo } from '../types'; + +/** + * Flex — `display:flex` container (layout primitive). + * + * Eidos-native: every public prop maps to a `--flex-*` (or inherited + * `--box-*`) custom property. The provider is a single `
` shell — Flex composes through ``. + * + * No semantic events — Flex is a passive container that arranges its + * children. See `box.ts` for the same 0-event justification. + */ +export const flexMorfo = { + name: 'Flex', + kebab: 'flex', + scope: ['eidos'], + parts: [ + { + name: 'Provider', + kebab: 'provider', + archetype: 'provider', + kind: 'public', + defaultElement: 'div', + optional: false, + data: [], + aria: [] + } + ] +} as const satisfies Morfo; diff --git a/web/routes/uix/components/flex/+page.svelte b/web/routes/uix/components/flex/+page.svelte index 4fa80021d..34907d616 100644 --- a/web/routes/uix/components/flex/+page.svelte +++ b/web/routes/uix/components/flex/+page.svelte @@ -1,9 +1,105 @@
@@ -11,85 +107,302 @@
Layout · Flex

Flex

- display:flex container with direction, wrap, alignment and gap. + display:flex container. Adds direction / align / + justify / wrap / rowGap / columnGap + on top of every <Box> prop. For grid containers + use <Grid>; for flex/grid item props + (alignSelf, gridColumn, order, basis, …) use <Box> on the child.

+
+ + parts{compiled.parts.order.length} + + + events0 + + + extendsBox + + + scopeeidos + +
-
-

Live example

- - Start - Middle - End - -
- -
-

Props

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PropDefaultNotes
inlinefalseswitch to inline-flex
direction'row'row · row-reverse · column · column-reverse
wrap'nowrap'nowrap · wrap · wrap-reverse
align—stretch · start · center · end · baseline
justify—start · center · end · space-between · space-around · space-evenly
gap / rowGap / columnGap—row/columnGap override gap per axis
… plus every BoxProps prop except display
-
- -
-

Reference

-
    -
  • - radix-themes Flex — same surface (direction, - align, justify, wrap, gap). -
  • -
  • - chakra-ui Flex — origin of the responsive Flex container API; - our prop names match. -
  • -
-
+ +
+
+ + Item A + Item B + Item C + +
+
+ trace + {trace.length === 0 ? 'no semantic events' : `${trace.length} event(s)`} + · + direction + {direction} + + align {align} · + justify {justify} + +
+
+ +
+ + + + + + +
+ + {#if tab === 'live'} +
+

Controls

+

+ Flex is eidos-native — no soma split. The 7 + container-side props below map to --flex-* CSS variables. Flex also inherits + every Box prop (padding, margin, size, position) by + composition. +

+ +
+ eidos props · container behaviour +
+
+ + + + + + + +
+ + +
+
+ soma + n/a · flex is eidos-native — equivalent markup shown + svelte +
+
{somaSnippet}
+
+ +
+
+ eidos + visual · container props mapped to --flex-* CSS variables + svelte +
+
{eidosSnippet}
+
+
+ {/if} + + {#if tab === 'api'} +
+

API reference

+

+ Flex adds container-side flex props on top of every BoxProps field. Pass + inline to switch to inline-flex; otherwise the provider renders + with display:flex. Item-side props (flex, grow, + shrink, basis, order, alignSelf, + justifySelf, placeSelf) live on the child + <Box>. +

+ +
Container props (Flex-only)
+
+ + + + + + + + + + + +
PropTypeDefaultNotes
inlinebooleanfalseSwitches to display:inline-flex.
directionrow | row-reverse | column | column-reverse'row'flex-direction.
alignstretch | start | center | end | baseline | flex-start | flex-end—align-items — cross-axis.
justifystart | center | end | space-between | space-around | space-evenly | stretch | flex-start | flex-end—justify-content — main-axis.
wrapnowrap | wrap | wrap-reverse'nowrap'flex-wrap.
gapnumber | string—Number → var(--space-N).
rowGap / columnGapnumber | string—Per-axis gap override; takes precedence over gap.
+
+ +
Inherited from Box
+

+ Every BoxProps field is forwarded: + padding*, margin*, width, height, + position, top/right/bottom/left, overflow*, plus + item-side props that apply when this Flex is itself an item of a parent flex/grid + (alignSelf, gridColumn, …). +

+ +
Reference comparison
+
+ + + + + + + +
LibraryClosest equivalentDifference
radix-themes<Flex>Same shape: container props on Flex, item props on Box. Radix uses flexShrink spelling; UIX uses shrink.
chakra-ui<Flex> / <HStack> / <VStack>Chakra also exposes <HStack>/<VStack> as direction-specific helpers. UIX uses <Stack> with a direction prop.
mantine<Flex> / <Group>Mantine splits row-only into <Group>; UIX has the same split.
+
+
+ {/if} + + {#if tab === 'morfo'} +
+

Morfo contract

+ +
+ + + + + + + + + +
FieldValue
name{flexMorfo.name}
kebab{flexMorfo.kebab}
scope{flexMorfo.scope.join(', ')}
parts{partsList.length}
events0
+
+ +
Parts
+
+ + + + {#each partsList as part} + + + + + + + + {/each} + +
kebabmarkerelementarchetypeoptional
{part.kebab}[{part.marker}]<{part.defaultElement}>{part.archetype}{part.optional ? 'yes' : 'no'}
+
+ +

+ Flex composes through <Box>, so the rendered DOM is a single + div[data-box][data-flex] shell. Recipe lives at + src/uix/eidos/components/flex/flex.css and layers on top of the Box + recipe. +

+
+ {/if} + + {#if tab === 'sema'} +
+

+ sema · events +

+

+ Flex declares no semantic events. As a passive layout primitive, it does not commit, + emerge, or react to anything — it just arranges its children. Components that animate + on appearance should compose Flex with an interactive primitive (popover, drawer, + collapsible) that owns the relevant sema verbs. +

+
+ {/if} + + {#if tab === 'recipe'} +
+

Eidos recipe

+

+ Recipe lives in src/uix/eidos/components/flex/flex.css and layers on top + of the Box recipe. The provider element carries both data-box and + data-flex markers because Flex renders through Box. +

+
+ + + + + + + + + + + + + + +
SelectorOwnerPurpose
[data-flex]morfoProvider marker.
[data-box][data-flex] {`{ display: flex | inline-flex; flex-direction: var(--flex-direction, row); … }`}eidosLayer container-side flex properties on the Box recipe.
+
+
+ {/if} + + {#if tab === 'a11y'} +
+

Accessibility

+
+ + + + + + + + +
ConcernContract
RoleNone implicit. Default element is <div> — semantically neutral. Use a semantic wrapper (<nav>, <header>, <ul role="list">) around Flex when content needs a landmark or list semantics.
LabelNot applicable — Flex has no content semantics. Labels belong to the interactive children.
KeyboardFlex is not focusable. Tab order follows DOM order even when direction visually reverses (row-reverse / column-reverse). Verify visual order matches focus order for keyboard users.
Reduced motionFlex does not animate. Layout shifts on resize follow CSS defaults — no transition on the recipe.
+
+
+ {/if}