Skip to content

Commit 1167555

Browse files
committed
refactor(eds-core-react): 🔧 Input - configure Rollup CSS build
- Add three Rollup configurations for JS and CSS builds - Output formatted CSS to build/styles.css (3.5KB) - Output minified CSS to build/styles.min.css (2.1KB) - Use postcss-import to bundle @import statements - Clean separation: CSS in build/, JS/TS in dist/ - Export both CSS versions in package.json - Update CSS_ARCHITECTURE.md with concise documentation - No new dependencies (uses existing postcss packages)
1 parent ff41418 commit 1167555

File tree

5 files changed

+193
-42
lines changed

5 files changed

+193
-42
lines changed
Lines changed: 35 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,71 @@
1-
# Global CSS Architecture
1+
# CSS Architecture
22

33
## Overview
44

5-
Component CSS is now centralized in a global `styles.css` file to prevent duplicate CSS imports when users consume the library.
5+
Component CSS is centralized in `src/styles.css` to prevent duplicate imports and enable automatic tree-shaking.
66

77
## Structure
88

99
```
1010
src/
11-
├── styles.css # Global CSS entry point
12-
├── index.ts # Imports styles.css once
11+
├── styles.css # Imports all component CSS
12+
├── index.ts # Imports styles.css once
1313
└── components/
1414
└── Input/
15-
├── Input.new.tsx # No CSS import
16-
└── Input.new.css # Styles imported via styles.css
15+
├── Input.new.tsx # No CSS import
16+
└── Input.new.css # Styles defined here
1717
```
1818

1919
## How It Works
2020

21-
1. **Component CSS files** (`Input.new.css`) contain the styles
22-
2. **Global styles.css** imports all component CSS files
23-
3. **Main index.ts** imports `styles.css` once
24-
4. **Users** get all CSS automatically when they import any component
21+
1. Component CSS files contain the styles
22+
2. `src/styles.css` imports all component CSS with `@import`
23+
3. `src/index.ts` imports `styles.css` once
24+
4. Users get all CSS automatically when importing components
2525

26-
## Benefits
26+
## Adding Components
2727

28-
✅ **No duplicate CSS** - CSS is imported once at the package level
29-
✅ **Automatic tree-shaking** - Bundlers can optimize unused CSS
30-
✅ **Better performance** - Single CSS import instead of per-component
31-
✅ **Easier maintenance** - All CSS imports in one place
28+
When creating a component with CSS:
3229

33-
## Adding New Components
34-
35-
When creating a new component with CSS:
36-
37-
1. Create the component CSS file (e.g., `Button.new.css`)
38-
2. Add import to `src/styles.css`:
30+
1. Create `Button.new.css` in component directory
31+
2. Add to `src/styles.css`:
3932
```css
4033
@import './components/Button/Button.new.css';
4134
```
42-
3. **Do NOT** import CSS in the component `.tsx` file
35+
3. **Never** import CSS in `.tsx` files
4336

44-
## Storybook Configuration
37+
## Build
4538

46-
The `.storybook/preview.mjs` imports the global CSS file:
39+
Rollup builds CSS with PostCSS to bundle all `@import` statements:
4740

48-
```javascript
49-
import './preview.css'
50-
import '../src/styles.css' // Global component styles
51-
```
41+
- **Input**: `src/styles.css`
42+
- **Output**:
43+
- `build/styles.css` (3.5KB formatted)
44+
- `build/styles.min.css` (2.1KB minified)
5245

53-
This ensures all component styles are available in Storybook stories.
46+
## Usage
5447

55-
## User Consumption
56-
57-
Users automatically get all CSS when importing components:
48+
Import components normally -- CSS is included automatically:
5849

5950
```tsx
60-
// This imports both the component AND all CSS
6151
import { InputNew } from '@equinor/eds-core-react'
6252
```
6353

64-
Alternatively, users can import just the CSS if needed:
54+
Or import CSS separately if needed:
6555

6656
```tsx
67-
import '@equinor/eds-core-react/styles.css'
57+
import '@equinor/eds-core-react/styles.css' // Development
58+
import '@equinor/eds-core-react/styles.min.css' // Production
6859
```
6960
70-
## Package Configuration
61+
## Configuration
7162
72-
The `package.json` includes:
63+
**package.json**:
64+
- `"sideEffects": ["**/*.css"]` -- Preserves CSS during tree-shaking
65+
- `"files": ["dist/*", "build/*"]` -- Publishes JS and CSS
66+
- Exports CSS at `./styles.css` and `./styles.min.css`
7367
74-
- `"sideEffects": ["**/*.css"]` - Preserves CSS imports during tree-shaking
75-
- `"./styles.css": "./dist/esm/styles.css"` - Exports CSS separately if needed
68+
**Storybook** (`.storybook/preview.mjs`):
69+
```javascript
70+
import '../src/styles.css' // Global component styles
71+
```
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/* Global styles for @equinor/eds-core-react */
2+
3+
/* Component styles */
4+
5+
@layer eds-components {
6+
/* Container - use neutral appearance by default */
7+
.eds-input {
8+
position: relative;
9+
display: flex;
10+
flex-direction: row;
11+
align-items: center;
12+
box-sizing: border-box;
13+
width: 100%;
14+
background: var(--eds-color-bg-surface);
15+
border: 1px solid var(--eds-color-border-medium);
16+
border-radius: var(--eds-spacing-border-radius-rounded);
17+
}
18+
19+
/* Hover - only for enabled inputs */
20+
.eds-input:hover:not(.eds-input--disabled):not(.eds-input--readonly) {
21+
border-color: var(--eds-color-border-strong);
22+
}
23+
24+
/* Container states */
25+
.eds-input:focus-within {
26+
border-color: transparent;
27+
outline: 2px solid var(--eds-color-border-focus);
28+
outline-offset: -2px;
29+
}
30+
31+
.eds-input--disabled {
32+
cursor: not-allowed;
33+
color: var(--eds-color-border-medium);
34+
border-color: var(--eds-color-border-subtle);
35+
}
36+
37+
.eds-input--readonly {
38+
border-color: var(--eds-color-border-subtle);
39+
}
40+
41+
/* Invalid state - border color comes from data-color-appearance="danger" */
42+
.eds-input--invalid {
43+
border-color: var(--eds-color-border-medium);
44+
}
45+
46+
/* Input/Textarea field */
47+
.eds-field {
48+
width: 100%;
49+
border: none;
50+
background: transparent;
51+
outline: none;
52+
color: var(--eds-color-text-strong);
53+
font-family: var(--eds-typography-ui-body-font-family), sans-serif;
54+
font-size: var(--eds-typography-ui-body-lg-font-size);
55+
font-weight: var(--eds-typography-ui-body-lg-font-weight-normal);
56+
line-height: var(--eds-typography-ui-body-lg-lineheight-squished);
57+
padding-block: var(--eds-selectable-spacing-stack);
58+
padding-inline: var(--eds-selectable-spacing-inline);
59+
overflow: hidden;
60+
white-space: nowrap;
61+
text-overflow: ellipsis;
62+
resize: none;
63+
}
64+
65+
.eds-field::placeholder {
66+
color: var(--eds-color-text-subtle);
67+
}
68+
69+
/*
70+
* Disabled field - override browser defaults for consistent styling
71+
* Safari applies default opacity and color to disabled inputs, so we need
72+
* to explicitly set opacity: 1 and use -webkit-text-fill-color
73+
* Note: We don't rely on inherited color context, so this works consistently
74+
*/
75+
.eds-input--disabled .eds-field {
76+
color: var(--eds-color-text-subtle);
77+
cursor: not-allowed;
78+
opacity: 1;
79+
-webkit-text-fill-color: var(--eds-color-text-subtle);
80+
}
81+
82+
/* Disabled placeholder - maintain same color as disabled text */
83+
.eds-input--disabled .eds-field::placeholder {
84+
-webkit-text-fill-color: var(--eds-color-text-subtle);
85+
}
86+
87+
/* Adornments (icons, text, buttons on left/right)
88+
* Always use neutral appearance regardless of parent invalid state
89+
*/
90+
.eds-adornment {
91+
position: absolute;
92+
top: var(--eds-selectable-spacing-stack);
93+
bottom: var(--eds-selectable-spacing-stack);
94+
display: flex;
95+
align-items: center;
96+
color: var(--eds-color-text-subtle);
97+
font-family: var(--eds-typography-ui-body-font-family), sans-serif;
98+
font-size: var(--eds-typography-ui-body-md-font-size);
99+
font-weight: var(--eds-typography-ui-body-md-font-weight-normal);
100+
line-height: var(--eds-typography-ui-body-md-lineheight-default);
101+
}
102+
103+
/* Force neutral colors for adornments even when parent has invalid state */
104+
[data-color-appearance] .eds-adornment {
105+
color: var(--eds-color-text-subtle);
106+
}
107+
108+
.eds-adornment--left {
109+
left: 0;
110+
padding-left: var(--eds-selectable-spacing-inline);
111+
}
112+
113+
.eds-adornment--right {
114+
right: 0;
115+
padding-right: var(--eds-selectable-spacing-inline);
116+
}
117+
}

‎packages/eds-core-react/build/styles.min.css‎

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎packages/eds-core-react/package.json‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,17 @@
2323
"url": "https://github.com/equinor/design-system/issues"
2424
},
2525
"files": [
26-
"dist/*"
26+
"dist/*",
27+
"build/*"
2728
],
2829
"exports": {
2930
".": {
3031
"types": "./dist/types/index.d.ts",
3132
"import": "./dist/esm/index.js",
3233
"require": "./dist/eds-core-react.cjs"
3334
},
34-
"./styles.css": "./dist/esm/styles.css"
35+
"./styles.css": "./build/styles.css",
36+
"./styles.min.css": "./build/styles.min.css"
3537
},
3638
"scripts": {
3739
"build": "rollup -c && tsc -p tsconfig.build.json",

‎packages/eds-core-react/rollup.config.js‎

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* eslint-disable import/no-default-export */
22
import resolve from '@rollup/plugin-node-resolve'
33
import postcss from 'rollup-plugin-postcss'
4+
import postcssImport from 'postcss-import'
45
import commonjs from '@rollup/plugin-commonjs'
56
import { preserveDirective } from 'rollup-preserve-directives'
67
import { babel } from '@rollup/plugin-babel'
@@ -31,12 +32,13 @@ export default [
3132
},
3233
plugins: [
3334
preserveDirective(),
34-
del({ targets: 'dist/*', runOnce: true }),
35+
del({ targets: ['dist/*', 'build/*'], runOnce: true }),
3536
resolve({ extensions }),
3637
commonjs(),
3738
postcss({
3839
extensions: ['.css'],
3940
extract: false,
41+
inject: false,
4042
}),
4143
babel({
4244
babelHelpers: 'runtime',
@@ -55,4 +57,37 @@ export default [
5557
{ file: './dist/eds-core-react.cjs', format: 'cjs', interop: 'auto' },
5658
],
5759
},
60+
{
61+
input: './src/styles.css',
62+
plugins: [
63+
postcss({
64+
extensions: ['.css'],
65+
extract: 'styles.css',
66+
minimize: false,
67+
sourceMap: false,
68+
plugins: [postcssImport()],
69+
}),
70+
],
71+
output: {
72+
dir: 'build',
73+
format: 'es',
74+
},
75+
},
76+
{
77+
input: './src/styles.css',
78+
plugins: [
79+
postcss({
80+
extensions: ['.css'],
81+
extract: 'styles.min.css',
82+
minimize: true,
83+
sourceMap: false,
84+
plugins: [postcssImport()],
85+
}),
86+
del({ targets: 'build/*.js', hook: 'writeBundle' }),
87+
],
88+
output: {
89+
dir: 'build',
90+
format: 'es',
91+
},
92+
},
5893
]

0 commit comments

Comments
 (0)