diff --git a/e2e/App.tsx b/e2e/App.tsx
index 8d58d9220f..6e43709c1f 100644
--- a/e2e/App.tsx
+++ b/e2e/App.tsx
@@ -28,7 +28,10 @@ const pagesToRender = Object.keys(modules)
? {
Component: lazy(
// oxlint-disable-next-line typescript/no-unsafe-return
- async () => import(`./tests/${path?.split('/')[2]}/render.tsx`),
+ async () =>
+ import(
+ `./tests/${path?.split('/')[2]}/${path?.split('/')[3]}/render.tsx`
+ ),
),
name: path.replace('.tsx', ''),
}
@@ -55,9 +58,9 @@ const WelcomePage = () => (
{pagesToRender.map(path => (
- {path?.name?.split('/')[2]?.toLowerCase()}
+ {path?.name?.split('/')[3]?.toLowerCase()}
))}
@@ -79,7 +82,7 @@ const App = () => (
}
key={path?.name}
- path={path?.name?.split('/')[2]?.toLowerCase()}
+ path={path?.name?.split('/')[3]?.toLowerCase()}
/>
)
}
diff --git a/e2e/Dockerfile b/e2e/Dockerfile
new file mode 100644
index 0000000000..fd40865935
--- /dev/null
+++ b/e2e/Dockerfile
@@ -0,0 +1,17 @@
+# this dockerfile will be used to generate the same screenshot for our CI.
+FROM mcr.microsoft.com/playwright:v1.58.2-jammy
+
+WORKDIR /build
+
+ARG TURBO_TOKEN=
+
+ENV TURBO_TOKEN ${TURBO_TOKEN}
+ENV CI=true
+
+COPY . .
+
+RUN npm install -g corepack@0.31.0
+RUN corepack enable
+RUN pnpm install --frozen-lockfile
+
+ENTRYPOINT ["pnpm", "run", "test:e2e"]
diff --git a/e2e/playwright.config.ts b/e2e/playwright.config.ts
index 957ffd996b..cd0dcf3272 100644
--- a/e2e/playwright.config.ts
+++ b/e2e/playwright.config.ts
@@ -19,21 +19,32 @@ export default defineConfig({
/* Configure projects for major browsers */
projects: [
{
- name: 'chromium',
+ name: 'e2e-chromium',
+ testDir: './tests/e2e',
use: { ...devices['Desktop Chrome'] },
},
{
- name: 'firefox',
+ name: 'e2e-firefox',
+ testDir: './tests/e2e',
use: { ...devices['Desktop Firefox'] },
},
{
- name: 'webkit',
- use: { ...devices['Desktop Safari'] },
+ name: 'e2e-webkit',
+ testDir: './tests/e2e',
+ use: {
+ ...devices['Desktop Safari'],
+ },
+ },
+ {
+ name: 'screenshots-chromium',
+ testDir: './tests/screenshots',
+ use: {
+ ...devices['Desktop Chrome'],
+ },
},
],
reporter: 'line',
retries: isCI ? 2 : 0,
- testDir: './tests',
timeout: isCI ? Number(times['1min']) : undefined,
use: {
baseURL,
@@ -45,6 +56,7 @@ export default defineConfig({
stderr: 'pipe',
stdout: 'ignore',
url: baseURL,
+ reuseExistingServer: true,
},
workers: isCI ? 1 : undefined,
})
diff --git a/e2e/tests/componentsWithinModal/render.tsx b/e2e/tests/e2e/componentsWithinModal/render.tsx
similarity index 96%
rename from e2e/tests/componentsWithinModal/render.tsx
rename to e2e/tests/e2e/componentsWithinModal/render.tsx
index 37368a423c..bbe93bbb76 100644
--- a/e2e/tests/componentsWithinModal/render.tsx
+++ b/e2e/tests/e2e/componentsWithinModal/render.tsx
@@ -7,7 +7,7 @@ import {
import { Button, Modal, Stack, Text, TextInput } from '@ultraviolet/ui'
import { useState } from 'react'
-import { mockErrors } from '../../mocks/mockErrors'
+import { mockErrors } from '../../../mocks/mockErrors'
const Render = () => {
const methods = useForm<{ lastName: ''; color: '' }>()
diff --git a/e2e/tests/componentsWithinModal/test.spec.ts b/e2e/tests/e2e/componentsWithinModal/test.spec.ts
similarity index 100%
rename from e2e/tests/componentsWithinModal/test.spec.ts
rename to e2e/tests/e2e/componentsWithinModal/test.spec.ts
diff --git a/e2e/tests/selectableCardComplexChildren/CheckboxSelectableCard.tsx b/e2e/tests/e2e/selectableCardComplexChildren/CheckboxSelectableCard.tsx
similarity index 100%
rename from e2e/tests/selectableCardComplexChildren/CheckboxSelectableCard.tsx
rename to e2e/tests/e2e/selectableCardComplexChildren/CheckboxSelectableCard.tsx
diff --git a/e2e/tests/selectableCardComplexChildren/RadioSelectableCard.tsx b/e2e/tests/e2e/selectableCardComplexChildren/RadioSelectableCard.tsx
similarity index 100%
rename from e2e/tests/selectableCardComplexChildren/RadioSelectableCard.tsx
rename to e2e/tests/e2e/selectableCardComplexChildren/RadioSelectableCard.tsx
diff --git a/e2e/tests/selectableCardComplexChildren/ToggleSelectableCard.tsx b/e2e/tests/e2e/selectableCardComplexChildren/ToggleSelectableCard.tsx
similarity index 100%
rename from e2e/tests/selectableCardComplexChildren/ToggleSelectableCard.tsx
rename to e2e/tests/e2e/selectableCardComplexChildren/ToggleSelectableCard.tsx
diff --git a/e2e/tests/selectableCardComplexChildren/render.tsx b/e2e/tests/e2e/selectableCardComplexChildren/render.tsx
similarity index 100%
rename from e2e/tests/selectableCardComplexChildren/render.tsx
rename to e2e/tests/e2e/selectableCardComplexChildren/render.tsx
diff --git a/e2e/tests/selectableCardComplexChildren/test.spec.ts b/e2e/tests/e2e/selectableCardComplexChildren/test.spec.ts
similarity index 100%
rename from e2e/tests/selectableCardComplexChildren/test.spec.ts
rename to e2e/tests/e2e/selectableCardComplexChildren/test.spec.ts
diff --git a/e2e/tests/template/render.tsx b/e2e/tests/e2e/template/render.tsx
similarity index 100%
rename from e2e/tests/template/render.tsx
rename to e2e/tests/e2e/template/render.tsx
diff --git a/e2e/tests/template/test.spec.ts b/e2e/tests/e2e/template/test.spec.ts
similarity index 100%
rename from e2e/tests/template/test.spec.ts
rename to e2e/tests/e2e/template/test.spec.ts
diff --git a/e2e/tests/screenshots/ui-components-showcase/render.tsx b/e2e/tests/screenshots/ui-components-showcase/render.tsx
new file mode 100644
index 0000000000..aa67b95378
--- /dev/null
+++ b/e2e/tests/screenshots/ui-components-showcase/render.tsx
@@ -0,0 +1,455 @@
+import {
+ Alert,
+ Avatar,
+ Badge,
+ Button,
+ Card,
+ Checkbox,
+ Chip,
+ DateInput,
+ Drawer,
+ EmptyState,
+ ExpandableCard,
+ Label,
+ Link,
+ List,
+ Loader,
+ Modal,
+ Notice,
+ NumberInput,
+ Pagination,
+ ProgressBar,
+ Radio,
+ RadioGroup,
+ Row,
+ SearchInput,
+ SelectInput,
+ Separator,
+ Skeleton,
+ Slider,
+ Stack,
+ Status,
+ StepList,
+ Stepper,
+ Table,
+ Tabs,
+ Tag,
+ Text,
+ TextArea,
+ TextInput,
+ TimeInput,
+ Toggle,
+ Tooltip,
+} from '@ultraviolet/ui'
+import { useState } from 'react'
+
+const UIComponentsShowcase = () => {
+ const [checkboxChecked, setCheckboxChecked] = useState(false)
+ const [radioValue, setRadioValue] = useState('option1')
+ const [toggleChecked, setToggleChecked] = useState(false)
+ const [sliderValue, setSliderValue] = useState(50)
+ const [selectValue, setSelectValue] = useState('')
+ const [textInputValue, setTextInputValue] = useState('')
+ const [numberValue, setNumberValue] = useState(0)
+ const [dateValue, setDateValue] = useState(null)
+ const [timeValue, setTimeValue] = useState(null)
+ const [activeTab, setActiveTab] = useState('1')
+ const [searchValue, setSearchValue] = useState('')
+ const [expandedCard, setExpandedCard] = useState(null)
+
+ return (
+
+
+ UI Components Showcase
+
+
+ {/* Basic Components */}
+
+
+
+ Basic Components
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Primary
+ Success
+ Warning
+ Danger
+
+
+ Tag 1
+ Tag 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Form Components */}
+
+
+
+ Form Components
+
+
+
+
+
+
+ {}}
+ placeholder="Search..."
+ />
+
+
+
+
+
+
+ date && setTimeValue(date)}
+ />
+
+
+
+
+
+
+ {/* Selection Controls */}
+
+
+
+ Selection Controls
+
+
+
+
+ setCheckboxChecked(!checkboxChecked)}
+ >
+ Checkbox label
+
+
+
+
+
+ setRadioValue(e.target.value)}
+ >
+ {}} />
+ {}} />
+ {}} />
+
+
+
+
+
+ setToggleChecked(!toggleChecked)}
+ label="Toggle"
+ />
+
+
+
+
+
+
+
+
+
+
+ {/* Feedback Components */}
+
+
+
+ Feedback & Status
+
+
+ This is an info alert
+ This is a success alert
+ This is a warning alert
+ This is an error alert
+
+
+
+
+
+ Notice message
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Navigation & Layout */}
+
+
+
+ Navigation & Layout
+
+
+ setActiveTab(String(value))}
+ >
+
+ Tab 1 content
+
+
+ Tab 2 content
+
+
+ Tab 3 content
+
+
+
+
+ Step 1
+ Step 2
+ Step 3
+
+
+
+
+
+
+
+
+ {}} />
+
+
+
+
+ {/* Data Display */}
+
+
+
+ Data Display
+
+
+
+
+
+
+
+ John Doe
+ 28
+ Active
+
+
+ Jane Smith
+ 34
+ Inactive
+
+
+
+
+
+
+
+
+
+ Item 1
+ Description 1
+
+
+ Item 2
+ Description 2
+
+
+ Item 3
+ Description 3
+
+
+
+
+
+
+
+
+
+
+ {/* Interactive Components */}
+
+
+
+ Interactive Components
+
+
+
+
+
+ setExpandedCard(expandedCard === '1' ? null : '1')
+ }
+ header="Expandable Card 1"
+ >
+ This is the content of expandable card 1
+
+
+ setExpandedCard(expandedCard === '2' ? null : '2')
+ }
+ header="Expandable Card 2"
+ >
+ This is the content of expandable card 2
+
+
+
+
+
+
+ Chip 1
+ Chip 2
+
+
+ Click me
+
+
+
+
+
+
+
+
+
+ {/* Modals & Overlays */}
+
+
+
+ Modals & Overlays
+
+
+ Open Modal}>
+
+
+ Modal Title
+
+
+ This is a modal dialog
+
+ {}} />
+
+
+
+ Open Drawer}
+ >
+
+
+ Drawer Title
+
+
+ This is a drawer
+
+ {}} />
+
+
+
+
+
+
+ )
+}
+
+export default UIComponentsShowcase
diff --git a/e2e/tests/screenshots/ui-components-showcase/test.spec.ts b/e2e/tests/screenshots/ui-components-showcase/test.spec.ts
new file mode 100644
index 0000000000..b2083936dc
--- /dev/null
+++ b/e2e/tests/screenshots/ui-components-showcase/test.spec.ts
@@ -0,0 +1,14 @@
+import { expect, test } from '@playwright/test'
+
+test('UI components showcase screenshot', async ({ page, baseURL }) => {
+ await page.goto(`${baseURL}/ui-components-showcase`)
+
+ // Wait for all components to load
+ await page.waitForLoadState('networkidle')
+
+ // Take a full page screenshot
+ await expect(page).toHaveScreenshot('ui-components-showcase-full.png', {
+ fullPage: true,
+ animations: 'disabled',
+ })
+})
diff --git a/e2e/tests/screenshots/ui-components-showcase/test.spec.ts-snapshots/ui-components-showcase-full-screenshots-chromium-darwin.png b/e2e/tests/screenshots/ui-components-showcase/test.spec.ts-snapshots/ui-components-showcase-full-screenshots-chromium-darwin.png
new file mode 100644
index 0000000000..94eb70f888
Binary files /dev/null and b/e2e/tests/screenshots/ui-components-showcase/test.spec.ts-snapshots/ui-components-showcase-full-screenshots-chromium-darwin.png differ
diff --git a/packages/themes/global.d.ts b/packages/themes/global.d.ts
new file mode 100644
index 0000000000..98e1d57c3c
--- /dev/null
+++ b/packages/themes/global.d.ts
@@ -0,0 +1,4 @@
+declare module '@ultraviolet/themes/global' {
+ const content: string
+ export default content
+}
diff --git a/packages/themes/package.json b/packages/themes/package.json
index ba335a4ed9..5e78edbc05 100644
--- a/packages/themes/package.json
+++ b/packages/themes/package.json
@@ -19,8 +19,7 @@
],
"type": "module",
"sideEffects": [
- "**/*.css",
- "**/*.css.ts"
+ "/global"
],
"main": "./dist/index.js",
"module": "./dist/index.js",
@@ -36,7 +35,10 @@
"import": "./dist/themes/console/*/index.js",
"require": "./dist/themes/console/*/index.js"
},
- "./global": "./dist/themes.css",
+ "./global": {
+ "types": "./global.d.ts",
+ "default": "./dist/themes.css"
+ },
"./theme.css": "./dist/themes.css"
},
"publishConfig": {