Skip to content

Commit e544a1d

Browse files
author
gjulivan
committed
chore: allow list indent
1 parent 2be7e37 commit e544a1d

60 files changed

Lines changed: 4843 additions & 95 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
schema: spec-driven
2+
created: 2026-07-12
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
## Context
2+
3+
Rich text widget renders ordered (`<ol>`) and unordered (`<ul>`) lists using Tiptap's StarterKit extensions. Current SCSS (`RichText.scss` lines 158-162) only sets basic padding and margin:
4+
5+
```scss
6+
ul,
7+
ol {
8+
padding-left: 1.5em;
9+
margin: 0.5em 0;
10+
}
11+
```
12+
13+
All nesting levels use browser defaults:
14+
15+
- Ordered lists: `list-style-type: decimal` (1, 2, 3) at all levels
16+
- Unordered lists: `list-style-type: disc` (●) at all levels
17+
18+
Standard word processors (Word, Google Docs, Notion) auto-cycle list styles by depth for visual hierarchy. Users coming from these tools expect similar behavior.
19+
20+
Recent change `fix-list-tab-indent` added Tab key support for nesting lists, making this enhancement more valuable.
21+
22+
## Goals / Non-Goals
23+
24+
**Goals:**
25+
26+
- Auto-cycle ordered list styles: decimal → lower-alpha → lower-roman (repeat)
27+
- Auto-cycle unordered list styles: disc → circle → square (repeat)
28+
- CSS-only implementation (zero JavaScript)
29+
- Preserve inline style overrides (user-set `style="list-style-type: ..."`)
30+
- Support 6+ nesting levels
31+
32+
**Non-Goals:**
33+
34+
- User controls for changing list style (Phase 2 scope)
35+
- Toolbar UI changes
36+
- Extending Tiptap list extensions
37+
- Data model changes (no new attributes)
38+
- RTL-specific list markers
39+
40+
## Decisions
41+
42+
### Decision 1: Pure CSS nested selectors
43+
44+
**Choice**: Use CSS descendant combinators (`ol ol { ... }`) to target nested lists.
45+
46+
**Rationale**:
47+
48+
- Zero JavaScript overhead
49+
- Standard CSS, widely supported
50+
- Works immediately with existing HTML structure
51+
- No Tiptap extension modifications needed
52+
- Inline styles naturally override via CSS specificity
53+
54+
**Alternatives considered**:
55+
56+
- Data attributes (`data-list-level="2"`) → Requires Tiptap extension to inject attributes, adds complexity
57+
- JavaScript depth calculation → Performance overhead, unnecessary for static styling
58+
- CSS `:nth-child()` or counters → Incorrect semantic (targets item position, not nesting depth)
59+
60+
### Decision 2: Cycle sequence matches Word
61+
62+
**Choice**:
63+
64+
- Ordered: decimal (1, 2, 3) → lower-alpha (a, b, c) → lower-roman (i, ii, iii)
65+
- Unordered: disc (●) → circle (○) → square (■)
66+
67+
**Rationale**:
68+
69+
- Industry standard (Microsoft Word, Google Docs use same sequence)
70+
- User familiarity reduces cognitive load
71+
- Lower-case styles preferred for nested content (less visual weight than uppercase)
72+
73+
**Alternatives considered**:
74+
75+
- Upper-case roman/alpha at level 1 → Too visually heavy for running text
76+
- Custom sequence → No benefit, breaks user expectations
77+
78+
### Decision 3: Define 6 nesting levels explicitly
79+
80+
**Choice**: Write CSS rules for 6 levels of nesting (2 full cycles).
81+
82+
**Rationale**:
83+
84+
- Covers 95%+ of real-world use cases
85+
- Cost is ~30 lines of CSS (cheap)
86+
- Deeper nesting (7+) falls back to browser defaults (acceptable edge case)
87+
88+
**Alternatives considered**:
89+
90+
- 3 levels only → Breaks at 4th level (incomplete cycle)
91+
- 9 levels → Unnecessary (deeply nested lists are rare, unreadable)
92+
- Infinite via preprocessor loops → Adds build complexity for marginal gain
93+
94+
### Decision 4: Preserve inline style precedence
95+
96+
**Choice**: CSS specificity naturally prioritizes inline styles. No `!important` needed for base rules.
97+
98+
**Rationale**:
99+
100+
- Users who manually set `style="list-style-type: upper-roman;"` keep their choice
101+
- Supports future Phase 2 (user overrides via toolbar)
102+
- Standard CSS behavior, no surprises
103+
104+
**CSS specificity**:
105+
106+
- Inline style: 1000 points (highest)
107+
- `ol ol ol`: 3 points
108+
- Inline wins automatically
109+
110+
## Risks / Trade-offs
111+
112+
**[Risk]** Users with existing nested lists see visual change after upgrade → **Mitigation**: Document in CHANGELOG as enhancement. Not breaking (only affects appearance, not functionality).
113+
114+
**[Risk]** Deeply nested lists (7+ levels) don't cycle correctly → **Mitigation**: Define extra levels if needed (cheap). Fallback to browser default (decimal/disc) is acceptable.
115+
116+
**[Risk]** User expectations from non-Word apps → **Mitigation**: Word/Google Docs are dominant, setting de facto standard. Other tools vary, but decimal→alpha→roman is most common.
117+
118+
**[Trade-off]** No per-list customization in Phase 1 → Accepted. Phase 2 adds toolbar controls for manual override.
119+
120+
**[Trade-off]** CSS file size increases ~40 lines → Negligible (gzipped impact <0.5KB).
121+
122+
## Implementation
123+
124+
**File modified**: `packages/pluggableWidgets/rich-text-web/src/ui/RichText.scss`
125+
126+
**Change location**: Lines 158-162 (existing `ul, ol` rules)
127+
128+
**Strategy**: Replace simple `ul, ol` selector with nested rules:
129+
130+
```scss
131+
// Ordered list auto-cycling (6 levels = 2 full cycles)
132+
ol {
133+
list-style-type: decimal;
134+
ol {
135+
list-style-type: lower-alpha;
136+
ol {
137+
list-style-type: lower-roman;
138+
ol {
139+
list-style-type: decimal; // Cycle repeats
140+
ol {
141+
list-style-type: lower-alpha;
142+
ol {
143+
list-style-type: lower-roman;
144+
}
145+
}
146+
}
147+
}
148+
}
149+
}
150+
151+
// Unordered list auto-cycling (6 levels = 2 full cycles)
152+
ul {
153+
list-style-type: disc;
154+
ul {
155+
list-style-type: circle;
156+
ul {
157+
list-style-type: square;
158+
ul {
159+
list-style-type: disc; // Cycle repeats
160+
ul {
161+
list-style-type: circle;
162+
ul {
163+
list-style-type: square;
164+
}
165+
}
166+
}
167+
}
168+
}
169+
}
170+
```
171+
172+
Keep existing padding/margin rules intact.
173+
174+
## Open Questions
175+
176+
None. Design is complete and straightforward.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
## Why
2+
3+
Nested lists in rich text widget currently use same numbering style at all levels (1, 2, 3 everywhere). Standard word processors (Word, Google Docs) automatically cycle through different styles for visual hierarchy (decimal → lower-alpha → lower-roman). This improves readability of complex nested lists.
4+
5+
## What Changes
6+
7+
- Ordered lists (`<ol>`) will auto-cycle numbering styles based on nesting depth:
8+
- Level 1: decimal (1, 2, 3)
9+
- Level 2: lower-alpha (a, b, c)
10+
- Level 3: lower-roman (i, ii, iii)
11+
- Level 4+: cycle repeats (decimal → lower-alpha → lower-roman)
12+
- Unordered lists (`<ul>`) will auto-cycle bullet styles based on nesting depth:
13+
- Level 1: disc (●)
14+
- Level 2: circle (○)
15+
- Level 3: square (■)
16+
- Level 4+: cycle repeats (disc → circle → square)
17+
- CSS-only implementation (no JavaScript changes)
18+
- No toolbar changes or user override controls (Phase 1 scope)
19+
20+
## Capabilities
21+
22+
### New Capabilities
23+
24+
- `list-style-auto-cycle`: Nested ordered and unordered lists automatically cycle through numbering/bullet styles based on depth
25+
26+
### Modified Capabilities
27+
28+
<!-- No existing spec requirements changing - this is pure visual enhancement -->
29+
30+
## Impact
31+
32+
**Files affected**:
33+
34+
- `packages/pluggableWidgets/rich-text-web/src/ui/RichText.scss` — Add nested selector rules for `ol` and `ul`
35+
36+
**User-facing changes**:
37+
38+
- Nested lists will display different numbering/bullet styles automatically
39+
- Matches standard word processor behavior
40+
- Existing lists with manual `style="list-style-type: ..."` inline styles unchanged (inline styles override CSS)
41+
- No breaking changes — pure visual enhancement
42+
43+
**Testing scope**:
44+
45+
- Visual verification of 6 nesting levels for ordered lists
46+
- Visual verification of 4 nesting levels for unordered lists
47+
- Mixed list types (ordered inside unordered, vice versa)
48+
- Task lists (`ul[data-type="taskList"]`) should remain unaffected
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
## ADDED Requirements
2+
3+
### Requirement: Ordered lists cycle through numbering styles by nesting depth
4+
5+
Ordered lists (`<ol>`) SHALL automatically cycle through numbering styles based on nesting level using CSS descendant selectors.
6+
7+
#### Scenario: Level 1 ordered list uses decimal
8+
9+
- **WHEN** an ordered list is at the top level (not nested)
10+
- **THEN** list items display with decimal numbering (1, 2, 3)
11+
12+
#### Scenario: Level 2 ordered list uses lower-alpha
13+
14+
- **WHEN** an ordered list is nested one level deep inside another ordered list
15+
- **THEN** list items display with lower-alpha numbering (a, b, c)
16+
17+
#### Scenario: Level 3 ordered list uses lower-roman
18+
19+
- **WHEN** an ordered list is nested two levels deep
20+
- **THEN** list items display with lower-roman numbering (i, ii, iii)
21+
22+
#### Scenario: Level 4 ordered list cycles back to decimal
23+
24+
- **WHEN** an ordered list is nested three levels deep
25+
- **THEN** list items display with decimal numbering (1, 2, 3)
26+
27+
#### Scenario: Level 5 ordered list cycles to lower-alpha
28+
29+
- **WHEN** an ordered list is nested four levels deep
30+
- **THEN** list items display with lower-alpha numbering (a, b, c)
31+
32+
#### Scenario: Level 6 ordered list cycles to lower-roman
33+
34+
- **WHEN** an ordered list is nested five levels deep
35+
- **THEN** list items display with lower-roman numbering (i, ii, iii)
36+
37+
### Requirement: Unordered lists cycle through bullet styles by nesting depth
38+
39+
Unordered lists (`<ul>`) SHALL automatically cycle through bullet styles based on nesting level using CSS descendant selectors.
40+
41+
#### Scenario: Level 1 unordered list uses disc
42+
43+
- **WHEN** an unordered list is at the top level (not nested)
44+
- **THEN** list items display with disc bullets (●)
45+
46+
#### Scenario: Level 2 unordered list uses circle
47+
48+
- **WHEN** an unordered list is nested one level deep inside another unordered list
49+
- **THEN** list items display with circle bullets (○)
50+
51+
#### Scenario: Level 3 unordered list uses square
52+
53+
- **WHEN** an unordered list is nested two levels deep
54+
- **THEN** list items display with square bullets (■)
55+
56+
#### Scenario: Level 4 unordered list cycles back to disc
57+
58+
- **WHEN** an unordered list is nested three levels deep
59+
- **THEN** list items display with disc bullets (●)
60+
61+
### Requirement: Inline styles override CSS defaults
62+
63+
When a list element has an inline `style="list-style-type: ..."` attribute, that style SHALL take precedence over CSS auto-cycle rules.
64+
65+
#### Scenario: Manually styled list preserves inline style
66+
67+
- **WHEN** an ordered list has `style="list-style-type: upper-roman;"`
68+
- **THEN** list displays with upper-roman (I, II, III) regardless of nesting depth
69+
70+
#### Scenario: Nested list without inline style uses auto-cycle
71+
72+
- **WHEN** parent list has inline style but nested child list has no inline style
73+
- **THEN** child list uses CSS auto-cycle rules based on its depth
74+
75+
### Requirement: Task lists remain unstyled
76+
77+
Task lists with `data-type="taskList"` SHALL remain unstyled with `list-style: none`, unaffected by auto-cycle rules.
78+
79+
#### Scenario: Task list ignores auto-cycle
80+
81+
- **WHEN** a list has `data-type="taskList"` attribute
82+
- **THEN** list displays with no bullet/number markers (checkboxes only)
83+
84+
### Requirement: Mixed list types cycle independently
85+
86+
When ordered and unordered lists are mixed (e.g., `<ul>` inside `<ol>`), each list type SHALL follow its own cycle sequence.
87+
88+
#### Scenario: Ordered list inside unordered list starts at decimal
89+
90+
- **WHEN** an `<ol>` is nested inside a `<ul>`
91+
- **THEN** ordered list uses decimal (1, 2, 3) regardless of parent's depth
92+
93+
#### Scenario: Unordered list inside ordered list starts at disc
94+
95+
- **WHEN** a `<ul>` is nested inside an `<ol>`
96+
- **THEN** unordered list uses disc (●) regardless of parent's depth
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
## 1. Update SCSS for list style cycling
2+
3+
- [x] 1.1 Add nested selector rules for ordered lists (ol) with 6 levels: decimal → lower-alpha → lower-roman → decimal → lower-alpha → lower-roman
4+
- [x] 1.2 Add nested selector rules for unordered lists (ul) with 6 levels: disc → circle → square → disc → circle → square
5+
- [x] 1.3 Preserve existing padding-left and margin rules for ul/ol
6+
7+
## 2. Manual testing
8+
9+
- [x] 2.1 Test ordered list nesting: verify 6 levels show correct cycle (1 → a → i → 1 → a → i)
10+
- [x] 2.2 Test unordered list nesting: verify 4 levels show correct cycle (● → ○ → ■ → ●)
11+
- [x] 2.3 Test mixed list types: ordered inside unordered starts at decimal, unordered inside ordered starts at disc
12+
- [x] 2.4 Test inline style override: list with style="list-style-type: upper-roman;" displays upper-roman at any depth
13+
- [x] 2.5 Test task lists remain unaffected: ul[data-type="taskList"] shows no bullets/numbers
14+
15+
## 3. Documentation
16+
17+
- [x] 3.1 Add entry to CHANGELOG.md describing auto-cycle enhancement
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
schema: spec-driven
2+
created: 2026-07-10

0 commit comments

Comments
 (0)