mirror of
https://github.com/nexu-io/open-design.git
synced 2026-10-27 09:51:12 +01:00
reorder web home creation type priorities (#6892)
* fix web home media pill placement * swap UI Mockup and Slide deck positions
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
// Capsule type row — the pill replacement for the fanned type carousel
|
||||
// (per product: 12 个创作类型全部换成胶囊形). ONE line exactly as wide as the
|
||||
// (per product: all 12 creation types use capsules). ONE line exactly as wide as the
|
||||
// composer card below it, EVERY gap identical (8px): the pills that fit
|
||||
// render inline, then the pinned 视频 pill, then the 全部 button, and the
|
||||
// render inline, then the pinned Image pill, then the All button, and the
|
||||
// rest fold into the 全部 popover. Fit is computed against an invisible
|
||||
// probe row that always lays out the full set at natural size, so showing /
|
||||
// hiding pills can never feed back into its own measurement. Selection
|
||||
@@ -15,10 +15,10 @@ import { useT } from '../../i18n';
|
||||
// today, so this only guards against future catalog growth widening the row.
|
||||
const MAX_PILLS = 12;
|
||||
|
||||
// Pills pinned just BEFORE the 全部 trigger (per product: 视频 stays visible
|
||||
// Pills pinned just BEFORE the All trigger (per product: Image stays visible
|
||||
// in the row, never folded into the popover). Pinned pills sit outside the
|
||||
// fit computation's flowing run, so they survive any window width.
|
||||
const PINNED_PILL_IDS: readonly string[] = ['video'];
|
||||
const PINNED_PILL_IDS: readonly string[] = ['image'];
|
||||
|
||||
// Must match .home-hero__type-pills-wrap's CSS gap.
|
||||
const PILL_GAP = 8;
|
||||
|
||||
@@ -381,19 +381,18 @@ export function chipsForGroup(group: ChipGroup): HomeHeroChip[] {
|
||||
}
|
||||
|
||||
// Display order for the inline `create` scenario rail. The composer leads with
|
||||
// Website clone (the fastest "paste a URL, get a site" on-ramp), then the slide
|
||||
// deck ("Slides") and the core build scenarios in decreasing generality
|
||||
// (Prototype → Wireframe → Mobile → Document → Animation), then the media
|
||||
// UI Mockup, followed by Slide deck and the remaining core build scenarios
|
||||
// (Wireframe → Mobile → Document → Animation), then the media
|
||||
// scenarios. Brand Kit is intentionally omitted here so it trails the scenario
|
||||
// set — it dispatches into the Brand Kit tab rather than seeding a scenario
|
||||
// plugin. Any create chip not listed keeps its catalog order after the explicit
|
||||
// entries (see `orderedCreateChips`).
|
||||
export const CREATE_RAIL_ORDER = [
|
||||
// Slide deck leads (per product: 幻灯片 is the row's first, default-selected
|
||||
// type); Website clone trails the whole list so at typical widths it lives
|
||||
// in the 全部 overflow popover rather than the visible pill row.
|
||||
'deck',
|
||||
// UI Mockup leads and Slide deck follows. Website clone trails the whole list
|
||||
// so at typical widths it lives in the All overflow popover rather than the
|
||||
// visible pill row.
|
||||
'prototype',
|
||||
'deck',
|
||||
'wireframe',
|
||||
'mobile',
|
||||
'document',
|
||||
@@ -425,7 +424,7 @@ export const ONBOARDING_ARTIFACT_CHIP_IDS = CREATE_RAIL_ORDER.filter(
|
||||
// The `create` chips in rail-display order. Listed ids come first in
|
||||
// `CREATE_RAIL_ORDER`; any unlisted create chip (e.g. `create-brand-kit`)
|
||||
// trails in catalog order. Reordering through this helper keeps the catalog
|
||||
// data table stable while letting the rail lead with the slide deck.
|
||||
// data table stable while letting the rail lead with UI Mockup.
|
||||
export function orderedCreateChips(): HomeHeroChip[] {
|
||||
const create = chipsForGroup('create');
|
||||
const listed = CREATE_RAIL_ORDER
|
||||
|
||||
@@ -88,10 +88,10 @@ describe('HomeHero scenario cards', () => {
|
||||
).toContain('Slide deck');
|
||||
});
|
||||
|
||||
it('leads the create rail with the slide deck and trails Website clone', () => {
|
||||
it('leads the create rail with UI Mockup, then Slide deck, and trails Website clone', () => {
|
||||
const ordered = orderedCreateChips();
|
||||
const ids = ordered.map((chip) => chip.id);
|
||||
expect(ids[0]).toBe('deck');
|
||||
expect(ids.slice(0, 2)).toEqual(['prototype', 'deck']);
|
||||
// Website clone sits behind every other explicit rail type (only the
|
||||
// unlisted catalog tail, e.g. Brand Kit, follows), so the visible pill
|
||||
// row overflows it into the 全部 popover at typical widths.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// @vitest-environment jsdom
|
||||
|
||||
import { act, cleanup, render, screen } from '@testing-library/react';
|
||||
import { act, cleanup, fireEvent, render, screen } from '@testing-library/react';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { TypePillRow } from '../../../src/components/home-hero/TypePillRow';
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
type HomeHeroChip,
|
||||
} from '../../../src/components/home-hero/chips';
|
||||
|
||||
const chips = ['deck', 'prototype', 'wireframe', 'video'].map((chipId) => {
|
||||
const chips = ['deck', 'prototype', 'wireframe', 'image', 'video'].map((chipId) => {
|
||||
const chip = HOME_HERO_CHIPS.find((candidate) => candidate.id === chipId);
|
||||
if (!chip) throw new Error(`Missing chip fixture: ${chipId}`);
|
||||
return chip;
|
||||
@@ -62,6 +62,17 @@ function renderPillRow(labelFor: (chipId: string) => string) {
|
||||
}
|
||||
|
||||
describe('TypePillRow', () => {
|
||||
it('keeps Image inline and moves Video into All when the row overflows', () => {
|
||||
renderPillRow((chipId) => chipId);
|
||||
|
||||
expect(screen.queryByTestId('home-hero-type-pill-image')).not.toBeNull();
|
||||
expect(screen.queryByTestId('home-hero-type-pill-video')).toBeNull();
|
||||
|
||||
fireEvent.click(screen.getByTestId('home-hero-type-pills-more'));
|
||||
expect(screen.queryByTestId('home-hero-type-pill-video-more')).not.toBeNull();
|
||||
expect(screen.queryByTestId('home-hero-type-pill-image-more')).toBeNull();
|
||||
});
|
||||
|
||||
it('recomputes the inline split when rendered labels change without resizing the container', () => {
|
||||
const labels = new Map(chips.map((chip) => [chip.id, chip.label]));
|
||||
const view = renderPillRow((chipId) => labels.get(chipId) ?? chipId);
|
||||
|
||||
Reference in New Issue
Block a user