Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add tailwind styles to lit migration #4804

Closed
wants to merge 12 commits into from
Closed
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
14,011 changes: 567 additions & 13,444 deletions package-lock.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {APP_INITIALIZER, ModuleWithProviders, NgModule, Provider} from '@angular


import {
AtomicText,
AtomicAriaLive,
AtomicAutomaticFacet,
AtomicAutomaticFacetGenerator,
Expand Down Expand Up @@ -140,7 +141,6 @@ AtomicSortExpression,
AtomicTab,
AtomicTabManager,
AtomicTableElement,
AtomicText,
AtomicTimeframe,
AtomicTimeframeFacet
} from './components';
Expand All @@ -151,6 +151,7 @@ defineCustomElements(window);


const DECLARATIONS = [
AtomicText,
AtomicAriaLive,
AtomicAutomaticFacet,
AtomicAutomaticFacetGenerator,
Expand Down Expand Up @@ -286,7 +287,6 @@ AtomicSortExpression,
AtomicTab,
AtomicTabManager,
AtomicTableElement,
AtomicText,
AtomicTimeframe,
AtomicTimeframeFacet
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3041,16 +3041,16 @@ export declare interface AtomicTableElement extends Components.AtomicTableElemen


@ProxyCmp({
inputs: ['count', 'value']
inputs: ['amount', 'label', 'period', 'unit']
})
@Component({
selector: 'atomic-text',
selector: 'atomic-timeframe',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['count', 'value'],
inputs: ['amount', 'label', 'period', 'unit'],
})
export class AtomicText {
export class AtomicTimeframe {
protected el: HTMLElement;
constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
c.detach();
Expand All @@ -3059,20 +3059,20 @@ export class AtomicText {
}


export declare interface AtomicText extends Components.AtomicText {}
export declare interface AtomicTimeframe extends Components.AtomicTimeframe {}


@ProxyCmp({
inputs: ['amount', 'label', 'period', 'unit']
inputs: ['dependsOn', 'facetId', 'field', 'filterFacetCount', 'headingLevel', 'injectionDepth', 'isCollapsed', 'label', 'max', 'min', 'sortCriteria', 'tabsExcluded', 'tabsIncluded', 'withDatePicker']
})
@Component({
selector: 'atomic-timeframe',
selector: 'atomic-timeframe-facet',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['amount', 'label', 'period', 'unit'],
inputs: ['dependsOn', 'facetId', 'field', 'filterFacetCount', 'headingLevel', 'injectionDepth', 'isCollapsed', 'label', 'max', 'min', 'sortCriteria', 'tabsExcluded', 'tabsIncluded', 'withDatePicker'],
})
export class AtomicTimeframe {
export class AtomicTimeframeFacet {
protected el: HTMLElement;
constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
c.detach();
Expand All @@ -3081,30 +3081,28 @@ export class AtomicTimeframe {
}


export declare interface AtomicTimeframe extends Components.AtomicTimeframe {}
export declare interface AtomicTimeframeFacet extends Components.AtomicTimeframeFacet {}



@ProxyCmp({
inputs: ['dependsOn', 'facetId', 'field', 'filterFacetCount', 'headingLevel', 'injectionDepth', 'isCollapsed', 'label', 'max', 'min', 'sortCriteria', 'tabsExcluded', 'tabsIncluded', 'withDatePicker']
inputs: ['value', 'count']
})
@Component({
selector: 'atomic-timeframe-facet',
selector: 'atomic-text',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['dependsOn', 'facetId', 'field', 'filterFacetCount', 'headingLevel', 'injectionDepth', 'isCollapsed', 'label', 'max', 'min', 'sortCriteria', 'tabsExcluded', 'tabsIncluded', 'withDatePicker'],
inputs: ['value', 'count']
})
export class AtomicTimeframeFacet {
protected el: HTMLElement;
constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
export class AtomicText {
protected readonly el: HTMLElement;
constructor(c: ChangeDetectorRef, el: ElementRef, protected z: NgZone) {
c.detach();
this.el = r.nativeElement;
this.el = el.nativeElement;
}
}

export declare interface AtomicText extends LitAtomicText {}

export declare interface AtomicTimeframeFacet extends Components.AtomicTimeframeFacet {}



import type {} from '@coveo/atomic/components';
import type {AtomicText as LitAtomicText} from '@coveo/atomic/components';
2 changes: 1 addition & 1 deletion packages/atomic-angular/scripts/build-lit.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import cem from '@coveo/atomic/custom-elements-manifest' with {type: 'json'};
import { createWriteStream, readFileSync, writeFileSync } from 'fs';

const isLitDeclaration = (declaration) => declaration?.superclass?.name === 'LitElement';
const isLitDeclaration = (declaration) => declaration?.superclass?.name === 'LitElement' || declaration?.superclass?.name === 'TailwindLitElement';

const atomicAngularModuleFilePath ='projects/atomic-angular/src/lib/stencil-generated/atomic-angular.module.ts';
const atomicAngularModuleFileContent = readFileSync(atomicAngularModuleFilePath, 'utf-8');
Expand Down
6 changes: 4 additions & 2 deletions packages/atomic-react/scripts/build-lit.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import cem from '@coveo/atomic/custom-elements-manifest' with {type: 'json'};
import {writeFileSync} from 'node:fs';
import * as prettier from 'prettier';



const isLitDeclaration = (declaration) =>
declaration?.superclass?.name === 'LitElement';
declaration?.superclass?.name === 'LitElement' || declaration?.superclass?.name === 'TailwindLitElement';

const entries = [
{
Expand Down Expand Up @@ -87,4 +89,4 @@ for (const entry of entries) {
prettierConfig
)
)
}
}
10 changes: 9 additions & 1 deletion packages/atomic-react/src/components/search/components.ts
Original file line number Diff line number Diff line change
@@ -1 +1,9 @@
export {};
import {AtomicText as LitAtomicText} from '@coveo/atomic/components';
import {createComponent} from '@lit/react';
import React from 'react';

export const AtomicText = createComponent({
tagName: 'atomic-text',
react: React,
elementClass: LitAtomicText,
});
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,5 @@ export const AtomicSortExpression = /*@__PURE__*/createReactComponent<JSX.Atomic
export const AtomicTab = /*@__PURE__*/createReactComponent<JSX.AtomicTab, HTMLAtomicTabElement>('atomic-tab');
export const AtomicTabManager = /*@__PURE__*/createReactComponent<JSX.AtomicTabManager, HTMLAtomicTabManagerElement>('atomic-tab-manager');
export const AtomicTableElement = /*@__PURE__*/createReactComponent<JSX.AtomicTableElement, HTMLAtomicTableElementElement>('atomic-table-element');
export const AtomicText = /*@__PURE__*/createReactComponent<JSX.AtomicText, HTMLAtomicTextElement>('atomic-text');
export const AtomicTimeframe = /*@__PURE__*/createReactComponent<JSX.AtomicTimeframe, HTMLAtomicTimeframeElement>('atomic-timeframe');
export const AtomicTimeframeFacet = /*@__PURE__*/createReactComponent<JSX.AtomicTimeframeFacet, HTMLAtomicTimeframeFacetElement>('atomic-timeframe-facet');
2 changes: 2 additions & 0 deletions packages/atomic/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,13 @@
"jest-cli": "29.7.0",
"jest-environment-node": "29.7.0",
"jest-localstorage-mock": "2.4.26",
"lightningcss": "1.28.2",
"lit-html": "3.2.1",
"local-web-server": "5.4.0",
"natural-orderby": "5.0.0",
"postcss-focus-visible": "10.0.1",
"postcss-import": "16.1.0",
"postcss-load-config": "6.0.1",
"postcss-map": "0.11.0",
"postcss-mixins": "11.0.3",
"postcss-nested": "7.0.2",
Expand Down
7 changes: 7 additions & 0 deletions packages/atomic/postcss.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import autoprefixer from 'autoprefixer';
import postcssImport from 'postcss-import';
import tailwindcss from 'tailwindcss';

export default {
plugins: [postcssImport(), tailwindcss(), autoprefixer()],
};
87 changes: 87 additions & 0 deletions packages/atomic/process-css.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import {readdir, mkdir, readFile, writeFile} from 'fs';
import * as lightningcss from 'lightningcss';
import {join, dirname, relative} from 'path';
import postcss from 'postcss';
import postcssLoadConfig from 'postcss-load-config';
import {fileURLToPath} from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const srcDir = join(__dirname, 'src');
const distDir = join(__dirname, 'dist', 'components');

async function processAndMinifyCss(content, filename) {
const {plugins, options} = await postcssLoadConfig();
const result = await postcss(plugins).process(content, {
...options,
from: filename,
});

let processedCss = minifyCss(result, filename);

return processedCss;
}

function minifyCss(result, filename) {
return lightningcss
.transform({
code: Buffer.from(result.css),
minify: true,
sourceMap: true,
filename: filename,
})
.code.toString();
}

function escapeString(str) {
return str.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$/g, '\\$');
}

function convertCssToJs(srcPath, distPath, file) {
readFile(srcPath, 'utf8', async (err, data) => {
if (err) {
throw err;
}

const processedCss = await processAndMinifyCss(data, srcPath);
const jsContent = `export default \`${escapeString(processedCss)}\`;`;
const jsPath = distPath + '.js';

writeFile(jsPath, jsContent, (err) => {
if (err) {
throw err;
}
});
});
}

function processCssFiles(srcDir, distDir) {
readdir(srcDir, {withFileTypes: true}, (err, files) => {
if (err) {
throw err;
}

files.forEach((file) => {
const srcPath = join(srcDir, file.name);

if (file.isDirectory()) {
processCssFiles(srcPath, join(distDir, file.name));
} else if (file.isFile() && file.name.endsWith('.tw.css')) {
const relPath = relative(srcDir, srcPath);
const distPath = join(distDir, relPath);
const targetDir = dirname(distPath);
console.log(`Processing ${srcPath}`);

mkdir(targetDir, {recursive: true}, (err) => {
if (err) {
throw err;
}
convertCssToJs(srcPath, distPath, file);
});
}
});
});
}

processCssFiles(srcDir, distDir);
1 change: 1 addition & 0 deletions packages/atomic/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"node --max_old_space_size=6144 ../../node_modules/@stencil/core/bin/stencil build",
"node ./scripts/stencil-proxy.mjs",
"tsc -p tsconfig.lit.json",
"node process-css.mjs",
"esbuild src/autoloader/index.ts --format=esm --outfile=dist/atomic/autoloader/index.esm.js",
"esbuild src/autoloader/index.ts --format=cjs --outfile=dist/atomic/autoloader/index.cjs.js"
],
Expand Down
1 change: 1 addition & 0 deletions packages/atomic/scripts/watch.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ function rebuild() {
'node --max_old_space_size=6144 ../../node_modules/@stencil/core/bin/stencil build',
'node ./scripts/stencil-proxy.mjs',
'tsc -p tsconfig.lit.json',
'node process-css.mjs',
'esbuild src/autoloader/index.ts --format=esm --outfile=dist/atomic/autoloader/index.esm.js',
'esbuild src/autoloader/index.ts --format=cjs --outfile=dist/atomic/autoloader/index.cjs.js',
];
Expand Down
41 changes: 0 additions & 41 deletions packages/atomic/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3724,19 +3724,6 @@ export namespace Components {
*/
"label": string;
}
/**
* The `atomic-text` component leverages the I18n translation module through the atomic-search-interface.
*/
interface AtomicText {
/**
* The count value used for plurals.
*/
"count"?: number;
/**
* The string key value.
*/
"value": string;
}
/**
* The `atomic-timeframe` component defines a timeframe of an `atomic-timeframe-facet`, and therefore must be defined within an `atomic-timeframe-facet` component.
* A timeframe is a span of time from now to a specific time in the past.
Expand Down Expand Up @@ -6066,15 +6053,6 @@ declare global {
prototype: HTMLAtomicTableElementElement;
new (): HTMLAtomicTableElementElement;
};
/**
* The `atomic-text` component leverages the I18n translation module through the atomic-search-interface.
*/
interface HTMLAtomicTextElement extends Components.AtomicText, HTMLStencilElement {
}
var HTMLAtomicTextElement: {
prototype: HTMLAtomicTextElement;
new (): HTMLAtomicTextElement;
};
/**
* The `atomic-timeframe` component defines a timeframe of an `atomic-timeframe-facet`, and therefore must be defined within an `atomic-timeframe-facet` component.
* A timeframe is a span of time from now to a specific time in the past.
Expand Down Expand Up @@ -6293,7 +6271,6 @@ declare global {
"atomic-tab-manager-bar": HTMLAtomicTabManagerBarElement;
"atomic-tab-popover": HTMLAtomicTabPopoverElement;
"atomic-table-element": HTMLAtomicTableElementElement;
"atomic-text": HTMLAtomicTextElement;
"atomic-timeframe": HTMLAtomicTimeframeElement;
"atomic-timeframe-facet": HTMLAtomicTimeframeFacetElement;
}
Expand Down Expand Up @@ -9819,19 +9796,6 @@ declare namespace LocalJSX {
*/
"label": string;
}
/**
* The `atomic-text` component leverages the I18n translation module through the atomic-search-interface.
*/
interface AtomicText {
/**
* The count value used for plurals.
*/
"count"?: number;
/**
* The string key value.
*/
"value": string;
}
/**
* The `atomic-timeframe` component defines a timeframe of an `atomic-timeframe-facet`, and therefore must be defined within an `atomic-timeframe-facet` component.
* A timeframe is a span of time from now to a specific time in the past.
Expand Down Expand Up @@ -10114,7 +10078,6 @@ declare namespace LocalJSX {
"atomic-tab-manager-bar": AtomicTabManagerBar;
"atomic-tab-popover": AtomicTabPopover;
"atomic-table-element": AtomicTableElement;
"atomic-text": AtomicText;
"atomic-timeframe": AtomicTimeframe;
"atomic-timeframe-facet": AtomicTimeframeFacet;
}
Expand Down Expand Up @@ -10995,10 +10958,6 @@ declare module "@stencil/core" {
* The `atomic-table-element` element defines a table column in a result list.
*/
"atomic-table-element": LocalJSX.AtomicTableElement & JSXBase.HTMLAttributes<HTMLAtomicTableElementElement>;
/**
* The `atomic-text` component leverages the I18n translation module through the atomic-search-interface.
*/
"atomic-text": LocalJSX.AtomicText & JSXBase.HTMLAttributes<HTMLAtomicTextElement>;
/**
* The `atomic-timeframe` component defines a timeframe of an `atomic-timeframe-facet`, and therefore must be defined within an `atomic-timeframe-facet` component.
* A timeframe is a span of time from now to a specific time in the past.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
div {
transition: background-color 0.3s;

@apply text-white;
}

div:hover {
@apply bg-primary-dark;
}
Comment on lines +1 to +9
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These styles are just to demonstrate how to combine normal css, inline styles, tailwind @apply rules and tailwind classes directly in the component markup.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For Tailwind V4, the theme need to be imported with the theme(reference) rule so that the tailwind utilities (including our custom theme) are available. See this for example:
https://github.com/coveo/headless-lit/blob/tsc-tw4/lito/src/components/lito-result-title/lito-result-title.css
(Notice that the theme.css file in that example only contains @theme rules, as other rules cannot be referenced that way)

It is possible to import the theme directly or even tailwind itself instead, but that will result in all their css being embedded in this file.

Loading
Loading