Skip to content

Commit

Permalink
build: Make the sandbox (npm run dev) switchable between LTR and RTL
Browse files Browse the repository at this point in the history
- Use postcss-rtlcss to make styles bidirectional in serve mode. This
  produces styles like [dir='ltr'] {...} [dir='rtl'] {...}
- (In build mode, continue to use rtlcss to build two separate style
  files, one for LTR and one for RTL)
- Add a direction switcher to the sandbox
- Move Sandbox.vue into a new src/demo directory, so we can put
  DirectionSwitcher.vue alongside it

Unfortunately this uses two different RTL flipping packages for build vs
serve mode. Thankfully postcss-rtlcss uses rtlcss for its flipping
logic, so while this makes me a little uneasy we shouldn't see any
differences in behavior between the two.

Bug: T295189
Bug: T296031
Change-Id: Ie3221fb349b269eb259f07c530b2dbfb9ae44a1b
  • Loading branch information
catrope committed Jan 25, 2022
1 parent 9be0516 commit fbfd6a6
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 24 deletions.
46 changes: 46 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/vue-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
},
"devDependencies": {
"@types/jest": "^27.0.2",
"@types/rtlcss": "^3.1.2",
"@vitejs/plugin-vue": "^2.1.0",
"@vue/compiler-sfc": "^3.2.19",
"@vue/test-utils": "^2.0.0-rc.15",
Expand All @@ -43,6 +44,7 @@
"jest": "^27.3.1",
"less": "^4.1.2",
"postcss": "8.3.11",
"postcss-rtlcss": "^3.5.1",
"rtlcss": "^3.5.0",
"ts-jest": "^27.0.5",
"typescript": "^4.4.3",
Expand Down
16 changes: 0 additions & 16 deletions packages/vue-components/sandbox-rtl.html

This file was deleted.

39 changes: 39 additions & 0 deletions packages/vue-components/src/demo/DirectionSwitcher.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<template>
<cdx-button
v-for="direction in directions"
:key="direction.value"
type="primary"
:action="modelValue === direction.value ? 'progressive' : 'default'"
@click="$emit( 'update:modelValue', direction.value )"
>
{{ direction.label }}
</cdx-button>
</template>

<script lang="ts">
import { defineComponent, PropType } from 'vue';
import CdxButton from '../components/button/Button.vue';
import { HTMLDirection } from '../types';
// TODO this component will be superfluous once we have a ButtonGroup component
export default defineComponent( {
components: {
CdxButton
},
props: {
modelValue: {
type: String as PropType<HTMLDirection>,
default: 'ltr'
}
},
emits: [
'update:modelValue'
],
data: () => ( {
directions: [
{ value: 'ltr', label: 'LTR' },
{ value: 'rtl', label: 'RTL' }
]
} )
} );
</script>
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
<template>
<div>
<div :dir="dir">
<nav>
Direction:
<direction-switcher v-model="dir" />
</nav>

<header>
<h1>Codex Demo</h1>
</header>
Expand Down Expand Up @@ -97,18 +102,19 @@
</template>

<script lang="ts" setup>
import { CdxButton, CdxCheckbox, CdxCombobox, CdxIcon, CdxRadio, CdxSelect, CdxTextInput } from './lib';
import { CdxButton, CdxCheckbox, CdxCombobox, CdxIcon, CdxRadio, CdxSelect, CdxTextInput, HTMLDirection, MenuOption } from '../lib';
import { cdxIconArrowNext, cdxIconBold, cdxIconTrash } from 'icons';
import { ButtonActions, ButtonTypes } from './constants';
import { MenuOption } from './types';
import { ButtonActions, ButtonTypes } from '../constants';
import { ref } from 'vue';
import DirectionSwitcher from './DirectionSwitcher.vue';
const options: MenuOption[] = [
{ label: 'Apple', value: 'a' },
{ label: 'Banana', value: 'b' },
{ label: 'Canteloupe', value: 'c' }
];
const dir = ref<HTMLDirection>( 'ltr' );
const selection = ref<string>();
const multiSelection = ref<string[]>( [] );
Expand All @@ -127,4 +133,8 @@ td {
/* stylelint-disable-next-line unit-disallowed-list */
padding: 1.5rem;
}
nav {
float: right;
}
</style>
2 changes: 1 addition & 1 deletion packages/vue-components/src/start.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createApp } from 'vue';
import App from './Sandbox.vue';
import App from './demo/Sandbox.vue';

createApp( App ).mount( '#app' );
38 changes: 35 additions & 3 deletions packages/vue-components/vite-plugin-rtl-css.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,49 @@
import { Plugin } from 'vite';
import rtlcss from 'rtlcss';
import postcssRTLCSS from 'postcss-rtlcss';

const rtlcssOptions = {
useCalc: true
};

/**
* Vite plugin that generates RTL versions of all .css output files.
* Vite plugin that generates RTL versions of all .css output files in build mode,
* and serves bidirectional CSS in serve mode.
*
* @return Plugin
*/
export default function rtlCss() : Plugin {

return {
name: 'rtl-css',
apply: 'build',
enforce: 'post',
config( config, env ) {
if ( env.command !== 'serve' ) {
return;
}
// Use postcss-rtlcss only in serve mode (npm run dev)
// This generates CSS like:
// [ dir='ltr' ] .foo { padding-left: 4px; }
// [ dir='rtl' ] .foo { padding-right: 4px; }
return {
css: {
postcss: {
plugins: [
// FIXME this weird type assertion is needed here because we use
// PostCSS 8.3.11, but Vite uses 8.4.5. This causes postcssRTLCSS() to
// return a PostCSS 8.3 plugin but Vite to expect an 8.4 plugin, which
// works in practice but the TypeScript types are not compatible.
// We can't upgrade PostCSS because that would cause a stylelint crash,
// see https://github.com/stylelint/stylelint/issues/5766
postcssRTLCSS( rtlcssOptions ) as { postcssPlugin: string }
]
}
}
};
},
generateBundle( options, bundle ) {
// This runs only in build mode (npm run build)
// For every generated .css file, generate a corresponding -rtl.css file
for ( const file of Object.values( bundle ) ) {
if ( file.type === 'asset' && file.fileName.endsWith( '.css' ) ) {
const ltrSource = typeof file.source === 'string' ?
Expand All @@ -20,7 +52,7 @@ export default function rtlCss() : Plugin {
this.emitFile( {
type: 'asset',
fileName: file.fileName.replace( /\.css$/, '-rtl.css' ),
source: rtlcss.process( ltrSource, {}, {}, {} )
source: rtlcss.process( ltrSource, rtlcssOptions )
} );
}
}
Expand Down

0 comments on commit fbfd6a6

Please sign in to comment.