Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion docs/reference/block-types.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@ Content and widget blocks support these properties. Sections support `align`
and `flex`, but scrolling is configured on child blocks or widgets.

### `align`
**Type:** String | **Default:** `center`
**Type:** String | **Default:** `centerLeft`

Controls content alignment:
- `topLeft`, `topCenter`, `topRight`
- `centerLeft`, `center`, `centerRight`
- `bottomLeft`, `bottomCenter`, `bottomRight`

Blocks default to `centerLeft` because paragraph-like content reads better
left-aligned. Set `align: center` explicitly for titles or short callouts.

### `flex`
**Type:** Number | **Default:** `1`

Expand Down
2 changes: 1 addition & 1 deletion docs/reference/markdown-syntax.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Built-in widgets (`image`, `dartpad`, `qrcode`) use the same widget syntax as `@
### `align`

- Type: string
- Default: `center`
- Default: `centerLeft`
- Values: `topLeft`, `topCenter`, `topRight`, `centerLeft`, `center`, `centerRight`, `bottomLeft`, `bottomCenter`, `bottomRight`

### `scrollable`
Expand Down
8 changes: 8 additions & 0 deletions packages/core/lib/src/deck/block_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ sealed class Block with BlockMappable {
);

static final fromMap = BlockMapper.fromMap;

/// The effective alignment for this block.
///
/// When [align] is not set explicitly, defaults to
/// [ContentAlignment.centerLeft] because paragraph-like content is easier
/// to read and scan when left-aligned. Set `align: center` explicitly to
/// restore the previous default.
ContentAlignment get resolvedAlign => align ?? ContentAlignment.centerLeft;
}

/// A section that contains multiple child blocks arranged horizontally.
Expand Down
36 changes: 36 additions & 0 deletions packages/core/test/src/deck/block_model_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,24 @@ void main() {
expect(block.scrollable, true);
});

group('resolvedAlign', () {
test('defaults to centerLeft when align is not set', () {
final block = ContentBlock('Content');

expect(block.align, isNull);
expect(block.resolvedAlign, ContentAlignment.centerLeft);
});

test('uses explicit align when set', () {
final block = ContentBlock(
'Content',
align: ContentAlignment.center,
);

expect(block.resolvedAlign, ContentAlignment.center);
});
});

group('copyWith', () {
test('copies with new content', () {
final original = ContentBlock('Original');
Expand Down Expand Up @@ -730,6 +748,24 @@ void main() {
});
});

group('resolvedAlign', () {
test('defaults to centerLeft when align is not set', () {
final widget = WidgetBlock(name: 'Test');

expect(widget.align, isNull);
expect(widget.resolvedAlign, ContentAlignment.centerLeft);
});

test('uses explicit align when set', () {
final widget = WidgetBlock(
name: 'Test',
align: ContentAlignment.topRight,
);

expect(widget.resolvedAlign, ContentAlignment.topRight);
});
});

group('copyWith', () {
test('copies with new name', () {
final original = WidgetBlock(name: 'Original');
Expand Down
4 changes: 2 additions & 2 deletions packages/superdeck/lib/src/builtins/image_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ class ImageWidget extends StatelessWidget {
styleSpec: StyleSpec(
spec: spec.image.spec.copyWith(
fit: _data.fit.toBoxFit,
alignment: alignment?.toAlignment ?? Alignment.center,
alignment: alignment?.toAlignment ?? Alignment.centerLeft,
),
),
);
Expand All @@ -129,7 +129,7 @@ class ImageWidget extends StatelessWidget {
: image;

return Align(
alignment: alignment?.toAlignment ?? Alignment.center,
alignment: alignment?.toAlignment ?? Alignment.centerLeft,
child: constrained,
);
}
Expand Down
4 changes: 2 additions & 2 deletions packages/superdeck/lib/src/rendering/blocks/block_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ class _BlockContainerState extends State<_BlockContainer> {
child: content,
);

// Apply alignment
// Apply alignment, falling back to the block's default when unset.
content = Align(
alignment: widget.block.align?.toAlignment ?? Alignment.center,
alignment: widget.block.resolvedAlign.toAlignment,
child: content,
);

Expand Down
17 changes: 17 additions & 0 deletions packages/superdeck/test/src/rendering/block_widget_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,23 @@ void main() {
tester.expectBlockCount(9);
expect(tester.takeException(), isNull);
});

testWidgets('block without explicit align defaults to centerLeft', (
tester,
) async {
await SlideTestHarness.pumpSlide(
tester,
Slide(
key: 'default-align',
sections: [
SectionBlock([ContentBlock('# No explicit align')]),
],
),
);

final align = tester.widget<Align>(find.byType(Align).first);
expect(align.alignment, Alignment.centerLeft);
});
});

group('scrollable behavior', () {
Expand Down
Loading