diff --git a/.changeset/nine-moons-wink.md b/.changeset/nine-moons-wink.md new file mode 100644 index 0000000000..8545cc9586 --- /dev/null +++ b/.changeset/nine-moons-wink.md @@ -0,0 +1,6 @@ +--- +"@ultraviolet/ui": major +--- + +- Remove `Emotion` +- Removed `Breakpoint`: use directly `up` and `down` diff --git a/.storybook/.babelrc b/.storybook/.babelrc index 1bebc8abf6..047386a449 100644 --- a/.storybook/.babelrc +++ b/.storybook/.babelrc @@ -1,14 +1,5 @@ { - "plugins": [ - [ - "@emotion", - { - "sourceMap": false, - "autoLabel": "never", - "labelFormat": "[filename]--[local]" - } - ] - ], + "presets": [ "@babel/preset-typescript", [ @@ -18,8 +9,7 @@ [ "@babel/preset-react", { - "runtime": "automatic", - "importSource": "@emotion/react" + "runtime": "automatic" } ] ] diff --git a/.storybook/components/DocsContainer.tsx b/.storybook/components/DocsContainer.tsx index f9df16b6b3..f49bfe293a 100644 --- a/.storybook/components/DocsContainer.tsx +++ b/.storybook/components/DocsContainer.tsx @@ -1,4 +1,3 @@ -import { Global, ThemeProvider } from '@emotion/react' import type { DocsContainerProps as BaseContainerProps} from '@storybook/addon-docs/blocks'; import { @@ -8,9 +7,10 @@ import { import { consoleLightTheme as lightTheme, ThemeProvider as ThemeProviderUV } from '@ultraviolet/themes' import type { ReactNode } from 'react' import { cloneElement, isValidElement, useState } from 'react' -import { globalStyles } from './globalStyle' import '@ultraviolet/fonts/fonts.css' import { GlobalAlert } from '@ultraviolet/ui' +import "../../packages/themes/dist/themes.css" +import { globalStyleStoryBook } from './globalStyle.css'; type ExtraProps = { /** @@ -66,8 +66,8 @@ const DocsContainer = ({ children, context }: DocsContainerProps) => { return ( - - +
+ {isBeta ? { > A Beta version is available. Please use this version if your dependencies include the Beta release. : null} - {isValidElement(children) ? cloneElement(children, { @@ -88,8 +87,8 @@ const DocsContainer = ({ children, context }: DocsContainerProps) => { }) : children} - - + +
) } diff --git a/.storybook/components/Page.tsx b/.storybook/components/Page.tsx index 127b19a49e..c47ad22560 100644 --- a/.storybook/components/Page.tsx +++ b/.storybook/components/Page.tsx @@ -1,4 +1,3 @@ -import styled from '@emotion/styled' import { linkTo } from '@storybook/addon-links' import { Controls, @@ -9,59 +8,7 @@ import { Title, } from '@storybook/addon-docs/blocks' import { Alert, Stack, Text } from '@ultraviolet/ui' -import background from '../assets/brand-background.png' - -const TitleDecorator = styled.div` - h1 { - color: ${({ theme }) => theme.colors.neutral.text}; - font-size: ${({ theme }) => theme.typography.headingLargeStronger.fontSize}; - font-family: ${({ theme }) => theme.typography.headingLargeStronger.fontFamily}; - font-weight: ${({ theme }) => theme.typography.headingLargeStronger.weight}; - letter-spacing: ${({ theme }) => theme.typography.headingLargeStronger.letterSpacing}; - line-height: ${({ theme }) => theme.typography.headingLargeStronger.lineHeight}; - text-transform: ${({ theme }) => theme.typography.headingLargeStronger.textCase}; - text-decoration: ${({ theme }) => theme.typography.headingLargeStronger.textDecoration}; - padding: ${({ theme }) => theme.space[5]} ${({ theme }) => theme.space[3]}; - border-radius: ${({ theme }) => theme.radii.default}; - background-image: url(${background}); - background-size: cover; - background-position: center; - background-repeat: no-repeat; - width: 100%; - } -` - -const StyledH2 = styled(Text)` - padding-bottom: ${({ theme }) => theme.space[1]}; - margin-bottom: ${({ theme }) => theme.space[2]}; - border-bottom: 2px solid ${({ theme }) => theme.colors.neutral.borderStronger}; -` - -const StoriesDecorator = styled(Stack)` - #stories { - color: ${({ theme }) => theme.colors.neutral.text}; - font-size: ${({ theme }) => theme.typography.headingStrong.fontSize}; - font-family: ${({ theme }) => theme.typography.headingStrong.fontFamily}; - font-weight: ${({ theme }) => theme.typography.headingStrong.weight}; - letter-spacing: ${({ theme }) => theme.typography.headingStrong.letterSpacing}; - line-height: ${({ theme }) => theme.typography.headingStrong.lineHeight}; - text-transform: ${({ theme }) => theme.typography.headingStrong.textCase}; - text-decoration: ${({ theme }) => theme.typography.headingStrong.textDecoration}; - padding-bottom: ${({ theme }) => theme.space[1]}; - border-bottom: 2px solid ${({ theme }) => theme.colors.neutral.borderStronger}; - margin-bottom: ${({ theme }) => theme.space[2]}; - } -` - -const StoriesThemes = styled.div` - .docs-story > div { - padding: 0; - } - - .css-xzp052 .innerZoomElementWrapper > * { - border: 0 !important; - } -` +import { h2Decorator, storiesDecorator, storiesTheme, titleDecorator } from './globalStyle.css' type PageProps = { deprecated?: boolean @@ -78,12 +25,12 @@ const Page = ({ hideArgsTable, experimental, }: PageProps) => ( - +
- +
- </TitleDecorator> + </div> {deprecated ? ( <Alert title="Deprecated component" @@ -107,9 +54,9 @@ const Page = ({ </div> <Stack gap={2}> <Stack> - <StyledH2 as="h2" variant="headingStrong"> + <Text as="h2" className={h2Decorator} variant="headingStrong"> Overview - </StyledH2> + </Text> <Subtitle /> <Description /> </Stack> @@ -117,19 +64,19 @@ const Page = ({ <Primary /> {!hideArgsTable ? ( <> - <StyledH2 as="h2" variant="headingStrong"> + <Text as="h2" className={h2Decorator} variant="headingStrong"> Props - </StyledH2> + </Text> <Controls /> </> ) : null} </div> - <StoriesDecorator> + <Stack className={storiesDecorator}> <Stories /> - </StoriesDecorator> + </Stack> </Stack> </Stack> - </StoriesThemes> + </div> ) export default Page diff --git a/.storybook/components/globalStyle.css.ts b/.storybook/components/globalStyle.css.ts new file mode 100644 index 0000000000..acfbe5a938 --- /dev/null +++ b/.storybook/components/globalStyle.css.ts @@ -0,0 +1,82 @@ +import { consoleLightTheme as theme } from '@ultraviolet/themes' +import { globalStyle, style } from '@vanilla-extract/css' +import background from '../assets/brand-background.png' + +export const globalStyleStoryBook = style({ + fontFamily: "'Inter', sans-serif", + fontSize: 16, + + color: theme.colors.neutral.text +}) + +globalStyle(`${globalStyleStoryBook} p`, { margin: 0 }) + + +globalStyle(`${globalStyleStoryBook} h2, ${globalStyleStoryBook} h3, ${globalStyleStoryBook} h4, ${globalStyleStoryBook} h5, ${globalStyleStoryBook} h6`, { margin: `${theme.space[2]} 0 ${theme.space[1]} 0`, + }) + +globalStyle(`${globalStyleStoryBook} .sb-anchor h1, ${globalStyleStoryBook} .sb-anchor h2, ${globalStyleStoryBook} .sb-anchor h3, ${globalStyleStoryBook} .sb-anchor h4, ${globalStyleStoryBook} .sb-anchor h5, ${globalStyleStoryBook} .sb-anchor h6`, { margin: "inherit" }) + +globalStyle(`${globalStyleStoryBook} body`, { + fontFamily: "'Inter', sans-serif", + fontSize: 16, + fontWeight: 400, + lineHeight: 24, + color: theme.colors.neutral.text + }) + + +globalStyle(`${globalStyleStoryBook} h1, h2, h3, h4, h5, h3`, { + color: theme.colors.neutral.text + }) + +globalStyle(`${globalStyleStoryBook} .toc-list-item::before`, { borderColor: `${theme.colors.primary.border} !important` }) + +globalStyle(`${globalStyleStoryBook} .toc-list-item`, { paddingBottom: "3px !important" }) + +globalStyle(`${globalStyleStoryBook} .toc-list-item.is-active-li>a`, { color: `${theme.colors.primary.text} !important` }) + +export const titleDecorator = style({}) + +globalStyle(`${titleDecorator} > h1`, { + color: theme.colors.neutral.text, + fontSize: theme.typography.headingLargeStronger.fontSize, + fontFamily: theme.typography.headingLargeStronger.fontFamily, + fontWeight: theme.typography.headingLargeStronger.weight, + letterSpacing: theme.typography.headingLargeStronger.letterSpacing, + lineHeight: theme.typography.headingLargeStronger.lineHeight, + textDecoration: theme.typography.headingLargeStronger.textDecoration, + padding: `${theme.space[5]} ${theme.space[3]}`, + borderRadius: theme.radii.default, + backgroundImage: `url(${background})`, + backgroundSize: "cover", + backgroundPosition: "center", + backgroundRepeat: 'no-repeat', + width: "100%", +}) + +export const h2Decorator = style({ + paddingBottom: theme.space[1], + marginBottom: `${theme.space[2]} !important`, + borderBottom: `2px solid ${theme.colors.neutral.borderStronger}` +}) + +export const storiesDecorator = style({}) + +globalStyle(`${storiesDecorator} #stories`, { + color: theme.colors.neutral.text, + fontSize: theme.typography.headingStrong.fontSize, + fontFamily: theme.typography.headingStrong.fontFamily, + fontWeight: theme.typography.headingStrong.weight, + letterSpacing: theme.typography.headingStrong.letterSpacing, + lineHeight: theme.typography.headingStrong.lineHeight, + textDecoration: theme.typography.headingStrong.textDecoration, + paddingBottom: theme.space[1], + borderBottom: `2px solid ${theme.colors.neutral.borderStronger}`, + marginBottom: theme.space[2], +}) +export const storiesTheme = style({}) + +globalStyle(`${storiesTheme} .docs-story > div`, { padding: 0}) + +globalStyle(`${storiesTheme} .css-xzp052 .innerZoomElementWrapper > *`, { border: "0 !important"}) diff --git a/.storybook/components/globalStyle.ts b/.storybook/components/globalStyle.ts deleted file mode 100644 index 221c943b08..0000000000 --- a/.storybook/components/globalStyle.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { css } from '@emotion/react' -import { normalize } from '@ultraviolet/ui' -import {space, colors} from '../../packages/ui/src/theme' - -export const globalStyles = css` - ${normalize()} - - p { - margin: 0; - } - - h1 { - margin: ${space['5']} 0; - } - - h2, h3, h4, h5, h6 { - margin: ${space['2']} 0 ${space['1']} 0; - } - - .sb-anchor h1, .sb-anchor h2, .sb-anchor h3, .sb-anchor h4, .sb-anchor h5, .sb-anchor h6 { - margin: inherit; - } - - body { - font-family: 'Inter', sans-serif; - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: ${colors.neutral.text}; - } - - .toc-list-item::before { - border-color: ${colors.primary.border} !important; - } - - .toc-list-item.is-active-li>a { - color: ${colors.primary.text} !important; - } -` diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 3096cadd61..dba274dc96 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -1,5 +1,3 @@ -import { Global, ThemeProvider } from '@emotion/react' -import { withThemeFromJSXProvider } from '@storybook/addon-themes' import type { Preview, StoryFn } from '@storybook/react-vite' import { themes } from 'storybook/theming' import { @@ -10,9 +8,9 @@ import { } from '@ultraviolet/themes' import DocsContainer from './components/DocsContainer' import Page from './components/Page' -import { globalStyles } from './components/globalStyle' import { dark, light } from './storybookThemes' import '@ultraviolet/fonts/fonts.css' + import { scan } from "react-scan" const BREAKPOINT_ORDER = [ @@ -166,16 +164,7 @@ const decorators = [ </ThemeProviderUI> </> )}, // Storybook is broken without this please refer to this issue: https://github.com/storybookjs/storybook/issues/24625 - withThemeFromJSXProvider({ - themes: { - light: lightTheme, - dark: darkTheme, - darker: darkerTheme, - }, - defaultTheme: 'light', - Provider: ThemeProvider, - GlobalStyles: () => <Global styles={[globalStyles]} />, - }), + withThemeProvider, ] diff --git a/.storybook/vite.config.ts b/.storybook/vite.config.ts index a9dcbe7f54..cbd0e69b05 100644 --- a/.storybook/vite.config.ts +++ b/.storybook/vite.config.ts @@ -48,10 +48,6 @@ export default defineConfig({ svgr({ memo: true, svgo: false }), react({ jsxRuntime: 'automatic', - jsxImportSource: '@emotion/react', - babel: { - plugins: ['@emotion/babel-plugin'], - }, }), vanillaExtractPlugin({}) ], diff --git a/babel.config.json b/babel.config.json index e27d9b78bf..fcf3b2e696 100644 --- a/babel.config.json +++ b/babel.config.json @@ -1,5 +1,4 @@ { - "plugins": ["@emotion"], "presets": [ "@babel/preset-typescript", [ @@ -9,8 +8,7 @@ [ "@babel/preset-react", { - "runtime": "automatic", - "importSource": "@emotion/react" + "runtime": "automatic" } ] ] diff --git a/e2e/tsconfig.json b/e2e/tsconfig.json index 33e8472d87..fe13c13e8b 100644 --- a/e2e/tsconfig.json +++ b/e2e/tsconfig.json @@ -5,7 +5,6 @@ "target": "esnext", "module": "esnext", "jsx": "preserve", - "jsxImportSource": "@emotion/react", "allowImportingTsExtensions": true, "forceConsistentCasingInFileNames": true, "noPropertyAccessFromIndexSignature": false, @@ -14,6 +13,6 @@ "skipLibCheck": true, "types": ["vite/client"] }, - "include": ["global.d.ts", "emotion.d.ts", "**/*.ts", "**/*.tsx"], + "include": ["global.d.ts", "**/*.ts", "**/*.tsx"], "exclude": ["node_modules", "coverage", "dist"] } diff --git a/e2e/vite.config.ts b/e2e/vite.config.ts index 16a2f2e488..5c746232d1 100644 --- a/e2e/vite.config.ts +++ b/e2e/vite.config.ts @@ -7,14 +7,7 @@ export default defineConfig({ external: ['fsevents'], }, }, - plugins: [ - react({ - babel: { - plugins: ['@emotion/babel-plugin'], - }, - jsxImportSource: '@emotion/react', - }), - ], + plugins: [react()], server: { // Sends all requests to index.html if file not found fs: { diff --git a/eslint.config.mjs b/eslint.config.mjs index 6aa0865923..dfe1f6800f 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -3,7 +3,6 @@ import path from 'node:path' import { fileURLToPath } from 'node:url' import babelParser from '@babel/eslint-parser' -import scwEmotion from '@scaleway/eslint-config-react/emotion' import scwJavascript from '@scaleway/eslint-config-react/javascript' import scwTypescript from '@scaleway/eslint-config-react/typescript' import oxlint from 'eslint-plugin-oxlint' @@ -76,7 +75,7 @@ export default [ }, }, }, - ...[...scwJavascript, ...scwEmotion].map(config => ({ + ...scwJavascript.map(config => ({ ...config, languageOptions: { parser: babelParser, @@ -98,7 +97,7 @@ export default [ }, }, }, - ...[...scwTypescript, ...scwEmotion].map(config => ({ + ...scwTypescript.map(config => ({ ...config, files: ['**/*.{ts,tsx}'], rules: { diff --git a/examples/next-app-router/emotion.d.ts b/examples/next-app-router/emotion.d.ts deleted file mode 100644 index f44242cfea..0000000000 --- a/examples/next-app-router/emotion.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -import '@emotion/react' -import type { consoleLightTheme } from '@ultraviolet/themes' - -type CustomTheme = typeof consoleLightTheme - -declare module '@emotion/react' { - // eslint-disable-next-line @typescript-eslint/consistent-type-definitions, @typescript-eslint/no-empty-interface - export interface Theme extends CustomTheme {} -} diff --git a/examples/next-app-router/tsconfig.json b/examples/next-app-router/tsconfig.json index 532910fb90..232cff3c44 100644 --- a/examples/next-app-router/tsconfig.json +++ b/examples/next-app-router/tsconfig.json @@ -27,7 +27,6 @@ "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", - "emotion.d.ts" ], "exclude": ["node_modules"] } diff --git a/examples/next/src/components/Header.tsx b/examples/next/src/components/Header.tsx index 6dbd94371e..d07acbf67a 100644 --- a/examples/next/src/components/Header.tsx +++ b/examples/next/src/components/Header.tsx @@ -1,6 +1,6 @@ import { MoonIcon, SunIcon } from '@ultraviolet/icons' import { useTheme } from '@ultraviolet/themes' -import { Breakpoint, Toggle } from '@ultraviolet/ui' +import { Toggle } from '@ultraviolet/ui' import styles from '../../styles/component.module.scss' import GithubAndDocumentationButtons from './GithubAndDocumentationButtons' import Logo from './Logo' @@ -15,9 +15,7 @@ const TopBar = ({ setTheme }: { setTheme: (theme: Themes) => void }) => { <div className={styles.headerRow}> <Logo /> <div className={styles.horizontalStack}> - <Breakpoint up="medium"> - <GithubAndDocumentationButtons /> - </Breakpoint> + <GithubAndDocumentationButtons /> <SunIcon size="small" /> <Toggle checked={theme === 'dark'} diff --git a/examples/next/src/pages/advanced/Introduction.tsx b/examples/next/src/pages/advanced/Introduction.tsx index a3d05395de..894fc939d9 100644 --- a/examples/next/src/pages/advanced/Introduction.tsx +++ b/examples/next/src/pages/advanced/Introduction.tsx @@ -1,4 +1,4 @@ -import { Breakpoint, Stack, Text } from '@ultraviolet/ui' +import { Stack, Text } from '@ultraviolet/ui' import Image from 'next/image' import styles from '../../../styles/advanced.module.scss' import swA11y from '../../assets/icons/icon-scaleway-a11y.svg' @@ -17,9 +17,7 @@ const Introduction = () => ( gap={2} justifyContent="space-between" > - <Breakpoint down="medium"> - <GithubAndDocumentationButtons /> - </Breakpoint> + <GithubAndDocumentationButtons /> <Stack> <Text as="h1" sentiment="primary" variant="headingLarge"> Scaleway <b>UI</b> diff --git a/global.d.ts b/global.d.ts index 21e49791c4..ca1ee35e7b 100644 --- a/global.d.ts +++ b/global.d.ts @@ -1,5 +1,3 @@ -/// <reference types="@emotion/react/types/css-prop" /> - declare module '*.svg' { import type { FunctionComponent, SVGProps } from 'react' diff --git a/package.json b/package.json index bf259a7ab1..f30653d83c 100644 --- a/package.json +++ b/package.json @@ -104,12 +104,6 @@ "@changesets/cli": "2.29.7", "@commitlint/cli": "20.1.0", "@commitlint/config-conventional": "20.0.0", - "@emotion/babel-plugin": "11.13.5", - "@emotion/cache": "11.14.0", - "@emotion/eslint-plugin": "11.12.0", - "@emotion/jest": "11.13.0", - "@emotion/react": "11.14.0", - "@emotion/styled": "11.14.1", "@eslint/compat": "1.4.1", "@eslint/eslintrc": "3.3.1", "@manypkg/cli": "0.25.1", @@ -137,6 +131,7 @@ "@ultraviolet/fonts": "workspace:*", "@ultraviolet/themes": "workspace:*", "@ultraviolet/ui": "workspace:*", + "@vanilla-extract/css": "1.17.4", "@vanilla-extract/vite-plugin": "5.1.1", "@vitejs/plugin-react": "5.0.4", "@vitest/coverage-istanbul": "3.2.4", diff --git a/packages/themes/package.json b/packages/themes/package.json index 1dbb12aae6..9f004a2fdb 100644 --- a/packages/themes/package.json +++ b/packages/themes/package.json @@ -53,7 +53,8 @@ "require": "./dist/themes/console/*/index.cjs", "import": "./dist/themes/console/*/index.js" }, - "./global": "./dist/themes.css" + "./global": "./dist/themes.css", + "./theme.css": "./dist/themes.css" }, "peerDependencies": { "react": "18.x || 19.x", diff --git a/packages/themes/src/vanilla/globalStyle.css b/packages/themes/src/vanilla/globalStyle.css index 4f52698834..2ec488c87d 100644 --- a/packages/themes/src/vanilla/globalStyle.css +++ b/packages/themes/src/vanilla/globalStyle.css @@ -1,156 +1,28 @@ -img, -canvas, -iframe, -video, -select, -textarea { - max-width: 100%; -} - -p, -h1, -h2, -h3, -h4, -h5, -h6 { - margin: 0; -} - -*, -::after, -::before { - box-sizing: border-box -} - -html { - -webkit-text-size-adjust: 100%; - -moz-tab-size: 4; - tab-size: 4; - font-size: 16px; - line-height: 1.5; - -webkit-tap-highlight-color: transparent; - margin: 0; -} - -body { - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - margin: 0; - font-family: system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji' -} - -hr { - height: 0; - color: inherit -} - -abbr[title] { - text-decoration: underline dotted -} - -b, -strong { - font-weight: bolder -} - -code, -kbd, -pre, -samp { - font-family: ui-monospace, SFMono-Regular, Consolas, 'Liberation Mono', Menlo, monospace; - font-size: 1em -} - -small { - font-size: 80% -} - -sub, -sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline -} - -sub { - bottom: -.25em -} - -sup { - top: -.5em -} - -table { - text-indent: 0; - border-color: inherit -} - -button, -input, -optgroup, -select, -textarea { - font-family: inherit; - font-size: 100%; - line-height: 1.15; - margin: 0 -} - -button, -select { - text-transform: none -} - -[type=button], -[type=reset], -[type=submit], -button { - -webkit-appearance: button -} - -::-moz-focus-inner { - border-style: none; - padding: 0 -} - -:-moz-focusring { - outline: 1px dotted ButtonText -} - -:-moz-ui-invalid { - box-shadow: none -} - -legend { - padding: 0 -} - -progress { - vertical-align: baseline -} - -::-webkit-inner-spin-button, -::-webkit-outer-spin-button { - height: auto -} - -[type=search] { - -webkit-appearance: textfield; - outline-offset: -2px -} - -::-webkit-search-decoration { - -webkit-appearance: none -} - -::-webkit-file-upload-button { - -webkit-appearance: button; - font: inherit -} - -summary { - display: list-item -} \ No newline at end of file +*,::after,::before{box-sizing:border-box}html{-moz-tab-size:4;tab-size:4}html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}body{font-family:system-ui,-apple-system,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji'}hr{height:0;color:inherit}abbr[title]{text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Consolas,'Liberation Mono',Menlo,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}::-moz-focus-inner{border-style:none;padding:0}:-moz-focusring{outline:1px dotted ButtonText}:-moz-ui-invalid{box-shadow:none}legend{padding:0}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item} + + html { + font-size: 16px; + line-height: 1.5; + -webkit-tap-highlight-color: transparent; + margin: 0; + } + + body { + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + } + + img, + canvas, + iframe, + video, + select, + textarea { + max-width: 100%; + } + + p, h1, h2, h3, h4, h5, h6 { + margin: 0; + } + \ No newline at end of file diff --git a/packages/ui/package.json b/packages/ui/package.json index 212ebbe819..f989b581bb 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -71,15 +71,11 @@ } ], "peerDependencies": { - "@emotion/react": "11.14.0", - "@emotion/styled": "11.14.1", "react": "18.x || 19.x", "react-dom": "18.x || 19.x" }, "devDependencies": { "@babel/core": "7.28.5", - "@emotion/react": "11.14.0", - "@emotion/styled": "11.14.1", "@types/react": "19.2.2", "@types/react-dom": "19.2.2", "@utils/test": "workspace:*", @@ -88,7 +84,6 @@ "react-dom": "19.2.0" }, "dependencies": { - "@emotion/serialize": "1.3.3", "@nivo/bar": "0.89.1", "@nivo/core": "0.89.1", "@nivo/line": "0.89.1", diff --git a/packages/ui/src/__stories__/Properties/Properties.tsx b/packages/ui/src/__stories__/Properties/Properties.tsx index 0575fb92d1..04aa67bf15 100644 --- a/packages/ui/src/__stories__/Properties/Properties.tsx +++ b/packages/ui/src/__stories__/Properties/Properties.tsx @@ -1,14 +1,9 @@ -import styled from '@emotion/styled' import type { ComponentType } from 'react' import * as components from '../../components' import { Stack } from '../../components/Stack' import { Table } from '../../components/Table' import { Text } from '../../components/Text' -const StyledTableRow = styled(Table.Row)` - vertical-align: top; -` - type PropertyType = { defaultValue: { value: string @@ -233,7 +228,11 @@ const Properties = () => { ] return ( - <StyledTableRow id={property} key={property}> + <Table.Row + id={property} + key={property} + style={{ verticalAlign: 'top' }} + > <Table.Cell> <Text as="span" variant="bodyStrong"> {property} @@ -264,7 +263,7 @@ const Properties = () => { ].components.join(', ')} </Text> </Table.Cell> - </StyledTableRow> + </Table.Row> ) }, )} diff --git a/packages/ui/src/__stories__/Testing.mdx b/packages/ui/src/__stories__/Testing.mdx index c638e5f937..8d072616e3 100644 --- a/packages/ui/src/__stories__/Testing.mdx +++ b/packages/ui/src/__stories__/Testing.mdx @@ -34,6 +34,8 @@ As stated in [`@testing-library/react`](https://testing-library.com/docs/dom-tes This will wrap the provided node with a ThemeProvider and render it + + This is useful when you need to dig through a rendered node ```jsx diff --git a/packages/ui/src/__stories__/Tools/ThemeGenerator/FormContent/index.tsx b/packages/ui/src/__stories__/Tools/ThemeGenerator/FormContent/index.tsx index e27aa78743..7c1f618aa9 100644 --- a/packages/ui/src/__stories__/Tools/ThemeGenerator/FormContent/index.tsx +++ b/packages/ui/src/__stories__/Tools/ThemeGenerator/FormContent/index.tsx @@ -1,4 +1,3 @@ -import styled from '@emotion/styled' import { CheckIcon, CloseIcon, RestoreIcon } from '@ultraviolet/icons' import { useState } from 'react' import { @@ -10,16 +9,7 @@ import { } from '../../../../../../form/src' import { Button, Row, Stack, Text, Tooltip } from '../../../../components' import { hexadecimalColorRegex, INITIAL_VALUES } from '../contants' - -const CapitalizeText = styled(Text)` - &::first-letter { - text-transform: capitalize; - } -` - -const StyledRow = styled(Row)` - width: 100%; -` +import { capitalizeText, row } from './style.css' export const FormContent = () => { const [confirmResetForm, setConfirmResetForm] = useState(false) @@ -33,13 +23,14 @@ export const FormContent = () => { <Stack gap={6}> <Stack direction="row" gap={1}> <Stack flex={1} gap={1}> - <CapitalizeText + <Text as="label" + className={capitalizeText} htmlFor="sentiment_neutral" variant="bodyStrong" > Neutral sentiment name - </CapitalizeText> + </Text> <Tooltip text="Neutral sentiment name cannot be changed as it is essential for the theme to work."> <Stack flex={1}> <TextInputField @@ -53,13 +44,14 @@ export const FormContent = () => { </Tooltip> </Stack> <Stack flex={1} gap={1}> - <CapitalizeText + <Text as="label" + className={capitalizeText} htmlFor="sentiment_neutral_value" variant="bodyStrong" > Neutral sentiment value - </CapitalizeText> + </Text> <Tooltip text="Neutral sentiment value cannot be changed as it is essential for the theme to work."> <Stack flex={1}> <TextInputField @@ -86,8 +78,9 @@ export const FormContent = () => { return ( <Stack direction="row" gap={1} key={field.id}> <Stack flex={1} gap={1}> - <CapitalizeText + <Text as="label" + className={capitalizeText} htmlFor={`sentiments.${index}.key`} variant="bodyStrong" > @@ -96,7 +89,7 @@ export const FormContent = () => { : `Additional sentiment ${ index - countRequiredSentiments + 1 } name`} - </CapitalizeText> + </Text> <Tooltip text={ isRequiredSentiment @@ -116,8 +109,9 @@ export const FormContent = () => { </Tooltip> </Stack> <Stack flex={1} gap={1}> - <CapitalizeText + <Text as="label" + className={capitalizeText} htmlFor={`sentiments.${index}.value`} variant="bodyStrong" > @@ -126,22 +120,16 @@ export const FormContent = () => { : `Additional sentiment ${ index - countRequiredSentiments + 1 } value`} - </CapitalizeText> + </Text> <Stack alignItems="center" direction="row" gap={1}> - <StyledRow gap={1} templateColumns="9fr 1fr"> - <TextInputField - id={`sentiments.${index}.value`} - name={`sentiments.${index}.value`} - placeholder="#FFFFFF" - regex={[hexadecimalColorRegex]} - /> + <Row className={row} gap={1} templateColumns="9fr 1fr"> <TextInputField id={`sentiments.${index}.value`} name={`sentiments.${index}.value`} placeholder="#FFFFFF" regex={[hexadecimalColorRegex]} /> - </StyledRow> + </Row> {!isRequiredSentiment ? ( <Button onClick={() => remove(index)} diff --git a/packages/ui/src/__stories__/Tools/ThemeGenerator/FormContent/style.css.ts b/packages/ui/src/__stories__/Tools/ThemeGenerator/FormContent/style.css.ts new file mode 100644 index 0000000000..51a81e6ea8 --- /dev/null +++ b/packages/ui/src/__stories__/Tools/ThemeGenerator/FormContent/style.css.ts @@ -0,0 +1,11 @@ +import { style } from '@vanilla-extract/css' + +export const capitalizeText = style({ + selectors: { + '&::first-letter': { + textTransform: 'capitalize', + }, + }, +}) + +export const row = style({ width: '100%' }) diff --git a/packages/ui/src/__stories__/Tools/ThemeGenerator/ThemeResult/CodeIntegration.tsx b/packages/ui/src/__stories__/Tools/ThemeGenerator/ThemeResult/CodeIntegration.tsx index 5f5fb741ad..bcd29fa9be 100644 --- a/packages/ui/src/__stories__/Tools/ThemeGenerator/ThemeResult/CodeIntegration.tsx +++ b/packages/ui/src/__stories__/Tools/ThemeGenerator/ThemeResult/CodeIntegration.tsx @@ -1,27 +1,21 @@ -import styled from '@emotion/styled' import { useState } from 'react' import { Snippet, Stack, Tabs, Text } from '../../../../components' import type { UltravioletUITheme } from '../../../../theme' +import { snippetResult } from './styles.css' type CodeIntegrationProps = { theme: UltravioletUITheme } -const StyledSnippet = styled(Snippet)` - pre { - padding: ${({ theme }) => theme.space['2']}; - } -` - const reactCode = (theme: string) => ` -import { Global, ThemeProvider, css } from '@emotion/react' import { Button, normalize } from '@ultraviolet/ui' +import { ThemeProvider } from "@ultraviolet/themes" +import "@ultraviolet/themes/global" const THEME = ${theme} const App = () => ( <ThemeProvider theme={THEME}> - <Global styles={css\`\${normalize()}\`} /> <Button onClick={() => console.log('clicked')}> Click Me </Button> @@ -48,9 +42,9 @@ export const CodeIntegration = ({ theme }: CodeIntegrationProps) => { <Tabs.Tab value={1}>JSON</Tabs.Tab> <Tabs.Tab value={2}>React</Tabs.Tab> </Tabs> - <StyledSnippet prefix="lines"> + <Snippet className={snippetResult} prefix="lines"> {tabState === 1 ? formattedTheme : reactCode(formattedTheme)} - </StyledSnippet> + </Snippet> </Stack> </Stack> ) diff --git a/packages/ui/src/__stories__/Tools/ThemeGenerator/ThemeResult/Demo.tsx b/packages/ui/src/__stories__/Tools/ThemeGenerator/ThemeResult/Demo.tsx index 67152c93cf..6fb8c411d2 100644 --- a/packages/ui/src/__stories__/Tools/ThemeGenerator/ThemeResult/Demo.tsx +++ b/packages/ui/src/__stories__/Tools/ThemeGenerator/ThemeResult/Demo.tsx @@ -1,4 +1,3 @@ -import styled from '@emotion/styled' import type { ChangeEvent } from 'react' import { useState } from 'react' import { @@ -27,25 +26,12 @@ import { Text, Toggle, } from '../../../../components' - -const StyledStepper = styled(Stepper)` - padding: 0 ${({ theme }) => theme.space['2']}; -` - -const StyledStepList = styled(StepList)` - margin: 0; -` - -const StyledStack = styled(Stack)` - gap: 6px; // This has to be custom because we need both row to be same size and this value doesn't exists in theme -` - -const Container = styled.div` - background: ${({ theme }) => theme.colors.neutral.background}; - box-shadow: ${({ theme }) => theme.shadows.hoverNeutral}; - border-radius: ${({ theme }) => theme.radii.large}; - padding: ${({ theme }) => theme.space['4']}; -` +import { + themeGeneratorContainer, + themeGeneratorStack, + themeGeneratorStepList, + themeGeneratorStepper, +} from './styles.css' export const Demo = () => { const [tabState, setTabState] = useState<number | string>(1) @@ -57,7 +43,7 @@ export const Demo = () => { const [selectableCardState, setSelectableCardState] = useState('option-1') return ( - <Container> + <div className={themeGeneratorContainer}> <Row gap={2} templateColumns="1fr 1fr"> <Stack gap={2}> <Tabs @@ -111,11 +97,11 @@ export const Demo = () => { </Row> </Stack> </Card> - <StyledStepper selected={1}> + <Stepper className={themeGeneratorStepper} selected={1}> <span>Initialize</span> <span>Create</span> <span>Done</span> - </StyledStepper> + </Stepper> <Stack direction="row" gap={1}> <Badge sentiment="neutral">UV-UI</Badge> <Badge sentiment="primary">UV-CORE</Badge> @@ -135,7 +121,7 @@ export const Demo = () => { /> </Card> <Card> - <StyledStepList> + <StepList className={themeGeneratorStepList}> <StepList.Item bulletContent={<CheckIcon />} sentiment="success" @@ -150,7 +136,7 @@ export const Demo = () => { > You have 10 days of trial </StepList.Item> - </StyledStepList> + </StepList> </Card> </Stack> <Stack gap={1}> @@ -178,14 +164,14 @@ export const Demo = () => { > <Stack alignItems="center" direction="row" gap={2}> <Avatar shape="circle" text="MA" variant="text" /> - <StyledStack> + <Stack className={themeGeneratorStack}> <Text as="span" sentiment="primary" variant="bodySmall"> Review from Marc - 2 days ago </Text> <Text as="span" variant="body"> Ultraviolet is the best UI library I... </Text> - </StyledStack> + </Stack> </Stack> <Button sentiment="neutral" size="small" variant="ghost"> <ArrowRightIcon /> @@ -249,6 +235,6 @@ export const Demo = () => { </Stack> </Stack> </Row> - </Container> + </div> ) } diff --git a/packages/ui/src/__stories__/Tools/ThemeGenerator/ThemeResult/index.tsx b/packages/ui/src/__stories__/Tools/ThemeGenerator/ThemeResult/index.tsx index d45a961c6b..cb136c33c9 100644 --- a/packages/ui/src/__stories__/Tools/ThemeGenerator/ThemeResult/index.tsx +++ b/packages/ui/src/__stories__/Tools/ThemeGenerator/ThemeResult/index.tsx @@ -1,19 +1,12 @@ -import { ThemeProvider } from '@emotion/react' -import styled from '@emotion/styled' import { ArrowLeftIcon, EyeIcon, EyeOffIcon } from '@ultraviolet/icons' +import { ThemeProvider } from '@ultraviolet/themes' import { useCallback, useState } from 'react' import { Button, Row, Stack, Text } from '../../../../components' import type { UltravioletUITheme } from '../../../../theme' import consoleLightTheme from '../../../../theme' -import { normalize } from '../../../../utils' import { CodeIntegration } from './CodeIntegration' import { Demo } from './Demo' // For some reason Global doesn't work here this is the workaround I found -// For some reason Global doesn't work here this is the workaround I found -const Container = styled.div` - ${normalize()} -` - type ThemeResultProps = { theme: UltravioletUITheme setTheme: (theme: UltravioletUITheme) => void @@ -72,9 +65,7 @@ export const ThemeResult = ({ </Row> <Stack gap={4}> <ThemeProvider theme={theme}> - <Container> - <Demo /> - </Container> + <Demo /> </ThemeProvider> <CodeIntegration theme={generatedPalette} /> </Stack> diff --git a/packages/ui/src/__stories__/Tools/ThemeGenerator/ThemeResult/styles.css.ts b/packages/ui/src/__stories__/Tools/ThemeGenerator/ThemeResult/styles.css.ts new file mode 100644 index 0000000000..7e7df5459e --- /dev/null +++ b/packages/ui/src/__stories__/Tools/ThemeGenerator/ThemeResult/styles.css.ts @@ -0,0 +1,23 @@ +import { theme } from '@ultraviolet/themes' +import { globalStyle, style } from '@vanilla-extract/css' + +export const snippetResult = style({}) + +globalStyle(`${snippetResult} pre`, { + padding: theme.space[2], +}) + +export const themeGeneratorStepper = style({ + padding: `0 ${theme.space[2]}`, +}) + +export const themeGeneratorStepList = style({ margin: 0 }) + +export const themeGeneratorStack = style({ gap: 6 }) + +export const themeGeneratorContainer = style({ + background: theme.colors.neutral.background, + boxShadow: theme.shadows.hoverNeutral, + borderRadius: theme.radii.large, + padding: theme.space[4], +}) diff --git a/packages/ui/src/__stories__/assets/screen-shot-example.png b/packages/ui/src/__stories__/assets/screen-shot-example.png deleted file mode 100644 index b32744372d..0000000000 Binary files a/packages/ui/src/__stories__/assets/screen-shot-example.png and /dev/null differ diff --git a/packages/ui/src/__stories__/components/Colors.tsx b/packages/ui/src/__stories__/components/Colors.tsx index 2c6819c213..d9e8688618 100644 --- a/packages/ui/src/__stories__/components/Colors.tsx +++ b/packages/ui/src/__stories__/components/Colors.tsx @@ -1,5 +1,5 @@ -import styled from '@emotion/styled' import { useTheme } from '@ultraviolet/themes' +import { assignInlineVars } from '@vanilla-extract/dynamic' import { Row } from '../../components' import { Card } from '../../components/Card' import { Separator } from '../../components/Separator' @@ -7,38 +7,16 @@ import { Stack } from '../../components/Stack' import { Text } from '../../components/Text' import type lightTheme from '../../theme' import type { Color } from '../../theme' +import { + capitalizedText, + card, + computedBackground, + noMarginText, + paddingCard, + separator, +} from './styles.css' import ThemeWrapper from './ThemeWrapper' -const StyledSeparator = styled(Separator)` - margin: ${({ theme }) => `${theme.space['3']} 0`}; -` - -const CapitalizedText = styled(Text)` - text-transform: capitalize; -` - -const NoMarginText = styled(Text)` - margin: 0; -` - -const StyledCard = styled(Card, { - shouldForwardProp: prop => - !['sentiment', 'context', 'color', 'padding'].includes(prop), -})<{ - sentiment?: Color - color?: string - context: keyof (typeof lightTheme)['colors'][Color] - padding?: string -}>` - align-items: center; - background: ${({ sentiment, context, theme, color }) => - sentiment ? theme.colors[sentiment][context] : color}; - display: flex; - justify-content: space-between; - padding: ${({ padding }) => padding ?? '8px'}; - width: 100%; -` - type AvailableContexts = keyof (typeof lightTheme)['colors'][Color] const Colors = () => { @@ -64,9 +42,13 @@ const Colors = () => { return ( <Stack gap={1} key={sentiment}> - <CapitalizedText as="h3" variant="headingSmallStrong"> + <Text + as="h3" + className={capitalizedText} + variant="headingSmallStrong" + > {sentiment} - </CapitalizedText> + </Text> <Row gap={2} templateColumns="repeat(3, 1fr)"> <Stack direction="column" gap={2}> {colorContextKeys @@ -86,13 +68,16 @@ const Colors = () => { </Text> </Stack> - <StyledCard - context={context} + <Card + className={`${card} ${paddingCard.default}`} key={context} - sentiment={sentiment} + style={assignInlineVars({ + [computedBackground]: + theme.colors[sentiment][context], + })} > {' '} - </StyledCard> + </Card> </Stack> ))} </Stack> @@ -113,9 +98,15 @@ const Colors = () => { {theme.colors[sentiment][context]} </Text> </Stack> - <StyledCard context={context} sentiment={sentiment}> + <Card + className={`${card} ${paddingCard.default}`} + style={assignInlineVars({ + [computedBackground]: + theme.colors[sentiment][context], + })} + > {' '} - </StyledCard> + </Card> </Stack> ))} </Stack> @@ -136,14 +127,20 @@ const Colors = () => { {theme.colors[sentiment][context]} </Text> </Stack> - <StyledCard context={context} sentiment={sentiment}> + <Card + className={`${card} ${paddingCard.default}`} + style={assignInlineVars({ + [computedBackground]: + theme.colors[sentiment][context], + })} + > {' '} - </StyledCard> + </Card> </Stack> ))} </Stack> </Row> - <StyledSeparator /> + <Separator className={separator} /> </Stack> ) })} @@ -171,9 +168,14 @@ const Colors = () => { {dataColors[data]} </Text> </Stack> - <StyledCard color={dataColors[data]} context="background"> + <Card + className={`${card} ${paddingCard.default}`} + style={assignInlineVars({ + [computedBackground]: dataColors[data], + })} + > {' '} - </StyledCard> + </Card> </Stack> ), )} @@ -208,29 +210,36 @@ const Colors = () => { gradientBackgroundColors[ type as keyof typeof gradientBackgroundColors ], - ).map(background => ( - <Stack key={background}> - <Stack - alignItems="center" - direction="row" - justifyContent="space-between" - > - <Text as="p" variant="body"> - {background} - </Text> + ).map(background => { + // @ts-expect-error can't infer properly + const gradient = gradientBackgroundColors[type][ + background + ].replace(/;$/, '') + + return ( + <Stack key={background}> + <Stack + alignItems="center" + direction="row" + justifyContent="space-between" + > + <Text as="p" variant="body"> + {background} + </Text> + </Stack> + <Card + className={`${card} ${paddingCard.large}`} + style={{ + ...assignInlineVars({ + [computedBackground]: gradient as string, + }), + }} + > + {' '} + </Card> </Stack> - <StyledCard - color={ - // @ts-expect-error can't infer properly - gradientBackgroundColors[type][background] - } - context="background" - padding="32px" - > - {' '} - </StyledCard> - </Stack> - ))} + ) + })} </Row> </Stack> ))} @@ -249,9 +258,13 @@ const Colors = () => { {Object.keys(iconColors[type as keyof typeof iconColors]).map( sentiment => ( <Stack direction="column" key={sentiment}> - <NoMarginText as="h4" variant="bodyStrong"> + <Text + as="h4" + className={noMarginText} + variant="bodyStrong" + > {sentiment} - </NoMarginText> + </Text> <Row gap={2} templateColumns="repeat(3, 1fr)"> {Object.keys( // @ts-expect-error can't infer properly @@ -264,26 +277,30 @@ const Colors = () => { direction="row" justifyContent="space-between" > - <NoMarginText as="p" variant="body"> + <Text + as="p" + className={noMarginText} + variant="body" + > {value} - </NoMarginText> + </Text> <Text as="small" variant="caption"> { // @ts-expect-error can't infer properly - iconColors[type][sentiment][value] } </Text> </Stack> - <StyledCard - color={ - // @ts-expect-error can't infer properly - iconColors[type][sentiment][value] - } - context="background" + <Card + className={`${card} ${paddingCard.default}`} + style={assignInlineVars({ + [computedBackground]: + // @ts-expect-error can't infer properly + iconColors[type][sentiment][value], + })} > {' '} - </StyledCard> + </Card> </Stack> ))} </Row> diff --git a/packages/ui/src/__stories__/components/ThemeWrapper.tsx b/packages/ui/src/__stories__/components/ThemeWrapper.tsx index 83843b028c..5b854d776c 100644 --- a/packages/ui/src/__stories__/components/ThemeWrapper.tsx +++ b/packages/ui/src/__stories__/components/ThemeWrapper.tsx @@ -1,13 +1,9 @@ -import { Global, ThemeProvider } from '@emotion/react' +import { ThemeProvider } from '@ultraviolet/themes' import type { ReactNode } from 'react' -import { globalStyles } from '../../../../../.storybook/components/globalStyle' import lightTheme from '../../theme' const ThemeWrapper = ({ children }: { children: ReactNode }) => ( - <ThemeProvider theme={lightTheme}> - <Global styles={[globalStyles]} /> - {children} - </ThemeProvider> + <ThemeProvider theme={lightTheme}>{children}</ThemeProvider> ) export default ThemeWrapper diff --git a/packages/ui/src/__stories__/components/styles.css.ts b/packages/ui/src/__stories__/components/styles.css.ts new file mode 100644 index 0000000000..738eaec97c --- /dev/null +++ b/packages/ui/src/__stories__/components/styles.css.ts @@ -0,0 +1,26 @@ +import { theme } from '@ultraviolet/themes' +import { createVar, style, styleVariants } from '@vanilla-extract/css' + +export const computedBackground = createVar() +export const separator = style({ + margin: `${theme.space[3]} 0`, +}) + +export const capitalizedText = style({ + textTransform: 'capitalize', +}) + +export const noMarginText = style({ margin: 0 }) + +export const card = style({ + alignItems: 'center', + display: 'flex', + justifyContent: 'space-between', + width: '100%', + padding: 8, + background: computedBackground, +}) +export const paddingCard = styleVariants({ + default: { padding: 8 }, + large: { padding: 32 }, +}) diff --git a/packages/ui/src/__stories__/theme/colors.mdx b/packages/ui/src/__stories__/theme/colors.mdx index b719e6b292..bf48e9a472 100644 --- a/packages/ui/src/__stories__/theme/colors.mdx +++ b/packages/ui/src/__stories__/theme/colors.mdx @@ -14,7 +14,7 @@ to your Theme Provider. You will need to pass an object with the same structure as the [default theme](https://github.com/scaleway/ultraviolet/blob/main/src/theme/tokens/light.ts), but with your own colors. ```tsx -import { ThemeProvider } from '@emotion/react' +import { ThemeProvider } from '@ultraviolet/themes' import { Badge, extendTheme } from '@ultraviolet/ui' function App() { diff --git a/packages/ui/src/__stories__/theme/darkMode.mdx b/packages/ui/src/__stories__/theme/darkMode.mdx index 7f712eba12..e47fdf5e5b 100644 --- a/packages/ui/src/__stories__/theme/darkMode.mdx +++ b/packages/ui/src/__stories__/theme/darkMode.mdx @@ -12,7 +12,7 @@ You can enable easily switch between light and dark mode by passing `theme` or ` Example: ```tsx -import { ThemeProvider } from '@emotion/react' +import { ThemeProvider } from '@ultraviolet/themes' import { theme, darkTheme, Button, Text } from '@ultraviolet/ui' import { useState } from 'react' diff --git a/packages/ui/src/__stories__/theme/shadows.mdx b/packages/ui/src/__stories__/theme/shadows.mdx index ddb8371e45..f3ef0d5a6f 100644 --- a/packages/ui/src/__stories__/theme/shadows.mdx +++ b/packages/ui/src/__stories__/theme/shadows.mdx @@ -12,7 +12,7 @@ You may also want to customize your shadows. To do that you need to create your You will need to pass an object with the same structure as the [default theme](https://github.com/scaleway/ultraviolet/blob/main/src/theme/tokens/light.ts), but with your own typography. ```tsx -import { ThemeProvider } from '@emotion/react' +import { ThemeProvider } from '@ultraviolet/themes' import { Tooltip, extendTheme } from '@ultraviolet/ui' function App() { diff --git a/packages/ui/src/__stories__/theme/spaces.mdx b/packages/ui/src/__stories__/theme/spaces.mdx index 8e190e01d4..3726a1fd6a 100644 --- a/packages/ui/src/__stories__/theme/spaces.mdx +++ b/packages/ui/src/__stories__/theme/spaces.mdx @@ -71,7 +71,7 @@ const MyComponent = styled.div` You can customize the space and sizing by passing a custom theme to the `ThemeProvider`: ```tsx -import { ThemeProvider } from '@emotion/react' +import { ThemeProvider } from '@ultraviolet/themes' import { Button, extendTheme } from '@ultraviolet/ui' function App() { diff --git a/packages/ui/src/__stories__/theme/typography.mdx b/packages/ui/src/__stories__/theme/typography.mdx index b7b2e24cce..469c98891c 100644 --- a/packages/ui/src/__stories__/theme/typography.mdx +++ b/packages/ui/src/__stories__/theme/typography.mdx @@ -13,7 +13,7 @@ You may also want to customize your typography fonts or sizes. To do that you ne You will need to pass an object with the same structure as the [default theme](https://github.com/scaleway/ultraviolet/blob/main/src/theme/tokens/light.ts), but with your own typography. ```tsx -import { css, Global, ThemeProvider } from '@emotion/react' +import { css, Global, ThemeProvider } from '@ultraviolet/themes' import { Text, extendTheme } from '@ultraviolet/ui' import AsapRegularWoff2 from 'assets/fonts/asap/Asap-Regular.woff2' diff --git a/packages/ui/src/__stories__/theme/understandTokens.mdx b/packages/ui/src/__stories__/theme/understandTokens.mdx index e3ef824a44..ae1fd525ba 100644 --- a/packages/ui/src/__stories__/theme/understandTokens.mdx +++ b/packages/ui/src/__stories__/theme/understandTokens.mdx @@ -6,7 +6,7 @@ import ThemeWrapper from '../components/ThemeWrapper' # Colors -Ultraviolet UI is based on `@emotion/react` library. +Ultraviolet UI is based on `vanilla-extract` library. ## Structure diff --git a/packages/ui/src/components/Button/__stories__/Showcase.stories.tsx b/packages/ui/src/components/Button/__stories__/Showcase.stories.tsx index 58e7dccd9d..2874a11aca 100644 --- a/packages/ui/src/components/Button/__stories__/Showcase.stories.tsx +++ b/packages/ui/src/components/Button/__stories__/Showcase.stories.tsx @@ -1,27 +1,11 @@ -import styled from '@emotion/styled' import type { StoryFn } from '@storybook/react-vite' -import type { ExtendedColor } from '../../../theme' import { SENTIMENTS } from '../../../theme' import { Stack, Table, Text } from '../..' import { Button } from '..' +import { showCase } from './style.css' const buttonVariants = ['ghost', 'filled', 'outlined'] as const -const StyledRow = styled(Table.Row, { - shouldForwardProp: prop => !['sentiment'].includes(prop), -})<{ sentiment: ExtendedColor }>` - background: ${({ sentiment }) => { - if (sentiment === 'white') { - return 'black' - } - if (sentiment === 'black') { - return 'white' - } - - return 'none' - }}; -` - const COLUMNS = [ { label: '' }, ...buttonVariants.map(variant => ({ @@ -35,7 +19,11 @@ export const Showcase: StoryFn<typeof Button> = args => ( <Table columns={COLUMNS}> <Table.Body> {([...SENTIMENTS, 'white', 'black'] as const).map(sentiment => ( - <StyledRow id={sentiment} key={sentiment} sentiment={sentiment}> + <Table.Row + className={showCase[sentiment]} + id={sentiment} + key={sentiment} + > <Table.Cell> <Text as="span" @@ -63,7 +51,7 @@ export const Showcase: StoryFn<typeof Button> = args => ( </Stack> </Table.Cell> ))} - </StyledRow> + </Table.Row> ))} </Table.Body> </Table> diff --git a/packages/ui/src/components/Button/__stories__/style.css.ts b/packages/ui/src/components/Button/__stories__/style.css.ts new file mode 100644 index 0000000000..5022e9c289 --- /dev/null +++ b/packages/ui/src/components/Button/__stories__/style.css.ts @@ -0,0 +1,17 @@ +import { styleVariants } from '@vanilla-extract/css' +import { SENTIMENTS } from '../../../theme' + +export const showCase = styleVariants( + Object.fromEntries( + [...SENTIMENTS, 'white', 'black'].map(sentiment => { + if (sentiment === 'white') { + return [sentiment, { background: 'black' }] + } + if (sentiment === 'black') { + return [sentiment, { background: 'white' }] + } + + return [sentiment, { background: 'none' }] + }), + ), +) diff --git a/packages/ui/src/components/Carousel/__stories__/Template.stories.tsx b/packages/ui/src/components/Carousel/__stories__/Template.stories.tsx index 7ab37a08ea..da26f12f6e 100644 --- a/packages/ui/src/components/Carousel/__stories__/Template.stories.tsx +++ b/packages/ui/src/components/Carousel/__stories__/Template.stories.tsx @@ -1,64 +1,56 @@ -import styled from '@emotion/styled' import type { StoryFn } from '@storybook/react-vite' import { Carousel } from '..' - -const Content = styled.div` - background-color: ${({ theme }) => theme.colors.info.background}; - width: 100%; - padding: ${({ theme }) => theme.space['3']}; - color: ${({ theme }) => theme.colors.info.text}; - text-align: center; -` +import { carouselStoryContent } from './styles.css' export const Template: StoryFn<typeof Carousel> = props => ( <Carousel {...props}> <Carousel.Item> - <Content> + <div className={carouselStoryContent}> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam - </Content> + </div> </Carousel.Item> <Carousel.Item> - <Content> + <div className={carouselStoryContent}> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. - </Content> + </div> </Carousel.Item> <Carousel.Item> - <Content> + <div className={carouselStoryContent}> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. - </Content> + </div> </Carousel.Item> <Carousel.Item> - <Content> + <div className={carouselStoryContent}> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. - </Content> + </div> </Carousel.Item> <Carousel.Item> - <Content> + <div className={carouselStoryContent}> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. - </Content> + </div> </Carousel.Item> <Carousel.Item> - <Content> + <div className={carouselStoryContent}> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. - </Content> + </div> </Carousel.Item> </Carousel> ) diff --git a/packages/ui/src/components/Carousel/__stories__/styles.css.ts b/packages/ui/src/components/Carousel/__stories__/styles.css.ts new file mode 100644 index 0000000000..49f755bc3b --- /dev/null +++ b/packages/ui/src/components/Carousel/__stories__/styles.css.ts @@ -0,0 +1,10 @@ +import { theme } from '@ultraviolet/themes' +import { style } from '@vanilla-extract/css' + +export const carouselStoryContent = style({ + backgroundColor: theme.colors.info.background, + width: '100%', + padding: theme.space[3], + color: theme.colors.info.text, + textAlign: 'center', +}) diff --git a/packages/ui/src/components/CopyButton/__stories__/Sizes.stories.tsx b/packages/ui/src/components/CopyButton/__stories__/Sizes.stories.tsx index 1741281cc6..e90e55d54e 100644 --- a/packages/ui/src/components/CopyButton/__stories__/Sizes.stories.tsx +++ b/packages/ui/src/components/CopyButton/__stories__/Sizes.stories.tsx @@ -1,20 +1,15 @@ -import styled from '@emotion/styled' import type { ComponentProps } from 'react' import { Stack } from '../../Stack' import { Text } from '../../Text' import { CopyButton } from '../index' -const StyledText = styled(Text)` - min-width: 80px; -` - export const Sizes = (props: ComponentProps<typeof CopyButton>) => ( <Stack gap={1}> {(['xsmall', 'small', 'medium', 'large'] as const).map(size => ( <Stack direction="row" gap={1} key={size}> - <StyledText as="span" variant="body"> + <Text as="span" style={{ minWidth: 80 }} variant="body"> {size}: - </StyledText> + </Text> <CopyButton {...props} size={size} value="Text that will be copied" /> </Stack> ))} diff --git a/packages/ui/src/components/InfiniteScroll/__stories__/SelectInput.stories.tsx b/packages/ui/src/components/InfiniteScroll/__stories__/SelectInput.stories.tsx index 63228dd065..9caff8a946 100644 --- a/packages/ui/src/components/InfiniteScroll/__stories__/SelectInput.stories.tsx +++ b/packages/ui/src/components/InfiniteScroll/__stories__/SelectInput.stories.tsx @@ -1,4 +1,3 @@ -import styled from '@emotion/styled' import type { StoryFn } from '@storybook/react-vite' import { useState } from 'react' import { SelectInput as SelectInputUV } from '../../SelectInput' @@ -6,17 +5,14 @@ import { Skeleton } from '../../Skeleton' import { Stack } from '../../Stack' import { InfiniteScroll } from '..' import { generateRandomNamesArray, SELECT_INPUT_DATA } from './data' - -const StyledStack = styled(Stack)` - padding: 0 ${({ theme }) => theme.space[3]}; -` +import { infiniteScrollSelectInput } from './style.css' const InfiniteScrollLoader = ( - <StyledStack direction="column" gap="3"> + <Stack className={infiniteScrollSelectInput} direction="column" gap="3"> <Skeleton variant="line" /> <Skeleton variant="line" /> <Skeleton variant="line" /> - </StyledStack> + </Stack> ) export const SelectInput: StoryFn<typeof InfiniteScroll> = args => { diff --git a/packages/ui/src/components/InfiniteScroll/__stories__/style.css.ts b/packages/ui/src/components/InfiniteScroll/__stories__/style.css.ts new file mode 100644 index 0000000000..2705701f48 --- /dev/null +++ b/packages/ui/src/components/InfiniteScroll/__stories__/style.css.ts @@ -0,0 +1,6 @@ +import { theme } from '@ultraviolet/themes' +import { style } from '@vanilla-extract/css' + +export const infiniteScrollSelectInput = style({ + padding: `0 ${theme.space[3]}`, +}) diff --git a/packages/ui/src/components/Loader/index.tsx b/packages/ui/src/components/Loader/index.tsx index b8bb3fd8c2..6a5fc3d9a3 100644 --- a/packages/ui/src/components/Loader/index.tsx +++ b/packages/ui/src/components/Loader/index.tsx @@ -66,7 +66,6 @@ export const Loader = ({ /> <circle className={loaderCircleAnimation} - // oxlint-disable-next-line no-unknown-property cx={HALF_VIEWBOX_WIDTH} cy={HALF_VIEWBOX_HEIGHT} fill="none" diff --git a/packages/ui/src/components/Pagination/__stories__/PerPage.stories.tsx b/packages/ui/src/components/Pagination/__stories__/PerPage.stories.tsx index b1172b57e8..48283778bf 100644 --- a/packages/ui/src/components/Pagination/__stories__/PerPage.stories.tsx +++ b/packages/ui/src/components/Pagination/__stories__/PerPage.stories.tsx @@ -1,17 +1,12 @@ -import styled from '@emotion/styled' import type { StoryFn } from '@storybook/react-vite' import { useState } from 'react' import { Badge } from '../../Badge' import { Stack } from '../../Stack' import { Pagination } from '..' +import { list } from './styles.css' const NUMBER_OF_ITEMS = 134 -const StyledList = styled.ul` - height: 13.5rem; - overflow-y: auto; - border: ${({ theme }) => theme.colors.neutral.border} 1px solid; - padding: ${({ theme }) => theme.space[1]}; -` + export const PerPage: StoryFn = props => { const [page, setPage] = useState(1) const [perPage, setPerPage] = useState(10) @@ -19,7 +14,7 @@ export const PerPage: StoryFn = props => { return ( <Stack gap={1}> - <StyledList> + <ul className={list}> {Array.from({ length: perPage }).map((_, index) => { const itemNumber = perPage * (page - 1) + index + 1 if (itemNumber <= NUMBER_OF_ITEMS) { @@ -28,7 +23,7 @@ export const PerPage: StoryFn = props => { return null })} - </StyledList> + </ul> <Pagination {...props} numberOfItems={NUMBER_OF_ITEMS} diff --git a/packages/ui/src/components/Pagination/__stories__/styles.css.ts b/packages/ui/src/components/Pagination/__stories__/styles.css.ts new file mode 100644 index 0000000000..ef56d63284 --- /dev/null +++ b/packages/ui/src/components/Pagination/__stories__/styles.css.ts @@ -0,0 +1,9 @@ +import { theme } from '@ultraviolet/themes' +import { style } from '@vanilla-extract/css' + +export const list = style({ + height: '13.5rem', + overflowY: 'auto', + border: `1px solid ${theme.colors.neutral.border}`, + padding: theme.space[1], +}) diff --git a/packages/ui/src/components/Row/__stories__/AlignItems.stories.tsx b/packages/ui/src/components/Row/__stories__/AlignItems.stories.tsx index 33a88a8374..324bcf261c 100644 --- a/packages/ui/src/components/Row/__stories__/AlignItems.stories.tsx +++ b/packages/ui/src/components/Row/__stories__/AlignItems.stories.tsx @@ -3,7 +3,7 @@ import { Separator } from '../../Separator' import { Stack } from '../../Stack' import { Text } from '../../Text' import { Row } from '..' -import { DivWithBackground } from './DivWithBackground' +import { divWithBackground } from './DivWithBackground.css' export const AlignItems: StoryFn = args => ( <Stack gap={2}> @@ -11,27 +11,37 @@ export const AlignItems: StoryFn = args => ( alignItems=“start“ </Text> <Row {...args} alignItems="start" gap={1} templateColumns="repeat(3, 1fr)"> - <DivWithBackground style={{ height: '100px' }}>1fr</DivWithBackground> - <DivWithBackground style={{ height: '50px' }}>1fr</DivWithBackground> - <DivWithBackground>1fr</DivWithBackground> + <div style={{ height: '100px' }}>1fr</div> + <div className={divWithBackground} style={{ height: '50px' }}> + 1fr + </div> + <div className={divWithBackground}>1fr</div> </Row> <Separator /> <Text as="p" variant="bodyStrong"> alignItems=“center“ </Text> <Row {...args} alignItems="center" gap={1} templateColumns="repeat(3, 1fr)"> - <DivWithBackground style={{ height: '100px' }}>1fr</DivWithBackground> - <DivWithBackground style={{ height: '50px' }}>1fr</DivWithBackground> - <DivWithBackground>1fr</DivWithBackground> + <div className={divWithBackground} style={{ height: '100px' }}> + 1fr + </div> + <div className={divWithBackground} style={{ height: '50px' }}> + 1fr + </div> + <div className={divWithBackground}>1fr</div> </Row> <Separator /> <Text as="p" variant="bodyStrong"> alignItems=“end“ </Text> <Row {...args} alignItems="end" gap={1} templateColumns="repeat(3, 1fr)"> - <DivWithBackground style={{ height: '100px' }}>1fr</DivWithBackground> - <DivWithBackground style={{ height: '50px' }}>1fr</DivWithBackground> - <DivWithBackground>1fr</DivWithBackground> + <div className={divWithBackground} style={{ height: '100px' }}> + 1fr + </div> + <div className={divWithBackground} style={{ height: '50px' }}> + 1fr + </div> + <div className={divWithBackground}>1fr</div> </Row> </Stack> ) diff --git a/packages/ui/src/components/Stack/__stories__/DivWithBackground.css.ts b/packages/ui/src/components/Row/__stories__/DivWithBackground.css.ts similarity index 75% rename from packages/ui/src/components/Stack/__stories__/DivWithBackground.css.ts rename to packages/ui/src/components/Row/__stories__/DivWithBackground.css.ts index a902de43dd..88a279ca61 100644 --- a/packages/ui/src/components/Stack/__stories__/DivWithBackground.css.ts +++ b/packages/ui/src/components/Row/__stories__/DivWithBackground.css.ts @@ -1,7 +1,7 @@ -import { style } from '@vanilla-extract/css' import { theme } from '@ultraviolet/themes' +import { style } from '@vanilla-extract/css' -export const styledDiv = style({ +export const divWithBackground = style({ padding: theme.space[1], background: theme.colors.primary.background, color: theme.colors.primary.text, @@ -10,9 +10,4 @@ export const styledDiv = style({ display: 'flex', alignItems: 'center', justifyContent: 'center', - selectors: { - '&[data-width-full="true"]': { - width: '100%', - }, - }, }) diff --git a/packages/ui/src/components/Row/__stories__/DivWithBackground.ts b/packages/ui/src/components/Row/__stories__/DivWithBackground.ts deleted file mode 100644 index de75609063..0000000000 --- a/packages/ui/src/components/Row/__stories__/DivWithBackground.ts +++ /dev/null @@ -1,12 +0,0 @@ -import styled from '@emotion/styled' - -export const DivWithBackground = styled.div` - padding: ${({ theme }) => theme.space[1]}; - background: ${({ theme }) => theme.colors.primary.background}; - color: ${({ theme }) => theme.colors.primary.text}; - border-radius: ${({ theme }) => theme.radii.default}; - border: 1px solid ${({ theme }) => theme.colors.primary.border}; - display: flex; - align-items: center; - justify-content: center; -` diff --git a/packages/ui/src/components/Row/__stories__/Padding.stories.tsx b/packages/ui/src/components/Row/__stories__/Padding.stories.tsx index eb26ef84fb..ce3b6c038c 100644 --- a/packages/ui/src/components/Row/__stories__/Padding.stories.tsx +++ b/packages/ui/src/components/Row/__stories__/Padding.stories.tsx @@ -1,21 +1,21 @@ import type { StoryFn } from '@storybook/react-vite' import { Stack } from '../../Stack' import { Row } from '..' -import { DivWithBackground } from './DivWithBackground' +import { divWithBackground } from './DivWithBackground.css' export const Padding: StoryFn = args => ( <Stack> <Row {...args} padding="50px 0" templateColumns="1fr"> - <DivWithBackground>Padding-top and bottom: 50px</DivWithBackground> + <div className={divWithBackground}>Padding-top and bottom: 50px</div> </Row> <Row {...args} padding="0 50px" templateColumns="1fr"> - <DivWithBackground>Padding-left and right: 50px</DivWithBackground> + <div className={divWithBackground}>Padding-left and right: 50px</div> </Row> <Row {...args} padding="16px 32px 24px 8px" templateColumns="1fr"> - <DivWithBackground> + <div className={divWithBackground}> Padding-left: 8px, padding-right: 32px, padding-top: 16px, padding-bottom: 24px; - </DivWithBackground> + </div> </Row> </Stack> ) diff --git a/packages/ui/src/components/Row/__stories__/Responsive.stories.tsx b/packages/ui/src/components/Row/__stories__/Responsive.stories.tsx index 1d93981c38..2cb98243e8 100644 --- a/packages/ui/src/components/Row/__stories__/Responsive.stories.tsx +++ b/packages/ui/src/components/Row/__stories__/Responsive.stories.tsx @@ -3,7 +3,7 @@ import { consoleLightTheme } from '@ultraviolet/themes' import { useEffect, useState } from 'react' import { Stack } from '../../Stack' import { Row } from '..' -import { DivWithBackground } from './DivWithBackground' +import { divWithBackground } from './DivWithBackground.css' export const Responsive: StoryFn = props => { const [breakpoint, setBreakpoint] = useState<'xxsmall' | 'xsmall' | 'small'>( @@ -70,9 +70,13 @@ export const Responsive: StoryFn = props => { const sentiments = ['primary', 'success', 'danger'] return ( - <DivWithBackground data-sentiment={sentiments[idx]} key={idx}> + <div + className={divWithBackground} + data-sentiment={sentiments[idx]} + key={idx} + > {col} - </DivWithBackground> + </div> ) })} </Row> @@ -93,9 +97,13 @@ export const Responsive: StoryFn = props => { const sentiments = ['primary', 'success', 'danger'] return ( - <DivWithBackground data-sentiment={sentiments[idx]} key={idx}> + <div + className={divWithBackground} + data-sentiment={sentiments[idx]} + key={idx} + > {col} - </DivWithBackground> + </div> ) })} </Row> diff --git a/packages/ui/src/components/Row/__stories__/Template.stories.tsx b/packages/ui/src/components/Row/__stories__/Template.stories.tsx index b8b09fe7c8..cb6677ed3a 100644 --- a/packages/ui/src/components/Row/__stories__/Template.stories.tsx +++ b/packages/ui/src/components/Row/__stories__/Template.stories.tsx @@ -1,19 +1,31 @@ import type { StoryFn } from '@storybook/react-vite' import { Stack } from '../../Stack' import { Row } from '..' -import { DivWithBackground } from './DivWithBackground' +import { divWithBackground } from './DivWithBackground.css' export const Template: StoryFn<typeof Row> = ({ ...props }) => ( <Stack gap={1}> <Row gap={1} {...props} templateColumns="3fr 6fr 3fr"> - <DivWithBackground data-sentiment="primary">3fr</DivWithBackground> - <DivWithBackground data-sentiment="success">6fr</DivWithBackground> - <DivWithBackground data-sentiment="danger">3fr</DivWithBackground> + <div className={divWithBackground} data-sentiment="primary"> + 3fr + </div> + <div className={divWithBackground} data-sentiment="success"> + 6fr + </div> + <div className={divWithBackground} data-sentiment="danger"> + 3fr + </div> </Row> <Row gap={1} {...props} templateColumns="4fr 3fr 4fr"> - <DivWithBackground data-sentiment="primary">4fr</DivWithBackground> - <DivWithBackground data-sentiment="success">3fr</DivWithBackground> - <DivWithBackground data-sentiment="danger">4fr</DivWithBackground> + <div className={divWithBackground} data-sentiment="primary"> + 4fr + </div> + <div className={divWithBackground} data-sentiment="success"> + 3fr + </div> + <div className={divWithBackground} data-sentiment="danger"> + 4fr + </div> </Row> </Stack> ) diff --git a/packages/ui/src/components/Stack/__stories__/AlignItems.stories.tsx b/packages/ui/src/components/Stack/__stories__/AlignItems.stories.tsx index e731c9fd5a..5e23d5b5d4 100644 --- a/packages/ui/src/components/Stack/__stories__/AlignItems.stories.tsx +++ b/packages/ui/src/components/Stack/__stories__/AlignItems.stories.tsx @@ -1,4 +1,3 @@ -import { coloredChildren } from './helper' import { Template } from './Template.stories' export const AlignItems = Template.bind({}) @@ -14,6 +13,5 @@ AlignItems.parameters = { AlignItems.args = { alignItems: 'center', - children: coloredChildren, gap: 2, } diff --git a/packages/ui/src/components/Stack/__stories__/Direction.stories.tsx b/packages/ui/src/components/Stack/__stories__/Direction.stories.tsx index 7a70000a13..86097ad651 100644 --- a/packages/ui/src/components/Stack/__stories__/Direction.stories.tsx +++ b/packages/ui/src/components/Stack/__stories__/Direction.stories.tsx @@ -1,7 +1,7 @@ import type { StoryFn } from '@storybook/react-vite' import { Stack } from '../../Stack' import { Text } from '../../Text' -import { styledDiv } from './DivWithBackground.css' +import { child } from './styles.css' export const Direction: StoryFn = props => ( <Stack gap={3}> @@ -10,13 +10,13 @@ export const Direction: StoryFn = props => ( Direction Row: </Text> <Stack {...props} direction="row" gap={1}> - <div className={styledDiv} data-width-full> + <div className={child} data-width-full> First child </div> - <div className={styledDiv} data-width-full> + <div className={child} data-width-full> Second child </div> - <div className={styledDiv} data-width-full> + <div className={child} data-width-full> Third child </div> </Stack> @@ -26,9 +26,9 @@ export const Direction: StoryFn = props => ( Direction Column: </Text> <Stack {...props} direction="column" gap={1}> - <div className={styledDiv}>First child</div> - <div className={styledDiv}>Second child</div> - <div className={styledDiv}>Third child</div> + <div className={child}>First child</div> + <div className={child}>Second child</div> + <div className={child}>Third child</div> </Stack> </Stack> </Stack> diff --git a/packages/ui/src/components/Stack/__stories__/Responsive.stories.tsx b/packages/ui/src/components/Stack/__stories__/Responsive.stories.tsx index c24ca7b6c5..46190586c3 100644 --- a/packages/ui/src/components/Stack/__stories__/Responsive.stories.tsx +++ b/packages/ui/src/components/Stack/__stories__/Responsive.stories.tsx @@ -1,6 +1,6 @@ import type { StoryFn } from '@storybook/react-vite' import { Stack } from '../../Stack' -import { styledDiv } from './DivWithBackground.css' +import { child } from './styles.css' export const Responsive: StoryFn = props => ( <Stack @@ -8,13 +8,13 @@ export const Responsive: StoryFn = props => ( direction={{ small: 'row', xsmall: 'row', xxsmall: 'column' }} gap={{ small: 3, xsmall: 2, xxsmall: 1 }} > - <div className={styledDiv} data-width-full> + <div className={child} data-width-full> First child </div> - <div className={styledDiv} data-width-full> + <div className={child} data-width-full> Second child </div> - <div className={styledDiv} data-width-full> + <div className={child} data-width-full> Third child </div> </Stack> diff --git a/packages/ui/src/components/Stack/__stories__/Template.stories.tsx b/packages/ui/src/components/Stack/__stories__/Template.stories.tsx index 8df0f5173b..2319f2ba41 100644 --- a/packages/ui/src/components/Stack/__stories__/Template.stories.tsx +++ b/packages/ui/src/components/Stack/__stories__/Template.stories.tsx @@ -1,11 +1,11 @@ import type { StoryFn } from '@storybook/react-vite' import { Stack } from '..' -import { styledDiv } from './DivWithBackground.css' +import { child, firstChild, secondChild, thirdChild } from './styles.css' export const Template: StoryFn<typeof Stack> = props => ( <Stack {...props}> - <div className={styledDiv}>First child</div> - <div className={styledDiv}>Second child</div> - <div className={styledDiv}>Third child</div> + <div className={`${child} ${firstChild}`}>First child</div> + <div className={`${child} ${secondChild}`}>Second child</div> + <div className={`${child} ${thirdChild}`}>Third child</div> </Stack> ) diff --git a/packages/ui/src/components/Stack/__stories__/helper.tsx b/packages/ui/src/components/Stack/__stories__/helper.tsx index d3cdd4e092..452e07a418 100644 --- a/packages/ui/src/components/Stack/__stories__/helper.tsx +++ b/packages/ui/src/components/Stack/__stories__/helper.tsx @@ -1,30 +1,13 @@ -import styled from '@emotion/styled' - -const Child = styled.div` - display: flex; - align-items: center; - justify-content: center; - padding: ${({ theme }) => theme.space['2']}; - border-radius: ${({ theme }) => theme.radii.default}; -` - -const FirstChild = styled(Child)` - background-color: ${({ theme }) => theme.colors.info.background}; - color: ${({ theme }) => theme.colors.info.text}; -` - -const SecondChild = styled(Child)` - background-color: ${({ theme }) => theme.colors.primary.background}; - color: ${({ theme }) => theme.colors.primary.text}; -` - -const ThirdChild = styled(Child)` - background-color: ${({ theme }) => theme.colors.warning.background}; - color: ${({ theme }) => theme.colors.warning.text}; -` +import { child, firstChild, secondChild, thirdChild } from './styles.css' export const coloredChildren = [ - <FirstChild key="1">1</FirstChild>, - <SecondChild key="2">2</SecondChild>, - <ThirdChild key="3">3</ThirdChild>, + <div className={`${child} ${firstChild}`} key="1"> + 1 + </div>, + <div className={`${child} ${secondChild}`} key="2"> + 2 + </div>, + <div className={`${child} ${thirdChild}`} key="3"> + 3 + </div>, ] diff --git a/packages/ui/src/components/Stack/__stories__/styles.css.ts b/packages/ui/src/components/Stack/__stories__/styles.css.ts new file mode 100644 index 0000000000..11576387de --- /dev/null +++ b/packages/ui/src/components/Stack/__stories__/styles.css.ts @@ -0,0 +1,36 @@ +import { theme } from '@ultraviolet/themes' +import { style } from '@vanilla-extract/css' + +export const child = style({ + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + padding: theme.space[1], + borderRadius: theme.radii.default, + color: theme.colors.primary.text, + border: `1px solid ${theme.colors.primary.border}`, + backgroundColor: theme.colors.primary.background, + selectors: { + '&[data-width-full="true"]': { + width: '100%', + }, + }, +}) + +export const firstChild = style({ + backgroundColor: theme.colors.info.background, + color: theme.colors.info.text, + border: `1px solid ${theme.colors.info.border}`, +}) + +export const secondChild = style({ + backgroundColor: theme.colors.primary.background, + color: theme.colors.primary.text, + border: `1px solid ${theme.colors.primary.border}`, +}) + +export const thirdChild = style({ + backgroundColor: theme.colors.warning.background, + color: theme.colors.warning.text, + border: `1px solid ${theme.colors.warning.border}`, +}) diff --git a/packages/ui/src/components/Text/__stories__/OneLine.stories.tsx b/packages/ui/src/components/Text/__stories__/OneLine.stories.tsx index 8881ac761f..5fe1a88477 100644 --- a/packages/ui/src/components/Text/__stories__/OneLine.stories.tsx +++ b/packages/ui/src/components/Text/__stories__/OneLine.stories.tsx @@ -1,33 +1,25 @@ -import styled from '@emotion/styled' import type { StoryFn } from '@storybook/react-vite' import { Text } from '../index' - -const Container = styled.div` - margin-bottom: ${({ theme }) => theme.space['2']}; - margin-top: ${({ theme }) => theme.space['1']}; - width: 200px; - background: ${({ theme }) => theme.colors.info.background}; - padding: ${({ theme }) => theme.space['1']}; -` +import { oneLineContainer } from './style.css' export const OneLine: StoryFn<typeof Text> = args => ( <> <strong>Without ellipsis</strong> - <Container> + <div className={oneLineContainer}> <Text {...args} as="div" variant="body"> This text is quite long. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </Text> - </Container> + </div> <strong>With ellipsis (a tooltip is displayed on hover)</strong> - <Container> + <div className={oneLineContainer}> <Text {...args} as="div" oneLine variant="body"> This text is quite long. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </Text> - </Container> + </div> </> ) diff --git a/packages/ui/src/components/Text/__stories__/style.css.ts b/packages/ui/src/components/Text/__stories__/style.css.ts new file mode 100644 index 0000000000..db90261c5f --- /dev/null +++ b/packages/ui/src/components/Text/__stories__/style.css.ts @@ -0,0 +1,10 @@ +import { theme } from '@ultraviolet/themes' +import { style } from '@vanilla-extract/css' + +export const oneLineContainer = style({ + marginBottom: theme.space[2], + marginTop: theme.space[2], + width: 200, + background: theme.colors.info.background, + padding: theme.space[1], +}) diff --git a/packages/ui/src/emotion.d.ts b/packages/ui/src/emotion.d.ts deleted file mode 100644 index fd16571f1d..0000000000 --- a/packages/ui/src/emotion.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -import type { consoleLightTheme } from '@ultraviolet/themes' - -type UltravioletUITheme = typeof consoleLightTheme -declare module '@emotion/react' { - export interface Theme extends UltravioletUITheme {} -} diff --git a/packages/ui/src/helpers/__tests__/treeMap.test.ts b/packages/ui/src/helpers/__tests__/treeMap.test.ts index 96b74d9ffa..0768251ae7 100644 --- a/packages/ui/src/helpers/__tests__/treeMap.test.ts +++ b/packages/ui/src/helpers/__tests__/treeMap.test.ts @@ -1,8 +1,10 @@ -import { Theme } from '@emotion/react' import { DefaultTreeMapDatum } from '@nivo/treemap' +import { consoleLightTheme } from '@ultraviolet/themes' import { describe, expect, it } from 'vitest' import { getAllIds, getDataColors, getOpacity, percentToHex } from '../treeMap' +type Theme = typeof consoleLightTheme + describe('getOpacity', () => { it('should return 100 for input 0', () => { expect(getOpacity(0)).toBe(100) diff --git a/packages/ui/src/helpers/treeMap.ts b/packages/ui/src/helpers/treeMap.ts index 76e27224f1..e054453047 100644 --- a/packages/ui/src/helpers/treeMap.ts +++ b/packages/ui/src/helpers/treeMap.ts @@ -1,6 +1,7 @@ -import type { Theme } from '@emotion/react' import type { DefaultTreeMapDatum } from '@nivo/treemap' +import type { consoleLightTheme } from '@ultraviolet/themes' +type Theme = typeof consoleLightTheme type ReturnType = Record<string, string> /** diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts index f3edfcac80..ed6a171b81 100644 --- a/packages/ui/src/index.ts +++ b/packages/ui/src/index.ts @@ -11,7 +11,6 @@ export { useTheme, } from './theme' export { - Breakpoint, bounce, bounceDefault, down, diff --git a/packages/ui/src/utils/index.ts b/packages/ui/src/utils/index.ts index f71d0c3707..6503e3e9d3 100644 --- a/packages/ui/src/utils/index.ts +++ b/packages/ui/src/utils/index.ts @@ -60,4 +60,4 @@ export { getUUID } from './ids' export { default as normalize } from './normalize' export type { ComparableType } from './orderBy' export { orderBy } from './orderBy' -export { Breakpoint, down, up } from './responsive' +export { down, up } from './responsive' diff --git a/packages/ui/src/utils/responsive/Breakpoint.tsx b/packages/ui/src/utils/responsive/Breakpoint.tsx deleted file mode 100644 index 00f5c8a67c..0000000000 --- a/packages/ui/src/utils/responsive/Breakpoint.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import styled from '@emotion/styled' -import type { ScreenSize } from '../../theme' -import { down, up } from './utilities' - -const Breakpoint = styled.div<{ down?: ScreenSize; up?: ScreenSize }>` - display: none; - ${props => ` - ${props.up ? up(props.up, 'display: block;') : ''} - ${props.down ? down(props.down, 'display: block;') : ''} - `} -` - -export default Breakpoint diff --git a/packages/ui/src/utils/responsive/index.ts b/packages/ui/src/utils/responsive/index.ts index 2361872e5c..91cafe82cc 100644 --- a/packages/ui/src/utils/responsive/index.ts +++ b/packages/ui/src/utils/responsive/index.ts @@ -1,2 +1 @@ -export { default as Breakpoint } from './Breakpoint' export { down, up } from './utilities' diff --git a/packages/ui/src/utils/responsive/style.css.ts b/packages/ui/src/utils/responsive/style.css.ts new file mode 100644 index 0000000000..88ccc73569 --- /dev/null +++ b/packages/ui/src/utils/responsive/style.css.ts @@ -0,0 +1,8 @@ +import { style } from '@vanilla-extract/css' + +export const breakpoint = style({ + display: 'none', +}) + +export const upStyle = style({}) +export const downStyle = style({}) diff --git a/packages/ui/tsconfig.json b/packages/ui/tsconfig.json index 469acdba3f..cb80a12a22 100644 --- a/packages/ui/tsconfig.json +++ b/packages/ui/tsconfig.json @@ -3,6 +3,6 @@ "compilerOptions": { "baseUrl": "." }, - "include": ["src", "../../global.d.ts", "emotion.d.ts", "vitest.setup.ts"], + "include": ["src", "../../global.d.ts", "vitest.setup.ts"], "exclude": ["node_modules", "coverage", "dist"] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0f779289f0..b580da36f8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -47,24 +47,6 @@ importers: '@commitlint/config-conventional': specifier: 20.0.0 version: 20.0.0 - '@emotion/babel-plugin': - specifier: 11.13.5 - version: 11.13.5 - '@emotion/cache': - specifier: 11.14.0 - version: 11.14.0 - '@emotion/eslint-plugin': - specifier: 11.12.0 - version: 11.12.0(eslint@9.39.1(jiti@2.4.2))(typescript@5.9.3) - '@emotion/jest': - specifier: 11.13.0 - version: 11.13.0 - '@emotion/react': - specifier: 11.14.0 - version: 11.14.0(@types/react@19.2.2)(react@19.2.0) - '@emotion/styled': - specifier: 11.14.1 - version: 11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0) '@eslint/compat': specifier: 1.4.1 version: 1.4.1(eslint@9.39.1(jiti@2.4.2)) @@ -146,6 +128,9 @@ importers: '@ultraviolet/ui': specifier: workspace:* version: link:packages/ui + '@vanilla-extract/css': + specifier: 1.17.4 + version: 1.17.4(babel-plugin-macros@3.1.0) '@vanilla-extract/vite-plugin': specifier: 5.1.1 version: 5.1.1(@types/node@22.18.11)(babel-plugin-macros@3.1.0)(jiti@2.4.2)(sass@1.94.0)(terser@5.39.0)(tsx@4.20.6)(vite@7.2.2(@types/node@22.18.11)(jiti@2.4.2)(sass@1.94.0)(terser@5.39.0)(tsx@4.20.6)(yaml@2.8.1))(yaml@2.8.1) @@ -712,9 +697,6 @@ importers: packages/ui: dependencies: - '@emotion/serialize': - specifier: 1.3.3 - version: 1.3.3 '@nivo/bar': specifier: 0.89.1 version: 0.89.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -776,12 +758,6 @@ importers: '@babel/core': specifier: 7.28.5 version: 7.28.5 - '@emotion/react': - specifier: 11.14.0 - version: 11.14.0(@types/react@19.2.2)(react@19.2.0) - '@emotion/styled': - specifier: 11.14.1 - version: 11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0) '@types/react': specifier: 19.2.2 version: 19.2.2 @@ -914,10 +890,6 @@ packages: resolution: {integrity: sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==} engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.25.9': - resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} - engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.27.1': resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} engines: {node: '>=6.9.0'} @@ -1431,14 +1403,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/runtime@7.26.9': - resolution: {integrity: sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==} - engines: {node: '>=6.9.0'} - - '@babel/runtime@7.27.6': - resolution: {integrity: sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==} - engines: {node: '>=6.9.0'} - '@babel/runtime@7.28.2': resolution: {integrity: sha512-KHp2IflsnGywDjBWDkR9iEqiWSpc8GIi0lgTT3mOElT0PP1tG26P4tmFI2YvAdzgq9RGyoHZQEIEdZy6Ec5xCA==} engines: {node: '>=6.9.0'} @@ -1451,10 +1415,6 @@ packages: resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.26.9': - resolution: {integrity: sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==} - engines: {node: '>=6.9.0'} - '@babel/traverse@7.28.4': resolution: {integrity: sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==} engines: {node: '>=6.9.0'} @@ -1463,10 +1423,6 @@ packages: resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==} engines: {node: '>=6.9.0'} - '@babel/types@7.26.9': - resolution: {integrity: sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==} - engines: {node: '>=6.9.0'} - '@babel/types@7.28.0': resolution: {integrity: sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==} engines: {node: '>=6.9.0'} @@ -1826,15 +1782,6 @@ packages: '@emnapi/wasi-threads@1.0.2': resolution: {integrity: sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==} - '@emotion/babel-plugin@11.13.5': - resolution: {integrity: sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==} - - '@emotion/cache@11.14.0': - resolution: {integrity: sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==} - - '@emotion/css-prettifier@1.2.0': - resolution: {integrity: sha512-p+9m/5fp61i90CGUT+516glGBXWoEHgSelybqR+5vlX6Kb+Z0rkOfEMFqTBwYMRxXZTitibZERl32n2yPma7Dw==} - '@emotion/eslint-plugin@11.12.0': resolution: {integrity: sha512-N0rtAVKk6w8RchWtexdG/GFbg48tdlO4cnq9Jg6H3ul3EDDgkYkPE0PKMb1/CJ7cDyYsiNPYVc3ZnWnd2/d0tA==} engines: {node: '>=6'} @@ -1844,62 +1791,6 @@ packages: '@emotion/hash@0.9.2': resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==} - '@emotion/is-prop-valid@1.3.1': - resolution: {integrity: sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==} - - '@emotion/jest@11.13.0': - resolution: {integrity: sha512-XyoUbJ9fthKdlXjTvjzd6aQ8yVWe68InZawFdGTFkJQRW44rsLHK1qjKB/+L7RiGgdm0BYFv7+tz8znQzRQOBw==} - peerDependencies: - '@types/jest': ^26.0.14 || ^27.0.0 || ^28.0.0 || ^29.0.0 - enzyme-to-json: ^3.2.1 - peerDependenciesMeta: - '@types/jest': - optional: true - enzyme-to-json: - optional: true - - '@emotion/memoize@0.9.0': - resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==} - - '@emotion/react@11.14.0': - resolution: {integrity: sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==} - peerDependencies: - '@types/react': '*' - react: '>=16.8.0' - peerDependenciesMeta: - '@types/react': - optional: true - - '@emotion/serialize@1.3.3': - resolution: {integrity: sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==} - - '@emotion/sheet@1.4.0': - resolution: {integrity: sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==} - - '@emotion/styled@11.14.1': - resolution: {integrity: sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==} - peerDependencies: - '@emotion/react': ^11.0.0-rc.0 - '@types/react': '*' - react: '>=16.8.0' - peerDependenciesMeta: - '@types/react': - optional: true - - '@emotion/unitless@0.10.0': - resolution: {integrity: sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==} - - '@emotion/use-insertion-effect-with-fallbacks@1.2.0': - resolution: {integrity: sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==} - peerDependencies: - react: '>=16.8.0' - - '@emotion/utils@1.4.2': - resolution: {integrity: sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==} - - '@emotion/weak-memoize@0.4.0': - resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==} - '@epic-web/invariant@1.0.0': resolution: {integrity: sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==} @@ -4360,9 +4251,6 @@ packages: engines: {node: '>=16'} hasBin: true - convert-source-map@1.9.0: - resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} - convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} @@ -5413,10 +5301,6 @@ packages: resolution: {integrity: sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==} engines: {node: '>=0.10.0'} - globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - globals@14.0.0: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} @@ -5500,9 +5384,6 @@ packages: highlightjs-vue@1.0.0: resolution: {integrity: sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==} - hoist-non-react-statics@3.3.2: - resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} - homedir-polyfill@1.0.3: resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==} engines: {node: '>=0.10.0'} @@ -7513,10 +7394,6 @@ packages: source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - source-map@0.5.7: - resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} - engines: {node: '>=0.10.0'} - source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} @@ -7539,10 +7416,6 @@ packages: spdx-license-ids@3.0.21: resolution: {integrity: sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==} - specificity@0.4.1: - resolution: {integrity: sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg==} - hasBin: true - split2@4.2.0: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} engines: {node: '>= 10.x'} @@ -7705,9 +7578,6 @@ packages: peerDependencies: postcss: ^8.2.15 - stylis@4.2.0: - resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} - supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -8539,13 +8409,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-module-imports@7.25.9': - dependencies: - '@babel/traverse': 7.26.9 - '@babel/types': 7.26.9 - transitivePeerDependencies: - - supports-color - '@babel/helper-module-imports@7.27.1': dependencies: '@babel/traverse': 7.28.4 @@ -9200,12 +9063,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/runtime@7.26.9': - dependencies: - regenerator-runtime: 0.14.1 - - '@babel/runtime@7.27.6': {} - '@babel/runtime@7.28.2': {} '@babel/runtime@7.28.4': {} @@ -9216,18 +9073,6 @@ snapshots: '@babel/parser': 7.28.5 '@babel/types': 7.28.5 - '@babel/traverse@7.26.9': - dependencies: - '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.5 - '@babel/parser': 7.28.5 - '@babel/template': 7.27.2 - '@babel/types': 7.28.5 - debug: 4.4.3 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - '@babel/traverse@7.28.4': dependencies: '@babel/code-frame': 7.27.1 @@ -9252,11 +9097,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/types@7.26.9': - dependencies: - '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.28.5 - '@babel/types@7.28.0': dependencies: '@babel/helper-string-parser': 7.27.1 @@ -9928,35 +9768,6 @@ snapshots: tslib: 2.8.1 optional: true - '@emotion/babel-plugin@11.13.5': - dependencies: - '@babel/helper-module-imports': 7.25.9 - '@babel/runtime': 7.26.9 - '@emotion/hash': 0.9.2 - '@emotion/memoize': 0.9.0 - '@emotion/serialize': 1.3.3 - babel-plugin-macros: 3.1.0 - convert-source-map: 1.9.0 - escape-string-regexp: 4.0.0 - find-root: 1.1.0 - source-map: 0.5.7 - stylis: 4.2.0 - transitivePeerDependencies: - - supports-color - - '@emotion/cache@11.14.0': - dependencies: - '@emotion/memoize': 0.9.0 - '@emotion/sheet': 1.4.0 - '@emotion/utils': 1.4.2 - '@emotion/weak-memoize': 0.4.0 - stylis: 4.2.0 - - '@emotion/css-prettifier@1.2.0': - dependencies: - '@emotion/memoize': 0.9.0 - stylis: 4.2.0 - '@emotion/eslint-plugin@11.12.0(eslint@9.39.1(jiti@2.4.2))(typescript@5.9.3)': dependencies: '@typescript-eslint/utils': 5.62.0(eslint@9.39.1(jiti@2.4.2))(typescript@5.9.3) @@ -9967,71 +9778,6 @@ snapshots: '@emotion/hash@0.9.2': {} - '@emotion/is-prop-valid@1.3.1': - dependencies: - '@emotion/memoize': 0.9.0 - - '@emotion/jest@11.13.0': - dependencies: - '@babel/runtime': 7.28.4 - '@emotion/css-prettifier': 1.2.0 - chalk: 4.1.2 - specificity: 0.4.1 - stylis: 4.2.0 - - '@emotion/memoize@0.9.0': {} - - '@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0)': - dependencies: - '@babel/runtime': 7.27.6 - '@emotion/babel-plugin': 11.13.5 - '@emotion/cache': 11.14.0 - '@emotion/serialize': 1.3.3 - '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.2.0) - '@emotion/utils': 1.4.2 - '@emotion/weak-memoize': 0.4.0 - hoist-non-react-statics: 3.3.2 - react: 19.2.0 - optionalDependencies: - '@types/react': 19.2.2 - transitivePeerDependencies: - - supports-color - - '@emotion/serialize@1.3.3': - dependencies: - '@emotion/hash': 0.9.2 - '@emotion/memoize': 0.9.0 - '@emotion/unitless': 0.10.0 - '@emotion/utils': 1.4.2 - csstype: 3.1.3 - - '@emotion/sheet@1.4.0': {} - - '@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0)': - dependencies: - '@babel/runtime': 7.27.6 - '@emotion/babel-plugin': 11.13.5 - '@emotion/is-prop-valid': 1.3.1 - '@emotion/react': 11.14.0(@types/react@19.2.2)(react@19.2.0) - '@emotion/serialize': 1.3.3 - '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.2.0) - '@emotion/utils': 1.4.2 - react: 19.2.0 - optionalDependencies: - '@types/react': 19.2.2 - transitivePeerDependencies: - - supports-color - - '@emotion/unitless@0.10.0': {} - - '@emotion/use-insertion-effect-with-fallbacks@1.2.0(react@19.2.0)': - dependencies: - react: 19.2.0 - - '@emotion/utils@1.4.2': {} - - '@emotion/weak-memoize@0.4.0': {} - '@epic-web/invariant@1.0.0': {} '@esbuild/aix-ppc64@0.25.0': @@ -11466,7 +11212,8 @@ snapshots: '@types/normalize-package-data@2.4.4': {} - '@types/parse-json@4.0.2': {} + '@types/parse-json@4.0.2': + optional: true '@types/react-dom@19.2.2(@types/react@19.2.2)': dependencies: @@ -12400,6 +12147,7 @@ snapshots: '@babel/runtime': 7.28.4 cosmiconfig: 7.1.0 resolve: 1.22.10 + optional: true babel-plugin-named-exports-order@0.0.2: {} @@ -12781,8 +12529,6 @@ snapshots: meow: 12.1.1 split2: 4.2.0 - convert-source-map@1.9.0: {} - convert-source-map@2.0.0: {} cookie@1.0.2: {} @@ -12811,6 +12557,7 @@ snapshots: parse-json: 5.2.0 path-type: 4.0.0 yaml: 1.10.2 + optional: true cosmiconfig@8.3.6(typescript@5.9.3): dependencies: @@ -14090,8 +13837,6 @@ snapshots: is-windows: 1.0.2 which: 1.3.1 - globals@11.12.0: {} - globals@14.0.0: {} globals@16.4.0: {} @@ -14166,10 +13911,6 @@ snapshots: highlightjs-vue@1.0.0: {} - hoist-non-react-statics@3.3.2: - dependencies: - react-is: 16.13.1 - homedir-polyfill@1.0.3: dependencies: parse-passwd: 1.0.0 @@ -16517,8 +16258,6 @@ snapshots: buffer-from: 1.1.2 source-map: 0.6.1 - source-map@0.5.7: {} - source-map@0.6.1: {} space-separated-tokens@1.1.5: {} @@ -16542,8 +16281,6 @@ snapshots: spdx-license-ids@3.0.21: {} - specificity@0.4.1: {} - split2@4.2.0: {} sprintf-js@1.0.3: {} @@ -16732,8 +16469,6 @@ snapshots: postcss: 8.5.6 postcss-selector-parser: 6.1.2 - stylis@4.2.0: {} - supports-color@5.5.0: dependencies: has-flag: 3.0.0 diff --git a/tsconfig.json b/tsconfig.json index c958a1dac5..5f5ed65cca 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,7 +3,6 @@ "compilerOptions": { "target": "esnext", "module": "esnext", - "jsxImportSource": "@emotion/react", "types": ["vite/client", "@testing-library/jest-dom"], "noEmit": true, "skipLibCheck": true, diff --git a/utils/scripts/analyse-deps.ts b/utils/scripts/analyse-deps.ts index 0b10268ef3..406c45d94b 100644 --- a/utils/scripts/analyse-deps.ts +++ b/utils/scripts/analyse-deps.ts @@ -58,14 +58,9 @@ for (const file of filesToAnalyze) { .replace(/\.tsx?$/, '') if ( - ![ - 'react', - 'react-vite', - 'vitest', - 'styled', - '@emotion/styled', - 'components/', - ].some(string => normalizedFile.endsWith(string)) + !['react', 'react-vite', 'vitest', 'styled', 'components/'].some( + string => normalizedFile.endsWith(string), + ) ) { const importedComponent = normalizedFile.split('/').toReversed()[0] diff --git a/vite.config.ts b/vite.config.ts index 86d54f2b3a..7b9b26e9a1 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -9,7 +9,6 @@ import type { ViteUserConfig } from 'vitest/config' const pkg = await readPackage() const externalPkgs = [ - '@emotion', ...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.optionalDependencies || {}), ...Object.keys(pkg.peerDependencies || {}), @@ -69,10 +68,6 @@ export const defaultConfig: ViteUserConfig = { }, plugins: [ react({ - babel: { - plugins: ['@emotion/babel-plugin'], - }, - jsxImportSource: '@emotion/react', jsxRuntime: 'automatic', }), preserveDirectives(),