feat(demos): expose the `shape` control in Badge/Button/Card/TagsInput demos

The shape prop was usable but invisible — add a live `shape` chip control
(rounded/continuous/cut/scoop) to each demo, wired to the live preview + code
snippet, plus a "shape families" patterns row in Badge and a tag-shape control on
TagsInput items. The family system is now discoverable, not just documented.

Verified live (Chrome 146): badge cut -> bevel, button continuous -> squircle,
both flow from the control to the rendered component.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
active-uix
dev 4 months ago
parent 4045e308b1
commit 27c8214d98

@ -18,8 +18,9 @@ como prop, además del default del tema. Diferenciador fuerte en **chips y badge
- **No** aplicar familias a círculos / píldoras (avatares): las deformaría (un avatar - **No** aplicar familias a círculos / píldoras (avatares): las deformaría (un avatar
`continuous` se vuelve squircle, un `cut` octágono). El default de esos componentes debe `continuous` se vuelve squircle, un `cut` octágono). El default de esos componentes debe
quedarse en `rounded`. quedarse en `rounded`.
- **Demo en componentes reales**: falta un control `shape` en las demos de badge/button/card - ✅ **Demos (2026-06-05)**: control `shape` en vivo en las demos de **badge · button · card ·
(hoy la prop existe y está verificada por probe, pero no se enseña en su demo). tags-input** (chips + code snippet + fila de patrones en badge). Ya es descubrible, no solo
documentado.
- **scoop / cóncavo**: en Chromium actual, `corner-shape: scoop` con `border` + `box-shadow` - **scoop / cóncavo**: en Chromium actual, `corner-shape: scoop` con `border` + `box-shadow`
proyecta la sombra DENTRO de los entrantes y el borde de 1px hace costura en las esquinas proyecta la sombra DENTRO de los entrantes y el borde de 1px hace costura en las esquinas
cóncavas → se ve sucio. Para chips/badges `scoop` (y `cut`), preferir **relleno plano** sin cóncavas → se ve sucio. Para chips/badges `scoop` (y `cut`), preferir **relleno plano** sin

@ -6,6 +6,7 @@
type BadgeVariant, type BadgeVariant,
type BadgeRounded type BadgeRounded
} from '$uix/eidos/components/badge'; } from '$uix/eidos/components/badge';
import { SHAPE_FAMILIES, type ShapeFamily } from '$uix/eidos/lib/types';
import { Box } from '$uix/eidos/components/box'; import { Box } from '$uix/eidos/components/box';
import { Stack } from '$uix/eidos/components/stack'; import { Stack } from '$uix/eidos/components/stack';
import { compileMorfo } from '$uix/morfo'; import { compileMorfo } from '$uix/morfo';
@ -23,6 +24,7 @@
let size = $state<BadgeSize>('md'); let size = $state<BadgeSize>('md');
let color = $state<BadgeColor>('primary'); let color = $state<BadgeColor>('primary');
let rounded = $state<BadgeRounded>('full'); let rounded = $state<BadgeRounded>('full');
let shape = $state<ShapeFamily>('rounded');
let labelText = $state('New'); let labelText = $state('New');
let withDot = $state(false); let withDot = $state(false);
let withIcon = $state(false); let withIcon = $state(false);
@ -84,6 +86,7 @@
size !== 'md' && ` size="${size}"`, size !== 'md' && ` size="${size}"`,
color !== 'primary' && ` color="${color}"`, color !== 'primary' && ` color="${color}"`,
rounded !== 'full' && ` rounded="${rounded}"`, rounded !== 'full' && ` rounded="${rounded}"`,
shape !== 'rounded' && ` shape="${shape}"`,
withDot && ' dot', withDot && ' dot',
removable && ' removable', removable && ' removable',
removable && ' onRemove={() => removeTag(id)}', removable && ' onRemove={() => removeTag(id)}',
@ -166,6 +169,7 @@
{size} {size}
{color} {color}
{rounded} {rounded}
{shape}
dot={withDot} dot={withDot}
{removable} {removable}
onRemove={handleRemove} onRemove={handleRemove}
@ -259,6 +263,16 @@
{/each} {/each}
</span> </span>
</label> </label>
<label data-uix-control>
<span data-uix-control-label>shape</span>
<span data-uix-chips role="radiogroup">
{#each SHAPE_FAMILIES as sh (sh)}
<button data-uix-chip data-active={shape === sh} onclick={() => (shape = sh)}
>{sh}</button
>
{/each}
</span>
</label>
<label data-uix-control> <label data-uix-control>
<span data-uix-control-label>label</span> <span data-uix-control-label>label</span>
<input <input
@ -314,6 +328,15 @@
<Badge variant="soft" color="loss" dot>Archived</Badge> <Badge variant="soft" color="loss" dot>Archived</Badge>
<Badge variant="soft" color="neutral" dot>Draft</Badge> <Badge variant="soft" color="neutral" dot>Draft</Badge>
</Box> </Box>
<Box
style="padding: var(--uix-space-4); border: 1px solid var(--uix-border); border-radius: var(--uix-radius-md); display: flex; flex-wrap: wrap; gap: var(--uix-space-2); align-items: center;"
>
<code style="min-inline-size: 8rem; color: var(--uix-text-faint);">shape families</code>
<Badge variant="soft" color="primary" rounded="md" shape="rounded">rounded</Badge>
<Badge variant="soft" color="primary" rounded="md" shape="continuous">continuous</Badge>
<Badge variant="solid" color="primary" rounded="md" shape="cut">cut</Badge>
<Badge variant="solid" color="primary" rounded="md" shape="scoop">scoop</Badge>
</Box>
<Box <Box
style="padding: var(--uix-space-4); border: 1px solid var(--uix-border); border-radius: var(--uix-radius-md); display: flex; flex-wrap: wrap; gap: var(--uix-space-2); align-items: center;" style="padding: var(--uix-space-4); border: 1px solid var(--uix-border); border-radius: var(--uix-radius-md); display: flex; flex-wrap: wrap; gap: var(--uix-space-2); align-items: center;"
> >

@ -5,6 +5,7 @@
type ButtonSize, type ButtonSize,
type ButtonRounded type ButtonRounded
} from '$uix/eidos/components/button'; } from '$uix/eidos/components/button';
import { SHAPE_FAMILIES, type ShapeFamily } from '$uix/eidos/lib/types';
import type { ButtonIntent } from '$soma/components/button'; import type { ButtonIntent } from '$soma/components/button';
import { compileMorfo } from '$uix/morfo'; import { compileMorfo } from '$uix/morfo';
import { buttonMorfo } from '@/uix/morfo/components/button'; import { buttonMorfo } from '@/uix/morfo/components/button';
@ -52,6 +53,7 @@
let variant = $state<ButtonVariant>('solid'); let variant = $state<ButtonVariant>('solid');
let size = $state<ButtonSize>('md'); let size = $state<ButtonSize>('md');
let rounded = $state<ButtonRounded | undefined>(undefined); let rounded = $state<ButtonRounded | undefined>(undefined);
let shape = $state<ShapeFamily>('rounded');
let block = $state(false); let block = $state(false);
let iconOnly = $state(false); let iconOnly = $state(false);
let spinnerPlacement = $state<'start' | 'end'>('start'); let spinnerPlacement = $state<'start' | 'end'>('start');
@ -137,6 +139,7 @@
variant !== 'solid' && ` variant="${variant}"`, variant !== 'solid' && ` variant="${variant}"`,
size !== 'md' && ` size="${size}"`, size !== 'md' && ` size="${size}"`,
rounded && ` rounded="${rounded}"`, rounded && ` rounded="${rounded}"`,
shape !== 'rounded' && ` shape="${shape}"`,
block && ' block', block && ' block',
iconOnly && ' iconOnly', iconOnly && ' iconOnly',
loading && ' loading', loading && ' loading',
@ -201,6 +204,7 @@
{variant} {variant}
{size} {size}
{rounded} {rounded}
{shape}
{block} {block}
{iconOnly} {iconOnly}
{loading} {loading}
@ -358,6 +362,14 @@
{/each} {/each}
</span> </span>
</label> </label>
<label data-uix-control>
<span data-uix-control-label>shape</span>
<span data-uix-chips role="radiogroup">
{#each SHAPE_FAMILIES as sh (sh)}
<button data-uix-chip data-active={shape === sh} onclick={() => (shape = sh)}>{sh}</button>
{/each}
</span>
</label>
<label data-uix-control> <label data-uix-control>
<span data-uix-control-label>block <span data-uix-control-hint>stretch to fill</span></span> <span data-uix-control-label>block <span data-uix-control-hint>stretch to fill</span></span>
<span data-uix-switch> <span data-uix-switch>

@ -6,6 +6,7 @@
type CardVariant, type CardVariant,
type CardRounded type CardRounded
} from '$uix/eidos/components/card'; } from '$uix/eidos/components/card';
import { SHAPE_FAMILIES, type ShapeFamily } from '$uix/eidos/lib/types';
import { Box } from '$uix/eidos/components/box'; import { Box } from '$uix/eidos/components/box';
import { Stack } from '$uix/eidos/components/stack'; import { Stack } from '$uix/eidos/components/stack';
import { Avatar } from '$uix/eidos/components/avatar'; import { Avatar } from '$uix/eidos/components/avatar';
@ -26,6 +27,7 @@
let size = $state<CardSize>('md'); let size = $state<CardSize>('md');
let color = $state<CardColor>('neutral'); let color = $state<CardColor>('neutral');
let rounded = $state<CardRounded>('md'); let rounded = $state<CardRounded>('md');
let shape = $state<ShapeFamily>('rounded');
let interactive = $state(false); let interactive = $state(false);
let selected = $state(false); let selected = $state(false);
let disabled = $state(false); let disabled = $state(false);
@ -111,6 +113,7 @@
size !== 'md' && ` size="${size}"`, size !== 'md' && ` size="${size}"`,
color !== 'neutral' && ` color="${color}"`, color !== 'neutral' && ` color="${color}"`,
rounded !== 'md' && ` rounded="${rounded}"`, rounded !== 'md' && ` rounded="${rounded}"`,
shape !== 'rounded' && ` shape="${shape}"`,
interactive && ' interactive', interactive && ' interactive',
selected && ' selected', selected && ' selected',
disabled && ' disabled', disabled && ' disabled',
@ -180,6 +183,7 @@
{size} {size}
{color} {color}
{rounded} {rounded}
{shape}
{interactive} {interactive}
{selected} {selected}
{disabled} {disabled}
@ -299,6 +303,16 @@
{/each} {/each}
</span> </span>
</label> </label>
<label data-uix-control>
<span data-uix-control-label>shape</span>
<span data-uix-chips role="radiogroup">
{#each SHAPE_FAMILIES as sh (sh)}
<button data-uix-chip data-active={shape === sh} onclick={() => (shape = sh)}
>{sh}</button
>
{/each}
</span>
</label>
<label data-uix-control> <label data-uix-control>
<span data-uix-control-label>interactive</span> <span data-uix-control-label>interactive</span>
<span data-uix-switch> <span data-uix-switch>

@ -5,6 +5,7 @@
type TagsInputSize, type TagsInputSize,
type TagsInputVariant type TagsInputVariant
} from '$uix/eidos/components/tags-input'; } from '$uix/eidos/components/tags-input';
import { SHAPE_FAMILIES, type ShapeFamily } from '$uix/eidos/lib/types';
import { compileMorfo } from '$uix/morfo'; import { compileMorfo } from '$uix/morfo';
import { tagsInputMorfo } from '@/uix/morfo/components/tags-input'; import { tagsInputMorfo } from '@/uix/morfo/components/tags-input';
import type { Intent } from '$uix/intent'; import type { Intent } from '$uix/intent';
@ -32,6 +33,7 @@
let size = $state<TagsInputSize>('md'); let size = $state<TagsInputSize>('md');
let variant = $state<TagsInputVariant>('surface'); let variant = $state<TagsInputVariant>('surface');
let color = $state<TagsInputColor>('primary'); let color = $state<TagsInputColor>('primary');
let tagShape = $state<ShapeFamily>('rounded');
let rejected = $state(''); let rejected = $state('');
type TraceEntry = { event: string; family: string; intent?: string; at: number }; type TraceEntry = { event: string; family: string; intent?: string; at: number };
@ -182,7 +184,7 @@
> >
<TagsInput.Control> <TagsInput.Control>
{#each value as tag, index (tag + index)} {#each value as tag, index (tag + index)}
<TagsInput.Item {index} value={tag}> <TagsInput.Item {index} value={tag} shape={tagShape}>
<TagsInput.ItemText>{tag}</TagsInput.ItemText> <TagsInput.ItemText>{tag}</TagsInput.ItemText>
<TagsInput.ItemDeleteTrigger <TagsInput.ItemDeleteTrigger
data-perm-step={!disabled && !readonly && index === 0 ? '1' : undefined} data-perm-step={!disabled && !readonly && index === 0 ? '1' : undefined}
@ -338,6 +340,16 @@
{/each} {/each}
</span> </span>
</label> </label>
<label data-uix-control>
<span data-uix-control-label>tag shape</span>
<span data-uix-chips role="radiogroup">
{#each SHAPE_FAMILIES as sh (sh)}
<button data-uix-chip data-active={tagShape === sh} onclick={() => (tagShape = sh)}>
{sh}
</button>
{/each}
</span>
</label>
<label data-uix-control> <label data-uix-control>
<span data-uix-control-label>color</span> <span data-uix-control-label>color</span>
<span data-uix-chips role="radiogroup"> <span data-uix-chips role="radiogroup">

Loading…
Cancel
Save

Powered by TurnKey Linux.