mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-16 10:01:59 +08:00
feat(css): add new css utility classes for display and flex utils (#30567)
Issue number: resolves #22469 --------- - Adds new responsive display classes with the following values: `none`, `inline`, `inline-block`, `block`, `flex`, `inline-flex`, `grid`, `inline-grid`, `table`, `table-cell`, `table-row` - Adds new responsive flex util classes for the following properties: `align-content`, `align-items`, `align-self`, `justify-content`, `flex-direction`, `flex-wrap`, `flex`, `flex-grow` , `flex-shrink`, `order` - Adds e2e tests to verify the correct classes are in the CSS files --------- Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
This commit is contained in:

committed by
Brandy Smith

parent
d5627c7368
commit
75f6c05fb9
@ -125,7 +125,7 @@
|
|||||||
|
|
||||||
<ion-toolbar color="dark">
|
<ion-toolbar color="dark">
|
||||||
<ion-buttons slot="start">
|
<ion-buttons slot="start">
|
||||||
<ion-back-button class="ion-hide"></ion-back-button>
|
<ion-back-button class="ion-display-none"></ion-back-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
<ion-title>Hidden</ion-title>
|
<ion-title>Hidden</ion-title>
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
|
@ -107,6 +107,7 @@ const renderProgress = (value: number, buffer: number) => {
|
|||||||
* When finalBuffer === 1, we use display: none
|
* When finalBuffer === 1, we use display: none
|
||||||
* instead of removing the element to avoid flickering.
|
* instead of removing the element to avoid flickering.
|
||||||
*/
|
*/
|
||||||
|
// TODO(FW-6697): change `ion-hide` class to `ion-display-none` or another class
|
||||||
<div
|
<div
|
||||||
class={{ 'buffer-circles-container': true, 'ion-hide': finalBuffer === 1 }}
|
class={{ 'buffer-circles-container': true, 'ion-hide': finalBuffer === 1 }}
|
||||||
style={{ transform: `translateX(${finalBuffer * 100}%)` }}
|
style={{ transform: `translateX(${finalBuffer * 100}%)` }}
|
||||||
|
@ -2,9 +2,14 @@
|
|||||||
@import "../themes/ionic.mixins";
|
@import "../themes/ionic.mixins";
|
||||||
|
|
||||||
// Display
|
// Display
|
||||||
// --------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// Modifies display of a particular element based on the given classes
|
// Provides utility classes to control the CSS display property
|
||||||
|
// of elements. Includes responsive variants for toggling between
|
||||||
|
// block, inline, flex, grid, and other display values at different
|
||||||
|
// breakpoints.
|
||||||
|
|
||||||
|
// TODO(FW-6697): remove ion-hide-* classes in favor of the new
|
||||||
|
// ion-display-* classes
|
||||||
.ion-hide {
|
.ion-hide {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
@ -29,3 +34,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$display-values: (
|
||||||
|
none,
|
||||||
|
inline,
|
||||||
|
inline-block,
|
||||||
|
block,
|
||||||
|
flex,
|
||||||
|
inline-flex,
|
||||||
|
grid,
|
||||||
|
inline-grid,
|
||||||
|
table,
|
||||||
|
table-cell,
|
||||||
|
table-row
|
||||||
|
);
|
||||||
|
|
||||||
|
@each $display in $display-values {
|
||||||
|
@each $breakpoint in map-keys($screen-breakpoints) {
|
||||||
|
$infix: breakpoint-infix($breakpoint, $screen-breakpoints);
|
||||||
|
|
||||||
|
@include media-breakpoint-up($breakpoint, $screen-breakpoints) {
|
||||||
|
.ion-display#{$infix}-#{$display} {
|
||||||
|
display: #{$display} !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,99 +1,211 @@
|
|||||||
|
@import "../themes/ionic.globals";
|
||||||
|
@import "../themes/ionic.mixins";
|
||||||
|
|
||||||
// Flex Utilities
|
// Flex Utilities
|
||||||
// --------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// Creates flex classes to align flex containers
|
// Provides utility classes to control flexbox layout, alignment,
|
||||||
// and items
|
// and sizing of elements. Includes responsive variants for managing
|
||||||
|
// flex direction, alignment, justification, wrapping, growth,
|
||||||
|
// shrinking, and ordering at different breakpoints.
|
||||||
|
|
||||||
// Align Self
|
// Align Content
|
||||||
// --------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
.ion-align-self-start {
|
$align-content-values: (
|
||||||
align-self: flex-start !important;
|
start: flex-start,
|
||||||
|
end: flex-end,
|
||||||
|
center: center,
|
||||||
|
between: space-between,
|
||||||
|
around: space-around,
|
||||||
|
stretch: stretch
|
||||||
|
);
|
||||||
|
|
||||||
|
@each $breakpoint in map-keys($screen-breakpoints) {
|
||||||
|
$infix: breakpoint-infix($breakpoint, $screen-breakpoints);
|
||||||
|
@include media-breakpoint-up($breakpoint, $screen-breakpoints) {
|
||||||
|
@each $key, $value in $align-content-values {
|
||||||
|
.ion-align-content#{$infix}-#{$key} {
|
||||||
|
align-content: #{$value} !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ion-align-self-end {
|
|
||||||
align-self: flex-end !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.ion-align-self-center {
|
|
||||||
align-self: center !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.ion-align-self-stretch {
|
|
||||||
align-self: stretch !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.ion-align-self-baseline {
|
|
||||||
align-self: baseline !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ion-align-self-auto {
|
|
||||||
align-self: auto !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Flex Wrap
|
|
||||||
// --------------------------------------------------
|
|
||||||
|
|
||||||
.ion-wrap {
|
|
||||||
flex-wrap: wrap !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ion-nowrap {
|
|
||||||
flex-wrap: nowrap !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ion-wrap-reverse {
|
|
||||||
flex-wrap: wrap-reverse !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Justify Content
|
|
||||||
// --------------------------------------------------
|
|
||||||
|
|
||||||
.ion-justify-content-start {
|
|
||||||
justify-content: flex-start !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ion-justify-content-center {
|
|
||||||
justify-content: center !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ion-justify-content-end {
|
|
||||||
justify-content: flex-end !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ion-justify-content-around {
|
|
||||||
justify-content: space-around !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ion-justify-content-between {
|
|
||||||
justify-content: space-between !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ion-justify-content-evenly {
|
|
||||||
justify-content: space-evenly !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Align Items
|
// Align Items
|
||||||
// --------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
.ion-align-items-start {
|
$align-items-values: (
|
||||||
align-items: flex-start !important;
|
start,
|
||||||
|
end,
|
||||||
|
center,
|
||||||
|
stretch,
|
||||||
|
baseline
|
||||||
|
);
|
||||||
|
|
||||||
|
@each $breakpoint in map-keys($screen-breakpoints) {
|
||||||
|
$infix: breakpoint-infix($breakpoint, $screen-breakpoints);
|
||||||
|
@include media-breakpoint-up($breakpoint, $screen-breakpoints) {
|
||||||
|
@each $value in $align-items-values {
|
||||||
|
.ion-align-items#{$infix}-#{$value} {
|
||||||
|
align-items: #{$value} !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ion-align-items-center {
|
// Align Self
|
||||||
align-items: center !important;
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
|
$align-self-values: (
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
center,
|
||||||
|
stretch,
|
||||||
|
baseline,
|
||||||
|
auto
|
||||||
|
);
|
||||||
|
|
||||||
|
@each $breakpoint in map-keys($screen-breakpoints) {
|
||||||
|
$infix: breakpoint-infix($breakpoint, $screen-breakpoints);
|
||||||
|
@include media-breakpoint-up($breakpoint, $screen-breakpoints) {
|
||||||
|
@each $value in $align-self-values {
|
||||||
|
.ion-align-self#{$infix}-#{$value} {
|
||||||
|
align-self: #{$value} !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ion-align-items-end {
|
// Justify Content
|
||||||
align-items: flex-end !important;
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
|
$justify-content-values: (
|
||||||
|
start: flex-start,
|
||||||
|
end: flex-end,
|
||||||
|
center: center,
|
||||||
|
between: space-between,
|
||||||
|
around: space-around,
|
||||||
|
evenly: space-evenly
|
||||||
|
);
|
||||||
|
|
||||||
|
@each $breakpoint in map-keys($screen-breakpoints) {
|
||||||
|
$infix: breakpoint-infix($breakpoint, $screen-breakpoints);
|
||||||
|
@include media-breakpoint-up($breakpoint, $screen-breakpoints) {
|
||||||
|
@each $key, $value in $justify-content-values {
|
||||||
|
.ion-justify-content#{$infix}-#{$key} {
|
||||||
|
justify-content: #{$value} !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ion-align-items-stretch {
|
// Flex Direction
|
||||||
align-items: stretch !important;
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
|
$flex-direction-values: (
|
||||||
|
row,
|
||||||
|
row-reverse,
|
||||||
|
column,
|
||||||
|
column-reverse
|
||||||
|
);
|
||||||
|
|
||||||
|
@each $breakpoint in map-keys($screen-breakpoints) {
|
||||||
|
$infix: breakpoint-infix($breakpoint, $screen-breakpoints);
|
||||||
|
@include media-breakpoint-up($breakpoint, $screen-breakpoints) {
|
||||||
|
@each $value in $flex-direction-values {
|
||||||
|
.ion-flex#{$infix}-#{$value} {
|
||||||
|
flex-direction: #{$value} !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ion-align-items-baseline {
|
// Flex Wrap
|
||||||
align-items: baseline !important;
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
|
$flex-wrap-values: (
|
||||||
|
wrap,
|
||||||
|
nowrap,
|
||||||
|
wrap-reverse
|
||||||
|
);
|
||||||
|
|
||||||
|
@each $value in $flex-wrap-values {
|
||||||
|
// TODO(FW-6697): remove ion-wrap, ion-nowrap, ion-wrap-reverse
|
||||||
|
// in favor of the new ion-flex-wrap, ion-flex-nowrap, and
|
||||||
|
// ion-flex-wrap-reverse classes
|
||||||
|
.ion-#{$value} {
|
||||||
|
flex-wrap: #{$value} !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@each $breakpoint in map-keys($screen-breakpoints) {
|
||||||
|
$infix: breakpoint-infix($breakpoint, $screen-breakpoints);
|
||||||
|
@include media-breakpoint-up($breakpoint, $screen-breakpoints) {
|
||||||
|
@each $value in $flex-wrap-values {
|
||||||
|
.ion-flex#{$infix}-#{$value} {
|
||||||
|
flex-wrap: #{$value} !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flex Fill
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
|
$flex-fill-values: (
|
||||||
|
1,
|
||||||
|
auto,
|
||||||
|
initial,
|
||||||
|
none
|
||||||
|
);
|
||||||
|
|
||||||
|
@each $breakpoint in map-keys($screen-breakpoints) {
|
||||||
|
$infix: breakpoint-infix($breakpoint, $screen-breakpoints);
|
||||||
|
@include media-breakpoint-up($breakpoint, $screen-breakpoints) {
|
||||||
|
@each $value in $flex-fill-values {
|
||||||
|
.ion-flex#{$infix}-#{$value} {
|
||||||
|
flex: #{$value} !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flex Grow and Shrink
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
|
@each $breakpoint in map-keys($screen-breakpoints) {
|
||||||
|
$infix: breakpoint-infix($breakpoint, $screen-breakpoints);
|
||||||
|
@include media-breakpoint-up($breakpoint, $screen-breakpoints) {
|
||||||
|
.ion-flex#{$infix}-grow-0 {
|
||||||
|
flex-grow: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ion-flex#{$infix}-grow-1 {
|
||||||
|
flex-grow: 1 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ion-flex#{$infix}-shrink-0 {
|
||||||
|
flex-shrink: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ion-flex#{$infix}-shrink-1 {
|
||||||
|
flex-shrink: 1 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flex Order
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
|
@each $breakpoint in map-keys($screen-breakpoints) {
|
||||||
|
$infix: breakpoint-infix($breakpoint, $screen-breakpoints);
|
||||||
|
@include media-breakpoint-up($breakpoint, $screen-breakpoints) {
|
||||||
|
.ion-order#{$infix}-first { order: -1 !important; }
|
||||||
|
|
||||||
|
@for $i from 0 through 12 {
|
||||||
|
.ion-order#{$infix}-#{$i} { order: #{$i} !important; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.ion-order#{$infix}-last { order: 13 !important; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
48
core/src/css/test/display.e2e.ts
Normal file
48
core/src/css/test/display.e2e.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
|
||||||
|
test.describe('display css utility classes', () => {
|
||||||
|
let css: string;
|
||||||
|
|
||||||
|
test.beforeAll(() => {
|
||||||
|
css = fs.readFileSync(path.resolve(__dirname, '../../../css/display.css'), 'utf8');
|
||||||
|
});
|
||||||
|
|
||||||
|
const INFIXES = ['', '-sm', '-md', '-lg', '-xl'];
|
||||||
|
|
||||||
|
// TODO(FW-6697): remove `ion-hide classes` test
|
||||||
|
test('ion-hide classes', () => {
|
||||||
|
expect(css).toContain('.ion-hide');
|
||||||
|
|
||||||
|
const values = ['up', 'down'];
|
||||||
|
|
||||||
|
for (const value of values) {
|
||||||
|
for (const infix of INFIXES) {
|
||||||
|
expect(css).toContain(`.ion-hide${infix}-${value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('ion-display classes', () => {
|
||||||
|
const values = [
|
||||||
|
'none',
|
||||||
|
'inline',
|
||||||
|
'inline-block',
|
||||||
|
'block',
|
||||||
|
'flex',
|
||||||
|
'inline-flex',
|
||||||
|
'grid',
|
||||||
|
'inline-grid',
|
||||||
|
'table',
|
||||||
|
'table-cell',
|
||||||
|
'table-row',
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const value of values) {
|
||||||
|
for (const infix of INFIXES) {
|
||||||
|
expect(css).toContain(`.ion-display${infix}-${value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
100
core/src/css/test/flex-utils.e2e.ts
Normal file
100
core/src/css/test/flex-utils.e2e.ts
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
|
||||||
|
test.describe('flex-utils css utility classes', () => {
|
||||||
|
let css: string;
|
||||||
|
|
||||||
|
test.beforeAll(() => {
|
||||||
|
css = fs.readFileSync(path.resolve(__dirname, '../../../css/flex-utils.css'), 'utf8');
|
||||||
|
});
|
||||||
|
|
||||||
|
const INFIXES = ['', '-sm', '-md', '-lg', '-xl'];
|
||||||
|
|
||||||
|
test('align-content classes', () => {
|
||||||
|
const values = ['start', 'end', 'center', 'between', 'around', 'stretch'];
|
||||||
|
for (const value of values) {
|
||||||
|
for (const infix of INFIXES) {
|
||||||
|
expect(css).toContain(`.ion-align-content${infix}-${value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('align-items classes', () => {
|
||||||
|
const values = ['start', 'center', 'end', 'stretch', 'baseline'];
|
||||||
|
for (const value of values) {
|
||||||
|
for (const infix of INFIXES) {
|
||||||
|
expect(css).toContain(`.ion-align-items${infix}-${value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('align-self classes', () => {
|
||||||
|
const values = ['start', 'end', 'center', 'stretch', 'baseline', 'auto'];
|
||||||
|
for (const value of values) {
|
||||||
|
for (const infix of INFIXES) {
|
||||||
|
expect(css).toContain(`.ion-align-self${infix}-${value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('justify-content classes', () => {
|
||||||
|
const values = ['start', 'center', 'end', 'around', 'between', 'evenly'];
|
||||||
|
for (const value of values) {
|
||||||
|
for (const infix of INFIXES) {
|
||||||
|
expect(css).toContain(`.ion-justify-content${infix}-${value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('flex-direction classes', () => {
|
||||||
|
const values = ['row', 'row-reverse', 'column', 'column-reverse'];
|
||||||
|
for (const value of values) {
|
||||||
|
for (const infix of INFIXES) {
|
||||||
|
expect(css).toContain(`.ion-flex${infix}-${value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('flex-wrap classes', () => {
|
||||||
|
const values = ['wrap', 'nowrap', 'wrap-reverse'];
|
||||||
|
// TODO(FW-6697): remove all `ion-wrap-*` expects
|
||||||
|
for (const value of values) {
|
||||||
|
expect(css).toContain(`.ion-${value}`);
|
||||||
|
}
|
||||||
|
for (const value of values) {
|
||||||
|
for (const infix of INFIXES) {
|
||||||
|
expect(css).toContain(`.ion-flex${infix}-${value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('flex-fill classes', () => {
|
||||||
|
const values = ['1', 'auto', 'initial', 'none'];
|
||||||
|
for (const value of values) {
|
||||||
|
for (const infix of INFIXES) {
|
||||||
|
expect(css).toContain(`.ion-flex${infix}-${value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('flex-grow and flex-shrink classes', () => {
|
||||||
|
const values = ['grow', 'shrink'];
|
||||||
|
for (const value of values) {
|
||||||
|
for (const infix of INFIXES) {
|
||||||
|
expect(css).toContain(`.ion-flex${infix}-${value}-0`);
|
||||||
|
expect(css).toContain(`.ion-flex${infix}-${value}-1`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('flex-order classes', () => {
|
||||||
|
for (const infix of INFIXES) {
|
||||||
|
expect(css).toContain(`.ion-order${infix}-first`);
|
||||||
|
expect(css).toContain(`.ion-order${infix}-last`);
|
||||||
|
for (let i = 0; i <= 12; i++) {
|
||||||
|
expect(css).toContain(`.ion-order${infix}-${i}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
Reference in New Issue
Block a user