diff --git a/.pnp.cjs b/.pnp.cjs index e2ef13478..aebfb90bd 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -1698,6 +1698,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["@atls-ui-parts/select", "workspace:ui-parts/select"],\ ["@atls-ui-parts/layout", "virtual:dbe1a421eee484ea0bdb9d0589d44d9184c9819d8f5bfcb1a73e3d85271cc45ecf4365a26e00f2a3256c13de48b40272578801688978809175001fb2693bc747#workspace:ui-parts/layout"],\ + ["@atls-ui-parts/theme", "virtual:dbe1a421eee484ea0bdb9d0589d44d9184c9819d8f5bfcb1a73e3d85271cc45ecf4365a26e00f2a3256c13de48b40272578801688978809175001fb2693bc747#workspace:ui-parts/theme"],\ ["@atls-utils/use-select", "virtual:9c076913ffd643939b8ac6e8c374fd1470f44689001261d35898fb07091ea0aa596a24d8bcdfb508f949d0c68789b448702cfb68072c423229496303e9a11342#workspace:utils/use-select"],\ ["@storybook/react", "virtual:90c3fa37a29dbddd012ae896ef9d136c46ca1d320faf1baf430439ab5aac7e1e7c8ef5281a72424df8d016a8c33c9d5ffe66ee23d2face19f27de3042508900f#npm:8.6.12"],\ ["@types/react", "npm:19.1.2"],\ @@ -1705,7 +1706,6 @@ const RAW_RUNTIME_STATE = ["@vanilla-extract/dynamic", "npm:2.1.2"],\ ["clsx", "npm:2.1.1"],\ ["framer-motion", "virtual:3dba37771ce499e6d5c33bd82b7263c259fd8b9b612d0bf65962a3da6b1ec4612c0f051c5ab6d1701e4760bde49cb56e2383e557801939071c5dbec0f467c0d5#npm:12.23.22"],\ - ["rainbow-sprinkles", "virtual:90c3fa37a29dbddd012ae896ef9d136c46ca1d320faf1baf430439ab5aac7e1e7c8ef5281a72424df8d016a8c33c9d5ffe66ee23d2face19f27de3042508900f#npm:1.0.0"],\ ["react", "npm:19.1.0"],\ ["react-dom", "virtual:90c3fa37a29dbddd012ae896ef9d136c46ca1d320faf1baf430439ab5aac7e1e7c8ef5281a72424df8d016a8c33c9d5ffe66ee23d2face19f27de3042508900f#npm:19.1.0"],\ ["storybook", "virtual:90c3fa37a29dbddd012ae896ef9d136c46ca1d320faf1baf430439ab5aac7e1e7c8ef5281a72424df8d016a8c33c9d5ffe66ee23d2face19f27de3042508900f#npm:8.6.12"]\ diff --git a/ui-parts/select/package.json b/ui-parts/select/package.json index 75d89b604..ee1830377 100644 --- a/ui-parts/select/package.json +++ b/ui-parts/select/package.json @@ -13,10 +13,10 @@ "postpack": "rm -rf dist" }, "dependencies": { + "@atls-ui-parts/theme": "workspace:*", "@atls-utils/use-select": "workspace:*", "clsx": "2.1.1", - "framer-motion": "12.23.22", - "rainbow-sprinkles": "1.0.0" + "framer-motion": "12.23.22" }, "devDependencies": { "@atls-ui-parts/layout": "workspace:*", diff --git a/ui-parts/select/src/select.component.tsx b/ui-parts/select/src/component.tsx similarity index 61% rename from ui-parts/select/src/select.component.tsx rename to ui-parts/select/src/component.tsx index 172418770..a73962f78 100644 --- a/ui-parts/select/src/select.component.tsx +++ b/ui-parts/select/src/component.tsx @@ -1,6 +1,6 @@ import type { ReactNode } from 'react' -import type { SelectProps } from './select.interfaces.js' +import type { SelectProps } from './interfaces.js' import { clsx } from 'clsx' import { motion } from 'framer-motion' @@ -9,16 +9,20 @@ import { useSelect } from '@atls-utils/use-select' import { MenuItem } from './item/index.js' import { baseButtonStyles } from './button/index.js' -import { baseMenuSprinkles } from './menu/index.js' import { baseMenuStyles } from './menu/index.js' +import { selectAppearances } from './styles/index.js' +import { selectShapes } from './styles/index.js' export const Select = ({ + appearance = selectAppearances.default, items, label, + menuProps: menuPropsProperty, value, onChangeValue, placeholder, - ...props + shape = selectShapes.default, + width, }: SelectProps): ReactNode => { const { isOpen, @@ -33,23 +37,29 @@ export const Select = ({ onChange: onChangeValue, }) - const { className, style, otherProps } = baseMenuSprinkles(props) + const triggerValue = value || placeholder + const { className, style, ...props } = menuPropsProperty ?? {} + const menuStyle = width === undefined ? style : { width, ...style } return ( <> {/* eslint-disable-next-line jsx-a11y/label-has-associated-control */} - {/* eslint-disable-next-line react/jsx-no-leaked-render */} {isOpen && renderMenu( {items.map((item, index) => ( {item} diff --git a/ui-parts/select/src/constants.ts b/ui-parts/select/src/constants.ts new file mode 100644 index 000000000..c8a77c173 --- /dev/null +++ b/ui-parts/select/src/constants.ts @@ -0,0 +1 @@ +export const DEFAULT_MENU_WIDTH = 100 diff --git a/ui-parts/select/src/index.ts b/ui-parts/select/src/index.ts index 74f4467fe..2c3bc6700 100644 --- a/ui-parts/select/src/index.ts +++ b/ui-parts/select/src/index.ts @@ -1,5 +1,6 @@ export * from './button/index.js' export * from './item/index.js' export * from './menu/index.js' -export * from './select.component.js' -export type * from './select.interfaces.js' +export * from './component.js' +export * from './styles/index.js' +export type * from './interfaces.js' diff --git a/ui-parts/select/src/interfaces.ts b/ui-parts/select/src/interfaces.ts new file mode 100644 index 000000000..314e5c52a --- /dev/null +++ b/ui-parts/select/src/interfaces.ts @@ -0,0 +1,31 @@ +import type { HTMLMotionProps } from 'framer-motion' +import type { CSSProperties } from 'react' + +export interface SelectAppearance { + highlightedItem: string + item: string + menu: string + trigger: string +} + +export type SelectAppearanceName = 'default' + +export interface SelectShape { + item: string + menu: string + trigger: string +} + +export type SelectShapeName = 'default' + +export interface SelectProps { + appearance?: SelectAppearance + label: string + value: string + onChangeValue: (nextValue: string) => void + placeholder: string + items: Array + menuProps?: HTMLMotionProps<'ul'> + shape?: SelectShape + width?: CSSProperties['width'] +} diff --git a/ui-parts/select/src/item/component.tsx b/ui-parts/select/src/item/component.tsx new file mode 100644 index 000000000..84d5d9f7b --- /dev/null +++ b/ui-parts/select/src/item/component.tsx @@ -0,0 +1,28 @@ +import type { ReactNode } from 'react' + +import type { ItemProps } from './interfaces.js' + +import { clsx } from 'clsx' + +import { baseItemStyles } from './item.css.js' +import { highlightedMenuItemStyles } from './item.css.js' + +export const MenuItem = ({ + highlighted, + highlightedClassName, + children, + className, + ...props +}: ItemProps): ReactNode => ( +
  • + {children} +
  • +) diff --git a/ui-parts/select/src/item/index.ts b/ui-parts/select/src/item/index.ts index 8b6699f95..db383be6b 100644 --- a/ui-parts/select/src/item/index.ts +++ b/ui-parts/select/src/item/index.ts @@ -1,2 +1,2 @@ -export * from './item.component.js' -export type * from './item.interfaces.js' +export * from './component.js' +export type * from './interfaces.js' diff --git a/ui-parts/select/src/item/item.interfaces.ts b/ui-parts/select/src/item/interfaces.ts similarity index 81% rename from ui-parts/select/src/item/item.interfaces.ts rename to ui-parts/select/src/item/interfaces.ts index 5b99ea1ba..298251b38 100644 --- a/ui-parts/select/src/item/item.interfaces.ts +++ b/ui-parts/select/src/item/interfaces.ts @@ -2,4 +2,5 @@ import type { LiHTMLAttributes } from 'react' export interface ItemProps extends LiHTMLAttributes { highlighted: boolean + highlightedClassName?: string } diff --git a/ui-parts/select/src/item/item.component.tsx b/ui-parts/select/src/item/item.component.tsx deleted file mode 100644 index 842d168d5..000000000 --- a/ui-parts/select/src/item/item.component.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import type { ReactNode } from 'react' - -import type { ItemProps } from './item.interfaces.js' - -import { clsx } from 'clsx' - -import { baseItemStyles } from './item.css.js' -import { highlightedMenuItemStyles } from './item.css.js' - -export const MenuItem = ({ highlighted, children, ...props }: ItemProps): ReactNode => ( -
  • - {children} -
  • -) diff --git a/ui-parts/select/src/menu/menu.css.ts b/ui-parts/select/src/menu/menu.css.ts index 9d0697c82..d826d9567 100644 --- a/ui-parts/select/src/menu/menu.css.ts +++ b/ui-parts/select/src/menu/menu.css.ts @@ -1,16 +1,4 @@ -import { style } from '@vanilla-extract/css' -import { createRainbowSprinkles } from 'rainbow-sprinkles' -import { defineProperties } from 'rainbow-sprinkles' - -const menuComponentProperties = defineProperties({ - dynamicProperties: { - width: true, - }, -}) - -export const baseMenuSprinkles = createRainbowSprinkles(menuComponentProperties) - -export type BaseMenuSprinkles = Parameters[0] +import { style } from '@vanilla-extract/css' export const baseMenuStyles = style({ display: 'flex', @@ -19,8 +7,5 @@ export const baseMenuStyles = style({ flexDirection: 'column', outline: 'none', padding: 0, - width: 100, height: 'auto', - border: '1px solid black', - borderRadius: 4, }) diff --git a/ui-parts/select/src/select.interfaces.ts b/ui-parts/select/src/select.interfaces.ts deleted file mode 100644 index 6eb7d2286..000000000 --- a/ui-parts/select/src/select.interfaces.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { BaseMenuSprinkles } from './menu/index.js' - -export interface SelectProps extends BaseMenuSprinkles { - label: string - value: string - onChangeValue: (nextValue: string) => void - placeholder: string - items: Array -} diff --git a/ui-parts/select/src/select.stories.tsx b/ui-parts/select/src/select.stories.tsx index 223404690..4500bc05a 100644 --- a/ui-parts/select/src/select.stories.tsx +++ b/ui-parts/select/src/select.stories.tsx @@ -9,7 +9,7 @@ import { Column } from '@atls-ui-parts/layout' import { Row } from '@atls-ui-parts/layout' import { Layout } from '@atls-ui-parts/layout' -import { Select } from './select.component.js' +import { Select } from './component.js' const meta: Meta = { title: 'Components/Select', diff --git a/ui-parts/select/src/styles/appearance.css.ts b/ui-parts/select/src/styles/appearance.css.ts new file mode 100644 index 000000000..3472c4f47 --- /dev/null +++ b/ui-parts/select/src/styles/appearance.css.ts @@ -0,0 +1,27 @@ +import type { SelectAppearance } from '../interfaces.js' +import type { SelectAppearanceName } from '../interfaces.js' + +import { style } from '@vanilla-extract/css' + +import { vars } from '@atls-ui-parts/theme' + +const itemDefaultAppearanceStyles = style({ + color: vars.colors.black, +}) + +const menuDefaultAppearanceStyles = style({ + border: vars.borders.normalBlack, +}) + +export const appearanceVariant = { + default: { + highlightedItem: '', + item: itemDefaultAppearanceStyles, + menu: menuDefaultAppearanceStyles, + trigger: '', + }, +} + +export const selectAppearances: Record = { + default: appearanceVariant.default, +} diff --git a/ui-parts/select/src/styles/index.ts b/ui-parts/select/src/styles/index.ts new file mode 100644 index 000000000..93e0eec5d --- /dev/null +++ b/ui-parts/select/src/styles/index.ts @@ -0,0 +1,2 @@ +export * from './appearance.css.js' +export * from './shape.css.js' diff --git a/ui-parts/select/src/styles/shape.css.ts b/ui-parts/select/src/styles/shape.css.ts new file mode 100644 index 000000000..e41351adc --- /dev/null +++ b/ui-parts/select/src/styles/shape.css.ts @@ -0,0 +1,23 @@ +import type { SelectShape } from '../interfaces.js' +import type { SelectShapeName } from '../interfaces.js' + +import { style } from '@vanilla-extract/css' + +import { vars } from '@atls-ui-parts/theme' + +import { DEFAULT_MENU_WIDTH } from '../constants.js' + +const menuDefaultShapeStyles = style({ + width: DEFAULT_MENU_WIDTH, + borderRadius: vars.radii.f4, +}) + +export const shapeStyles = { + default: { + item: '', + menu: menuDefaultShapeStyles, + trigger: '', + }, +} + +export const selectShapes: Record = shapeStyles diff --git a/ui-parts/theme/src/tokens/borders.ts b/ui-parts/theme/src/tokens/borders.ts index b75f97a04..9c43c82f9 100644 --- a/ui-parts/theme/src/tokens/borders.ts +++ b/ui-parts/theme/src/tokens/borders.ts @@ -5,6 +5,7 @@ export const borders = { thinLightGray: '0.5px solid rgba(228, 228, 228, 1)', normalGray: '1px solid rgba(114, 114, 114, 1)', + normalBlack: '1px solid rgba(0, 0, 0, 1)', normalSilver: '1px solid rgba(224, 224, 224, 1)', normalCloudyWhite: '1px solid rgba(228, 228, 228, 1)', normalBlue: '1px solid rgba(65, 109, 223, 1)', diff --git a/yarn.lock b/yarn.lock index f7f883afc..e6b9f8536 100644 --- a/yarn.lock +++ b/yarn.lock @@ -887,6 +887,7 @@ __metadata: resolution: "@atls-ui-parts/select@workspace:ui-parts/select" dependencies: "@atls-ui-parts/layout": "workspace:*" + "@atls-ui-parts/theme": "workspace:*" "@atls-utils/use-select": "workspace:*" "@storybook/react": "npm:8.6.12" "@types/react": "npm:19.1.2" @@ -894,7 +895,6 @@ __metadata: "@vanilla-extract/dynamic": "npm:2.1.2" clsx: "npm:2.1.1" framer-motion: "npm:12.23.22" - rainbow-sprinkles: "npm:1.0.0" react: "npm:19.1.0" react-dom: "npm:19.1.0" storybook: "npm:8.6.12"