@codecademy/gamut
72.2.272.2.3-alpha.83b0a8.0
dist/Form/SelectDropdown/core/styles.js+
dist/Form/SelectDropdown/core/styles.jsNew file+248
Index: package/dist/Form/SelectDropdown/core/styles.js
===================================================================
--- package/dist/Form/SelectDropdown/core/styles.js
+++ package/dist/Form/SelectDropdown/core/styles.js
@@ -0,0 +1,248 @@
+import { css, states, variant } from '@codecademy/gamut-styles';
+import { dismissSharedStyles, tagBaseStyles, tagLabelFontSize, tagLabelPadding } from '../../../Tag/styles';
+import { formBaseComponentStyles, formBaseFieldStylesObject, formFieldDisabledStyles, formFieldPaddingStyles, InputSelectors } from '../../styles';
+const selectDropdownStyles = css({
+ ...formBaseFieldStylesObject,
+ display: 'flex',
+ zIndex: 3
+});
+const selectFocusStyles = {
+ color: 'primary',
+ borderColor: 'currentColor',
+ boxShadow: `inset 0 0 0 1px currentColor`
+};
+export const conditionalBorderStates = states({
+ isFocused: selectFocusStyles,
+ activated: {
+ borderColor: 'currentColor'
+ },
+ error: {
+ color: 'feedback-error',
+ borderColor: 'currentColor',
+ [InputSelectors.HOVER]: {
+ borderColor: 'currentColor'
+ }
+ },
+ isDisabled: formFieldDisabledStyles
+});
+const sizeVariants = variant({
+ prop: 'size',
+ defaultVariant: 'medium',
+ variants: {
+ medium: formFieldPaddingStyles,
+ mediumIsMultiSelected: {
+ px: 8,
+ py: 8
+ },
+ small: {
+ minHeight: '2rem',
+ px: 8,
+ py: 0
+ }
+ }
+});
+const dropdownBorderStates = states({
+ error: {
+ borderColorTop: 'feedback-error'
+ }
+});
+const dropdownBorderStyles = (zIndex = 2) => css({
+ ...formBaseComponentStyles,
+ border: 1,
+ borderColor: 'currentColor',
+ position: 'absolute',
+ marginTop: 0,
+ borderRadius: 'none',
+ zIndex
+});
+const getOptionBackground = (isSelected, isFocused) => css({
+ bg: isFocused ? 'background-hover' : isSelected ? 'background-selected' : 'transparent'
+});
+const textColor = css({
+ color: 'text'
+});
+const placeholderColor = css({
+ color: 'text-secondary'
+});
+export const getMemoizedStyles = (theme, zIndex) => {
+ return {
+ clearIndicator: provided => ({
+ ...provided
+ }),
+ container: (provided, state) => {
+ const {
+ inputWidth
+ } = state.selectProps;
+ return {
+ ...provided,
+ pointerEvents: 'visible',
+ cursor: state.selectProps.isSearchable ? 'text' : 'pointer',
+ width: inputWidth || '100%',
+ minWidth: '7rem'
+ };
+ },
+ control: (provided, state) => {
+ const {
+ isMulti,
+ size
+ } = state.selectProps;
+ const getSize = size ?? 'medium';
+ const getPadding = isMulti && state.hasValue && size !== 'small' ? `mediumIsMultiSelected` : getSize;
+ return {
+ ...selectDropdownStyles({
+ theme
+ }),
+ ...sizeVariants({
+ size: getPadding,
+ theme
+ }),
+ ...conditionalBorderStates({
+ isFocused: state.isFocused,
+ isDisabled: state.isDisabled,
+ error: state.selectProps.error,
+ activated: state.selectProps.activated,
+ theme
+ })
+ };
+ },
+ dropdownIndicator: () => ({
+ color: 'currentColor',
+ display: 'flex',
+ padding: '0',
+ pointerEvents: 'none'
+ }),
+ groupHeading: provided => ({
+ ...provided,
+ color: theme.colors['text-disabled']
+ }),
+ input: provided => ({
+ ...provided,
+ ...textColor({
+ theme
+ }),
+ margin: '0',
+ padding: '0'
+ }),
+ menu: (provided, state) => {
+ const {
+ dropdownWidth,
+ menuAlignment
+ } = state.selectProps;
+ return {
+ ...provided,
+ ...dropdownBorderStyles(zIndex)({
+ theme
+ }),
+ ...dropdownBorderStates({
+ error: state.selectProps.error,
+ theme
+ }),
+ // Drop react-select's default menu drop shadow; the border above defines the edge.
+ boxShadow: 'none',
+ ...(dropdownWidth ? {
+ minWidth: dropdownWidth,
+ width: dropdownWidth
+ } : {}),
+ ...(menuAlignment === 'right' ? {
+ left: 'auto',
+ right: 0
+ } : {})
+ };
+ },
+ menuList: (provided, state) => {
+ const sizeInteger = state.selectProps.size === 'small' ? 2 : 3;
+ const maxHeight = `${(state.selectProps.shownOptionsLimit ?? 6) * sizeInteger}rem`;
+ return {
+ ...provided,
+ maxHeight
+ };
+ },
+ multiValue: (provided, state) => ({
+ ...provided,
+ ...tagBaseStyles,
+ backgroundColor: 'transparent',
+ color: theme.colors.background,
+ cursor: state.isDisabled ? 'not-allowed' : 'pointer',
+ height: '24px'
+ }),
+ multiValueLabel: provided => ({
+ ...provided,
+ backgroundColor: theme.colors['text-secondary'],
+ borderEndEndRadius: 0,
+ borderEndStartRadius: theme.borderRadii.md,
+ borderStartEndRadius: 0,
+ borderStartStartRadius: theme.borderRadii.md,
+ color: theme.colors.background,
+ fontSize: tagLabelFontSize,
+ height: '100%',
+ padding: `0 ${tagLabelPadding}px`,
+ paddingLeft: `${tagLabelPadding}px`,
+ // default label has an explicit rule for padding left so we need this to override it
+ paddingTop: '2px' // adding to shift the text down to vertically center it
+ }),
+ multiValueRemove: (provided, state) => ({
+ ...provided,
+ ...dismissSharedStyles,
+ backgroundColor: theme.colors['text-secondary'],
+ borderEndEndRadius: theme.borderRadii.md,
+ borderEndStartRadius: 0,
+ borderStartEndRadius: theme.borderRadii.md,
+ borderStartStartRadius: 0,
+ cursor: state.isDisabled ? 'not-allowed' : 'pointer',
+ padding: 0,
+ // default remove has padding left and right that we don't need
+ pointerEvents: state.isDisabled ? 'none' : 'visible',
+ ':hover': {
+ backgroundColor: theme.colors['secondary-hover']
+ }
+ }),
+ noOptionsMessage: provided => ({
+ ...provided,
+ color: theme.colors['text-secondary']
+ }),
+ option: (provided, state) => {
+ const isNew = state.data?.__isNew__;
+ const isSmall = state.selectProps.size === 'small';
+ return {
+ ...getOptionBackground(state.isSelected, state.isFocused)({
+ theme
+ }),
+ alignItems: 'center',
+ color: state.isDisabled ? theme.colors['text-disabled'] : isNew ? theme.colors.primary : theme.colors.text,
+ cursor: state.isDisabled ? 'not-allowed' : 'pointer',
+ display: 'flex',
+ padding: isSmall ? '3px 14px' : '11px 14px',
+ ...(isNew && {
+ // Gradient creates the 1px divider line at the top edge of the option background
+ backgroundImage: `linear-gradient(${theme.colors['text-disabled']} 1px, transparent 1px)`,
+ backgroundPosition: '0 0',
+ backgroundRepeat: 'no-repeat',
+ backgroundSize: '100% 1px',
+ paddingTop: isSmall ? '11px' : '19px'
+ })
+ };
+ },
+ placeholder: provided => ({
+ ...provided,
+ ...placeholderColor({
+ theme
+ }),
+ overflow: 'hidden',
+ textOverflow: 'ellipsis',
+ whiteSpace: 'nowrap'
+ }),
+ singleValue: provided => ({
+ ...provided,
+ ...textColor({
+ theme
+ }),
+ alignItems: 'center',
+ display: 'flex',
+ marginLeft: 0
+ }),
+ valueContainer: provided => ({
+ ...provided,
+ padding: 0
+ })
+ };
+};
\ No newline at end of file