From 4639afaaa47e2d25874eaaa90c3c19d99c669a87 Mon Sep 17 00:00:00 2001 From: natoverse Date: Mon, 21 Nov 2022 12:32:15 -0800 Subject: [PATCH] Align ScaleDropdown better with fluent base --- .../theme.ts => ScaleDropdown.hooks.ts} | 87 +++++++++++++------ .../ScaleDropdown/ScaleDropdown.tsx | 32 +++---- .../ScaleDropdown/ScaleDropdown.types.ts | 2 +- ...opdownItem.tsx => ScaleDropdownOption.tsx} | 12 ++- .../components/ScaleDropdown/hooks/size.ts | 37 -------- 5 files changed, 86 insertions(+), 84 deletions(-) rename packages/fluent/src/components/ScaleDropdown/{hooks/theme.ts => ScaleDropdown.hooks.ts} (67%) rename packages/fluent/src/components/ScaleDropdown/{ScaleDropdownItem.tsx => ScaleDropdownOption.tsx} (76%) delete mode 100644 packages/fluent/src/components/ScaleDropdown/hooks/size.ts diff --git a/packages/fluent/src/components/ScaleDropdown/hooks/theme.ts b/packages/fluent/src/components/ScaleDropdown/ScaleDropdown.hooks.ts similarity index 67% rename from packages/fluent/src/components/ScaleDropdown/hooks/theme.ts rename to packages/fluent/src/components/ScaleDropdown/ScaleDropdown.hooks.ts index 3dc41b0..3ab6d3a 100644 --- a/packages/fluent/src/components/ScaleDropdown/hooks/theme.ts +++ b/packages/fluent/src/components/ScaleDropdown/ScaleDropdown.hooks.ts @@ -2,21 +2,30 @@ * Copyright (c) Microsoft. All rights reserved. * Licensed under the MIT license. See LICENSE file in the project. */ -import type { IDropdownOption } from '@fluentui/react' +import type { + IDropdownOption, + IDropdownStyleProps, + IDropdownStyles, + IStyleFunctionOrObject, +} from '@fluentui/react' import type { ContinuousColorScaleFunction, NominalColorScaleFunction, } from '@thematic/core' import { chooseScale } from '@thematic/core' import { useThematic } from '@thematic/react' +import { useSize } from 'ahooks' +import merge from 'lodash-es/merge.js' import type React from 'react' import { useMemo } from 'react' -import type { ChipsProps } from '../ScaleDropdown.types.js' -import { selectColorPalette } from '../ScaleDropdown.utils.js' +import type { ChipsProps } from './ScaleDropdown.types.js' +import { selectColorPalette } from './ScaleDropdown.utils.js' + +const DEFAULT_WIDTH = 200 +const DEFAULT_HEIGHT = 32 const ITEM_LEFT_PADDING = 8 // default right padding in fluent item -const ITEM_BORDER_MODIFIER = 1 // accounts for transparent border on outer container const CARET_PADDING = 28 // defined default in fluent dropdown is 28 (this also aligns with item right padding) export const TEXT_WIDTH = 80 // TODO: adjust this based on font size/max measured const LABEL_HEIGHT = 29 // defined default in fluent dropdown @@ -25,16 +34,26 @@ const LABEL_HEIGHT = 29 // defined default in fluent dropdown // visually we'll keep it lowercase in this app for visual consistency const TITLE_CASE = false +export function useDropdownStyles( + styles?: IStyleFunctionOrObject, +): IStyleFunctionOrObject { + return useMemo( + () => + merge( + { + root: { + textAlign: 'left', + }, + }, + styles, + ), + [styles], + ) +} + export function usePaletteWidth(width: number): number { // subtract space for the caret, pad, text, etc. - return ( - width - - ITEM_BORDER_MODIFIER - - ITEM_LEFT_PADDING - - TEXT_WIDTH - - CARET_PADDING - - ITEM_BORDER_MODIFIER - ) + return width - ITEM_LEFT_PADDING - TEXT_WIDTH - CARET_PADDING } export function usePaletteHeight(height: number, label?: string): number { @@ -43,19 +62,6 @@ export function usePaletteHeight(height: number, label?: string): number { return root / 2 } -/** - * Provides style overrides for root dropdown container - * @returns - */ -export function useContainerStyle(): React.CSSProperties { - return useMemo( - () => ({ - textAlign: 'left', - }), - [], - ) -} - /** * This provides unique style overrides for the dropdown items, * NOT the title. The paddings here are to align the item @@ -66,7 +72,7 @@ export function useItemStyle(width: number): React.CSSProperties { return useMemo( () => ({ width: width - CARET_PADDING, - paddingLeft: ITEM_BORDER_MODIFIER, + paddingLeft: 0, paddingRight: CARET_PADDING, }), [width], @@ -110,3 +116,32 @@ export function useScale( export function usePaletteComponent(key: string): React.FC { return useMemo(() => selectColorPalette(key), [key]) } + +export interface Dimensions { + width: number + height: number +} + +export function useSafeDimensions( + ref: React.RefObject, +): Dimensions { + const dimensions = useSize(ref) + return ( + dimensions || { + width: DEFAULT_WIDTH, + height: DEFAULT_HEIGHT, + } + ) +} + +/** + * Retrieve a non-zero width/height, because collapsible panels can force invalid color arrays + * @param width + * @param height + */ +export function useSafeCollapseDimensions( + width: number, + height: number, +): [number, number] { + return [width <= 0 ? 1 : width, height <= 0 ? 1 : height] +} diff --git a/packages/fluent/src/components/ScaleDropdown/ScaleDropdown.tsx b/packages/fluent/src/components/ScaleDropdown/ScaleDropdown.tsx index eda4663..736c146 100644 --- a/packages/fluent/src/components/ScaleDropdown/ScaleDropdown.tsx +++ b/packages/fluent/src/components/ScaleDropdown/ScaleDropdown.tsx @@ -7,35 +7,35 @@ import { Dropdown } from '@fluentui/react' import type { FC } from 'react' import { useCallback, useRef } from 'react' -import { useSafeDimensions } from './hooks/size.js' import { - useContainerStyle, + useDropdownStyles, useItemStyle, usePaletteHeight, usePaletteWidth, + useSafeDimensions, useThematicScaleOptions, -} from './hooks/theme.js' +} from './ScaleDropdown.hooks.js' import type { ScaleDropdownProps } from './ScaleDropdown.types.js' -import { ScaleDropdownItem } from './ScaleDropdownItem.js' +import { ScaleDropdownOption } from './ScaleDropdownOption.js' /** * Represents a Fluent dropdown of Thematic scale options. * The scale names can be accompanied by a visual rendering of the scale colors. * This bascially extends Dropdown, overriding the options and item rendering. */ -export const ScaleDropdown: FC = props => { +export const ScaleDropdown: FC = ({ styles, ...props }) => { const ref = useRef(null) const { width, height } = useSafeDimensions(ref) + const _styles = useDropdownStyles(styles) const paletteWidth = usePaletteWidth(width) const paletteHeight = usePaletteHeight(height, props.label) - const containerStyle = useContainerStyle() const itemStyle = useItemStyle(width) const options = useThematicScaleOptions() const handleRenderTitle = useCallback( (options: IDropdownOption[] | undefined) => { const firstOption: IDropdownOption = options![0]! return ( - = props => { const handleRenderOption = useCallback( (option: IDropdownOption | undefined) => { return option ? ( - = props => { ) return ( -
- -
+ ) } diff --git a/packages/fluent/src/components/ScaleDropdown/ScaleDropdown.types.ts b/packages/fluent/src/components/ScaleDropdown/ScaleDropdown.types.ts index 03423f1..042e3f1 100644 --- a/packages/fluent/src/components/ScaleDropdown/ScaleDropdown.types.ts +++ b/packages/fluent/src/components/ScaleDropdown/ScaleDropdown.types.ts @@ -10,7 +10,7 @@ import type { export type ScaleDropdownProps = Omit -export interface ScaleDropdownItemProps { +export interface ScaleDropdownOptionProps { option: IDropdownOption paletteWidth: number paletteHeight: number diff --git a/packages/fluent/src/components/ScaleDropdown/ScaleDropdownItem.tsx b/packages/fluent/src/components/ScaleDropdown/ScaleDropdownOption.tsx similarity index 76% rename from packages/fluent/src/components/ScaleDropdown/ScaleDropdownItem.tsx rename to packages/fluent/src/components/ScaleDropdown/ScaleDropdownOption.tsx index 85b9dc3..a72c4c2 100644 --- a/packages/fluent/src/components/ScaleDropdown/ScaleDropdownItem.tsx +++ b/packages/fluent/src/components/ScaleDropdown/ScaleDropdownOption.tsx @@ -5,11 +5,15 @@ import type { FC } from 'react' import { useMemo } from 'react' -import { useSafeCollapseDimensions } from './hooks/size.js' -import { TEXT_WIDTH, usePaletteComponent, useScale } from './hooks/theme.js' -import type { ScaleDropdownItemProps } from './ScaleDropdown.types.js' +import { + TEXT_WIDTH, + usePaletteComponent, + useSafeCollapseDimensions, + useScale, +} from './ScaleDropdown.hooks.js' +import type { ScaleDropdownOptionProps } from './ScaleDropdown.types.js' -export const ScaleDropdownItem: FC = ({ +export const ScaleDropdownOption: FC = ({ option, paletteWidth, paletteHeight, diff --git a/packages/fluent/src/components/ScaleDropdown/hooks/size.ts b/packages/fluent/src/components/ScaleDropdown/hooks/size.ts deleted file mode 100644 index e854f67..0000000 --- a/packages/fluent/src/components/ScaleDropdown/hooks/size.ts +++ /dev/null @@ -1,37 +0,0 @@ -/*! - * Copyright (c) Microsoft. All rights reserved. - * Licensed under the MIT license. See LICENSE file in the project. - */ -import { useSize } from 'ahooks' - -const DEFAULT_WIDTH = 200 -const DEFAULT_HEIGHT = 32 - -export interface Dimensions { - width: number - height: number -} - -export function useSafeDimensions( - ref: React.RefObject, -): Dimensions { - const dimensions = useSize(ref) - return ( - dimensions || { - width: DEFAULT_WIDTH, - height: DEFAULT_HEIGHT, - } - ) -} - -/** - * Retrieve a non-zero width/height, because collapsible panels can force invalid color arrays - * @param width - * @param height - */ -export function useSafeCollapseDimensions( - width: number, - height: number, -): [number, number] { - return [width <= 0 ? 1 : width, height <= 0 ? 1 : height] -}