diff --git a/apps/docs/src/usages/chips.tsx b/apps/docs/src/usages/chips.tsx index cf32901..2e56171 100644 --- a/apps/docs/src/usages/chips.tsx +++ b/apps/docs/src/usages/chips.tsx @@ -1,126 +1,63 @@ -import { Chip, Icon } from 'actify' +import { ChipGroup, ChipItem, useListData, type Selection } from 'actify' -export default () => { - return ( - <> -

Assist chips

-
- - - - speaker - - - - - - - - - - -
- -

Filter chips

-
- console.log(value)}> - - - speaker - - - - -
+import React from 'react' -

Input chips

-
- - - - speaker - - - - - - - - - - - - - - - - -
+export default () => { + const [selected, setSelected] = React.useState(new Set(['Actify'])) + const list = useListData({ + initialItems: [ + { id: 1, name: 'Actify' }, + { id: 2, name: 'Ngroker' }, + { id: 3, name: 'Taildoor' }, + { id: 4, name: 'Hugola' } + ] + }) -

Suggestion chips

-
- - - - speaker - - - - - - - - - - -
- + return ( +
+ + Actify + Ngroker + Taildoor + Hugola + + list.remove(...keys)} + > + {(item) => {item.name}} + + + Laundry + Fitness center + Parking + Swimming pool + Breakfast + +

+ Current selection (controlled):{' '} + {selected === 'all' ? 'all' : [...selected].join(', ')} +

+ + + Actifyjs + + + Ngroker + + + Taildoor + + + Hugola + + +
) } diff --git a/packages/actify/src/components/Chips/AssistChip.tsx b/packages/actify/src/components/Chips/AssistChip.tsx deleted file mode 100644 index 8dba6ea..0000000 --- a/packages/actify/src/components/Chips/AssistChip.tsx +++ /dev/null @@ -1,292 +0,0 @@ -'use client' - -import React, { useId } from 'react' - -import { ChipProps } from './ChipItem' -import { Elevation } from './../Elevation' -import { FocusRing } from './../FocusRing' -import { Ripple } from './../Ripple' -import { tv } from 'tailwind-variants' - -const root = tv({ - base: [ - '[--container-height:var(--md-assist-chip-container-height,32px)]', - '[--disabled-label-text-color:var(--md-assist-chip-disabled-label-text-color,var(--md-sys-color-surface))]', - '[--disabled-label-text-opacity:var(--md-assist-chip-disabled-label-text-opacity,0.38)]', - '[--elevated-container-color:var(--md-assist-chip-elevated-container-color,var(--md-sys-color-surface-container-low,#f7f2fa))]', - '[--elevated-container-elevation:var(--md-assist-chip-elevated-container-elevation,1)]', - '[--elevated-container-shadow-color:var(--md-assist-chip-elevated-container-shadow-color,var(--md-sys-color-shadow,#000))]', - '[--elevated-disabled-container-color:var(--md-assist-chip-elevated-disabled-container-color,var(--md-sys-color-on-surface,#1d1b20))]', - '[--elevated-disabled-container-elevation:var(--md-assist-chip-elevated-disabled-container-elevation,0)]', - '[--elevated-disabled-container-opacity:var(--md-assist-chip-elevated-disabled-container-opacity,0.12)]', - '[--elevated-focus-container-elevation:var(--md-assist-chip-elevated-focus-container-elevation,1)]', - '[--elevated-hover-container-elevation:var(--md-assist-chip-elevated-hover-container-elevation,2)]', - '[--elevated-pressed-container-elevation:var(--md-assist-chip-elevated-pressed-container-elevation,1)]', - '[--focus-label-text-color:var(--md-assist-chip-focus-label-text-color,var(--md-sys-color-on-surface))]', - '[--hover-label-text-color:var(--md-assist-chip-hover-label-text-color,var(--md-sys-color-on-surface))]', - '[--hover-state-layer-color:var(--md-assist-chip-hover-state-layer-color,var(--md-sys-color-on-surface))]', - '[--hover-state-layer-opacity:var(--md-assist-chip-hover-state-layer-opacity,0.08)]', - '[--label-text-color:var(--md-assist-chip-label-text-color,var(--md-sys-color-on-surface))]', - '[--label-text-font:var(--md-assist-chip-label-text-font,var(--md-sys-typescale-label-large-font,var(--md-ref-typeface-plain,Roboto)))]', - '[--label-text-line-height:var(--md-assist-chip-label-text-line-height,var(--md-sys-typescale-label-large-line-height,1.25rem))]', - '[--label-text-size:var(--md-assist-chip-label-text-size,var(--md-sys-typescale-label-large-size,0.875rem))]', - '[--label-text-weight:var(--md-assist-chip-label-text-weight,var(--md-sys-typescale-label-large-weight,var(--md-ref-typeface-weight-medium, 500)))]', - '[--pressed-label-text-color:var(--md-assist-chip-pressed-label-text-color,var(--md-sys-color-on-surface))]', - '[--pressed-state-layer-color:var(--md-assist-chip-pressed-state-layer-color,var(--md-sys-color-on-surface))]', - '[--pressed-state-layer-opacity:var(--md-assist-chip-pressed-state-layer-opacity,0.12)]', - '[--disabled-outline-color:var(--md-assist-chip-disabled-outline-color,var(--md-sys-color-on-surface))]', - '[--disabled-outline-opacity:var(--md-assist-chip-disabled-outline-opacity,0.12)]', - '[--focus-outline-color:var(--md-assist-chip-focus-outline-color,var(--md-sys-color-on-surface))]', - '[--outline-color:var(--md-assist-chip-outline-color,rgb(var(--md-sys-color-outline)))]', - '[--outline-width:var(--md-assist-chip-outline-width,1px)]', - '[--disabled-leading-icon-color:var(--md-assist-chip-disabled-leading-icon-color,var(--md-sys-color-on-surface))]', - '[--disabled-leading-icon-opacity:var(--md-assist-chip-disabled-leading-icon-opacity,0.38)]', - '[--focus-leading-icon-color:var(--md-assist-chip-focus-leading-icon-color,var(--md-sys-color-primary))]', - '[--hover-leading-icon-color:var(--md-assist-chip-hover-leading-icon-color,var(--md-sys-color-primary))]', - '[--leading-icon-color:var(--md-assist-chip-leading-icon-color,var(--md-sys-color-primary))]', - '[--icon-size:var(--md-assist-chip-icon-size,18px)]', - '[--pressed-leading-icon-color:var(--md-assist-chip-pressed-leading-icon-color,var(--md-sys-color-primary))]', - '[--container-shape-start-start:var(--md-assist-chip-container-shape-start-start,var(--md-assist-chip-container-shape,var(--md-sys-shape-corner-small,8px)))]', - '[--container-shape-start-end:var(--md-assist-chip-container-shape-start-end,var(--md-assist-chip-container-shape,var(--md-sys-shape-corner-small,8px)))]', - '[--container-shape-end-end:var(--md-assist-chip-container-shape-end-end,var(--md-assist-chip-container-shape,var(--md-sys-shape-corner-small,8px)))]', - '[--container-shape-end-start:var(--md-assist-chip-container-shape-end-start,var(--md-assist-chip-container-shape,var(--md-sys-shape-corner-small,8px)))]', - '[--leading-space:var(--md-assist-chip-leading-space,16px)]', - '[--trailing-space:var(--md-assist-chip-trailing-space,16px)]', - '[--icon-label-space:var(--md-assist-chip-icon-label-space,8px)]', - '[--with-leading-icon-leading-space:var(--md-assist-chip-with-leading-icon-leading-space,8px)]', - // border - '[border-start-start-radius:var(--container-shape-start-start)]', - '[border-start-end-radius:var(--container-shape-start-end)]', - '[border-end-start-radius:var(--container-shape-end-start)]', - '[border-end-end-radius:var(--container-shape-end-end)]', - 'inline-flex', - 'h-[var(--container-height)]', - 'cursor-pointer', - '[-webkit-tap-highlight-color:rgba(0,0,0,0)]', - '[--md-ripple-hover-color:var(--hover-state-layer-color)]', - '[--md-ripple-hover-opacity:var(--hover-state-layer-opacity)]', - '[--md-ripple-pressed-color:var(--pressed-state-layer-color)]', - '[--md-ripple-pressed-opacity:var(--pressed-state-layer-opacity)]' - ], - variants: { - disabled: { - true: 'pointer-events-none' - } - } -}) - -const container = tv({ - base: [ - 'flex', - 'relative', - 'size-full', - 'box-border', - 'rounded-[inherit]', - // before - 'before:rounded-[inherit]', - 'before:absolute', - 'before:inset-0', - 'before:pointer-events-none' - ], - variants: { - disabled: { - true: 'pointer-events-none', - false: 'cursor-pointer' - } - } -}) - -const outline = tv({ - base: [ - 'inset-0', - 'absolute', - 'rounded-[inherit]', - 'pointer-events-none', - '[border:var(--outline-width)_solid_var(--outline-color)]' - ], - variants: { - disabled: { - true: [ - '[border-color:var(--disabled-outline-color)]', - 'opacity-[--disabled-outline-opacity]' - ] - } - } -}) - -const action = tv({ - base: [ - 'p-0', - 'flex', - 'relative', - 'no-underline', - 'outline-none', - '[border:none]', - 'items-baseline', - 'appearance-none', - '[background:none]', - 'rounded-[inherit]' - ], - variants: { - primary: { - true: ['ps-[var(--leading-space)]', 'pe-[var(--trailing-space)]'] - }, - hasIcon: { - true: '' - } - }, - compoundVariants: [ - { - primary: true, - hasIcon: true, - className: 'ps-[var(--with-leading-icon-leading-space)]' - } - ] -}) - -const icon = tv({ - base: ['z-[1]', 'flex', 'relative', 'self-center', 'fill-current'], - variants: { - leading: { - true: 'text[--leading-icon-color]' - } - } -}) - -const label = tv({ - base: [ - 'flex', - 'z-[1]', - 'h-full', - 'select-none', - 'items-center', - 'text-ellipsis', - 'whitespace-nowrap', - 'font-[--label-text-weight]', - 'text-[--label-text-color]', - 'leading-[--label-text-line-height]', - '[font-family:var(--label-text-font)]', - '[font-size:var(--label-text-size)]' - ], - variants: { - disabled: { - true: [ - 'text-[--disabled-label-text-color]', - 'opacity-[--disabled-label-text-opacity]' - ] - } - } -}) - -const touch = tv({ - base: [ - 'h-12', - 'z-[1]', - 'w-full', - 'absolute', - 'inset-[50%_0_0]', - '-translate-y-1/2' - ] -}) - -const ring = tv({ - base: [ - 'text-primary', - '[--md-focus-ring-shape-start-start:var(--container-shape-start-start)]', - '[--md-focus-ring-shape-start-end:var(--container-shape-start-end)]', - '[--md-focus-ring-shape-end-end:var(--container-shape-end-end)]', - '[--md-focus-ring-shape-end-start:var(--container-shape-end-start)]' - ] -}) - -interface AssitChipProps extends Omit {} - -const AssitChip = (props: AssitChipProps) => { - const { - id, - href, - target, - className, - elevated, - children, - disabled = false, - label: labelString, - ...rest - } = props - - const chipId = id || `actify-assit-chip${useId()}` - - const hasIcon = React.Children.toArray(children).find( - (child) => - // @ts-ignore - child?.type?.displayName == 'Actify.Icon' - ) - ? true - : false - - const renderLeadingIcon = () => { - return ( - - ) - } - - const renderPrimaryAction = ({ - href, - primary - }: { - href?: string - primary: boolean - }) => { - return href ? ( - - {renderLeadingIcon()} - {labelString} - - - ) : ( - - ) - } - - return ( -
-
- {elevated ? ( - - ) : ( - - )} - - - {renderPrimaryAction({ href, primary: true })} -
-
- ) -} - -AssitChip.displayName = 'Actify.AssitChip' - -export { AssitChip } diff --git a/packages/actify/src/components/Chips/Chip.tsx b/packages/actify/src/components/Chips/Chip.tsx index 585d616..77d863e 100644 --- a/packages/actify/src/components/Chips/Chip.tsx +++ b/packages/actify/src/components/Chips/Chip.tsx @@ -1,30 +1,74 @@ -'use client' +import { AriaTagProps, TagAria, useFocusRing, useTag } from 'react-aria' -import { Children, cloneElement, isValidElement } from 'react' -import { ChipProps, ChipProvider } from './ChipContext' +import { FocusRing } from '../FocusRing' +import { Icon } from '../Icon' +import { IconButton } from './../Button' +import { ListState } from 'react-stately' +import React from 'react' +import { Ripple } from '../Ripple' +import clsx from 'clsx' +import styles from './chip.module.css' -import { ChipItem } from './ChipItem' +interface ChipProps extends AriaTagProps { + state: ListState +} + +const Chip = (props: ChipProps) => { + let { item, state } = props + let ref = React.useRef(null) + let { focusProps, isFocusVisible } = useFocusRing({ within: true }) + let { rowProps, gridCellProps, removeButtonProps, allowsRemoving } = useTag( + props, + state, + ref + ) -const Chip = (props: ChipProps) => { - const { children, ...rest } = props return ( - - {Children.map( - children, - (child, index) => - isValidElement(child) && - cloneElement(child, { - index, - // @ts-ignore - ...child.props - }) - )} - +
+
+ {/* outline */} + + {/* focus ring */} + {isFocusVisible && } + {/* ripple */} + + {/* leading icon */} + + + check + + + {item.rendered} + {allowsRemoving && ( + + + close + + + )} +
+
) } -Chip.displayName = 'Actify.Chip' - -export default Object.assign(Chip, { - Item: ChipItem -}) +export { Chip } diff --git a/packages/actify/src/components/Chips/ChipContext.tsx b/packages/actify/src/components/Chips/ChipContext.tsx deleted file mode 100644 index 8b6c8b3..0000000 --- a/packages/actify/src/components/Chips/ChipContext.tsx +++ /dev/null @@ -1,51 +0,0 @@ -'use client' - -import React, { createContext, useContext, useMemo, useState } from 'react' - -export interface ChipProps extends React.PropsWithChildren { - // if there is a selected value, it means a controlled component, need onChange handler - selected?: number[] - defaultSelected?: number[] - onChange?: (value: number[] | []) => void -} - -const ChipContext = createContext({}) - -interface ChipProviderProps extends React.PropsWithChildren {} - -export const ChipProvider = (props: ChipProviderProps) => { - const { selected, defaultSelected, onChange, children } = props - - const isControlled = typeof selected != 'undefined' - const hasDefaultSelected = typeof defaultSelected != 'undefined' - const [internalSelected, setInternalSelected] = useState( - hasDefaultSelected ? defaultSelected : [] - ) - const chipSelected = isControlled ? selected : internalSelected - - const handleChange = (event: any) => { - onChange?.(event) - if (!isControlled) { - setInternalSelected(event) - } - } - - return ( - - {children} - - ) -} - -export const useChip = () => { - const context = useContext(ChipContext) - if (context == null) { - throw new Error('Chip components must be wrapped in ') - } - return context -} diff --git a/packages/actify/src/components/Chips/ChipGroup.tsx b/packages/actify/src/components/Chips/ChipGroup.tsx new file mode 100644 index 0000000..8998e86 --- /dev/null +++ b/packages/actify/src/components/Chips/ChipGroup.tsx @@ -0,0 +1,39 @@ +import type { AriaTagGroupProps } from 'react-aria' +import { Chip } from './Chip' +import { Label } from '../Label' +import React from 'react' +import styles from './chip-group.module.css' +import { useListState } from 'react-stately' +import { useTagGroup } from 'react-aria' + +const ChipGroup = (props: AriaTagGroupProps) => { + const { label, description, errorMessage } = props + const ref = React.useRef(null) + + const state = useListState(props) + const { gridProps, labelProps, descriptionProps, errorMessageProps } = + useTagGroup(props, state, ref) + + return ( +
+ +
+ {[...state.collection].map((item) => ( + + ))} +
+ {description && ( +
+ {description} +
+ )} + {errorMessage && ( +
+ {errorMessage} +
+ )} +
+ ) +} + +export { ChipGroup } diff --git a/packages/actify/src/components/Chips/ChipItem.tsx b/packages/actify/src/components/Chips/ChipItem.tsx deleted file mode 100644 index c2e99a5..0000000 --- a/packages/actify/src/components/Chips/ChipItem.tsx +++ /dev/null @@ -1,34 +0,0 @@ -'use client' - -import { AssitChip } from './AssistChip' -import { FilterChip } from './FilterChip' -import { InputChip } from './InputChip' -import React from 'react' -import { SuggestionChip } from './SuggestionChip' - -export interface ChipProps extends React.ComponentProps<'div'> { - index?: number - href?: string - label?: string - elevated?: boolean - disabled?: boolean - removable?: boolean - removeOnly?: boolean - target?: React.HTMLAttributeAnchorTarget - type?: 'assit' | 'filter' | 'input' | 'suggestion' -} - -const ChipItem = (props: ChipProps) => { - const { type = 'assit', ...rest } = props - - return ( - - {type == 'assit' && } - {type == 'filter' && } - {type == 'input' && } - {type == 'suggestion' && } - - ) -} - -export { ChipItem } diff --git a/packages/actify/src/components/Chips/FilterChip.tsx b/packages/actify/src/components/Chips/FilterChip.tsx deleted file mode 100644 index 3b7644c..0000000 --- a/packages/actify/src/components/Chips/FilterChip.tsx +++ /dev/null @@ -1,381 +0,0 @@ -'use client' - -import React, { useId, useState } from 'react' - -import { ChipProps } from './ChipItem' -import { Elevation } from './../Elevation' -import { FocusRing } from './../FocusRing' -import RemoveButton from './RemoveButton' -import { Ripple } from './../Ripple' -import { motion } from 'framer-motion' -import { tv } from 'tailwind-variants' -import { useChip } from './ChipContext' - -const root = tv({ - base: [ - '[--container-height:var(--md-filter-chip-container-height,32px)]', - '[--disabled-label-text-color:var(--md-filter-chip-disabled-label-text-color,var(--md-sys-color-on-surface))]', - '[--disabled-label-text-opacity:var(--md-filter-chip-disabled-label-text-opacity,0.38)]', - - '[--elevated-container-color:var(--md-filter-chip-elevated-container-color,var(--md-sys-color-surface-container-low,#f7f2fa))]', - '[--elevated-container-elevation:var(--md-filter-chip-elevated-container-elevation,1)]', - '[--elevated-container-shadow-color:var(--md-filter-chip-elevated-container-shadow-color,var(--md-sys-color-shadow,#000))]', - '[--elevated-disabled-container-color:var(--md-filter-chip-elevated-disabled-container-color,var(--md-sys-color-on-surface,#1d1b20))]', - '[--elevated-disabled-container-elevation:var(--md-filter-chip-elevated-disabled-container-elevation,0)]', - '[--elevated-disabled-container-opacity:var(--md-filter-chip-elevated-disabled-container-opacity,0.12)]', - '[--elevated-focus-container-elevation:var(--md-filter-chip-elevated-focus-container-elevation,1)]', - '[--elevated-hover-container-elevation:var(--md-filter-chip-elevated-hover-container-elevation,2)]', - '[--elevated-pressed-container-elevation:var(--md-filter-chip-elevated-pressed-container-elevation,1)]', - - '[--focus-label-text-color:var(--md-filter-chip-focus-label-text-color,var(--md-sys-color-on-surface))]', - '[--hover-label-text-color:var(--md-filter-chip-hover-label-text-color,var(--md-sys-color-on-surface))]', - '[--hover-state-layer-color:var(--md-filter-chip-hover-state-layer-color,var(--md-sys-color-on-surface))]', - '[--hover-state-layer-opacity:var(--md-filter-chip-hover-state-layer-opacity,0.08)]', - '[--label-text-color:var(--md-filter-chip-label-text-color,var(--md-sys-color-on-surface))]', - '[--label-text-font:var(--md-filter-chip-label-text-font,var(--md-sys-typescale-label-large-font,var(--md-ref-typeface-plain,Roboto)))]', - '[--label-text-line-height:var(--md-filter-chip-label-text-line-height,var(--md-sys-typescale-label-large-line-height,1.25rem))]', - '[--label-text-size:var(--md-filter-chip-label-text-size,var(--md-sys-typescale-label-large-size,0.875rem))]', - '[--label-text-weight:var(--md-filter-chip-label-text-weight,var(--md-sys-typescale-label-large-weight,var(--md-ref-typeface-weight-medium, 500)))]', - '[--pressed-label-text-color:var(--md-filter-chip-pressed-label-text-color,var(--md-sys-color-on-surface))]', - '[--pressed-state-layer-color:var(--md-filter-chip-pressed-state-layer-color,var(--md-sys-color-on-surface))]', - '[--pressed-state-layer-opacity:var(--md-filter-chip-pressed-state-layer-opacity,0.12)]', - '[--disabled-outline-color:var(--md-filter-chip-disabled-outline-color,var(--md-sys-color-on-surface))]', - '[--disabled-outline-opacity:var(--md-filter-chip-disabled-outline-opacity,0.12)]', - '[--disabled-trailing-icon-color:var(--md-filter-chip-disabled-trailing-icon-color,var(--md-sys-color-on-surface))]', - '[--disabled-trailing-icon-opacity:var(--md-filter-chip-disabled-trailing-icon-opacity,0.38)]', - '[--focus-outline-color:var(--md-filter-chip-focus-outline-color,var(--md-sys-color-on-surface))]', - '[--outline-color:var(--md-filter-chip-outline-color,rgb(var(--md-sys-color-outline)))]', - '[--outline-width:var(--md-filter-chip-outline-width,1px)]', - - '[--disabled-leading-icon-color:var(--md-filter-chip-disabled-leading-icon-color,var(--md-sys-color-on-surface))]', - '[--disabled-leading-icon-opacity:var(--md-filter-chip-disabled-leading-icon-opacity,0.38)]', - '[--focus-leading-icon-color:var(--md-filter-chip-focus-leading-icon-color,var(--md-sys-color-primary))]', - '[--hover-leading-icon-color:var(--md-filter-chip-hover-leading-icon-color,var(--md-sys-color-primary))]', - '[--leading-icon-color:var(--md-filter-chip-leading-icon-color,var(--md-sys-color-primary))]', - '[--icon-size:var(--md-filter-chip-icon-size,18px)]', - '[--pressed-leading-icon-color:var(--md-filter-chip-pressed-leading-icon-color,var(--md-sys-color-primary))]', - - '[--disabled-trailing-icon-color:var(--md-filter-chip-disabled-trailing-icon-color,var(--md-sys-color-on-surface,#1d1b20))]', - '[--disabled-trailing-icon-opacity:var(--md-filter-chip-disabled-trailing-icon-opacity,0.38)]', - '[--selected-focus-trailing-icon-color:var(--md-filter-chip-selected-focus-trailing-icon-color,var(--md-sys-color-on-secondary-container,#1d192b))]', - '[--selected-hover-trailing-icon-color:var(--md-filter-chip-selected-hover-trailing-icon-color,var(--md-sys-color-on-secondary-container,#1d192b))]', - '[--selected-pressed-trailing-icon-color:var(--md-filter-chip-selected-pressed-trailing-icon-color,var(--md-sys-color-on-secondary-container,#1d192b))]', - '[--selected-trailing-icon-color:var(--md-filter-chip-selected-trailing-icon-color,var(--md-sys-color-on-secondary-container,#1d192b))]', - '[--focus-trailing-icon-color:var(--md-filter-chip-focus-trailing-icon-color,var(--md-sys-color-on-surface-variant,#49454f))]', - '[--hover-trailing-icon-color:var(--md-filter-chip-hover-trailing-icon-color,var(--md-sys-color-on-surface-variant,#49454f))]', - '[--pressed-trailing-icon-color:var(--md-filter-chip-pressed-trailing-icon-color,var(--md-sys-color-on-surface-variant,#49454f))]', - '[--trailing-icon-color:var(--md-filter-chip-trailing-icon-color,var(--md-sys-color-on-surface-variant,#49454f))]', - - '[--container-shape-start-start:var(--md-filter-chip-container-shape-start-start,var(--md-filter-chip-container-shape,var(--md-sys-shape-corner-small,8px)))]', - '[--container-shape-start-end:var(--md-filter-chip-container-shape-start-end,var(--md-filter-chip-container-shape,var(--md-sys-shape-corner-small,8px)))]', - '[--container-shape-end-end:var(--md-filter-chip-container-shape-end-end,var(--md-filter-chip-container-shape,var(--md-sys-shape-corner-small,8px)))]', - '[--container-shape-end-start:var(--md-filter-chip-container-shape-end-start,var(--md-filter-chip-container-shape,var(--md-sys-shape-corner-small,8px)))]', - '[--leading-space:var(--md-filter-chip-leading-space,16px)]', - '[--trailing-space:var(--md-filter-chip-trailing-space,16px)]', - '[--icon-label-space:var(--md-filter-chip-icon-label-space,8px)]', - '[--with-leading-icon-leading-space:var(--md-filter-chip-with-leading-icon-leading-space,8px)]', - '[--with-trailing-icon-trailing-space:var(--md-filter-chip-with-trailing-icon-trailing-space,8px)]', - // border - '[border-start-start-radius:var(--container-shape-start-start)]', - '[border-start-end-radius:var(--container-shape-start-end)]', - '[border-end-start-radius:var(--container-shape-end-start)]', - '[border-end-end-radius:var(--container-shape-end-end)]', - 'inline-flex', - 'h-[var(--container-height)]', - 'cursor-pointer', - '[-webkit-tap-highlight-color:rgba(0,0,0,0)]', - '[--md-ripple-hover-color:var(--hover-state-layer-color)]', - '[--md-ripple-hover-opacity:var(--hover-state-layer-opacity)]', - '[--md-ripple-pressed-color:var(--pressed-state-layer-color)]', - '[--md-ripple-pressed-opacity:var(--pressed-state-layer-opacity)]', - '[--selected-outline-width:var(--md-filter-chip-selected-outline-width,0px)]', - '[--selected-container-color:var(--md-filter-chip-selected-container-color,rgb(var(--md-sys-color-secondary-container)))]', - '[--selected-leading-icon-color:var(--md-filter-chip-selected-leading-icon-color,var(--md-sys-color-on-secondary-container,#1d192b))]' - ], - variants: { - disabled: { - true: 'pointer-events-none' - } - } -}) - -const container = tv({ - base: [ - 'flex', - 'relative', - 'size-full', - 'box-border', - 'rounded-[inherit]', - // before - 'before:rounded-[inherit]', - 'before:absolute', - 'before:inset-0', - 'before:pointer-events-none' - ], - variants: { - disabled: { - true: 'pointer-events-none', - false: 'cursor-pointer' - }, - selected: { - true: [ - '[--md-ripple-hover-color:var(--selected-hover-state-layer-color)]', - '[--md-ripple-hover-opacity:var(--selected-hover-state-layer-opacity)]', - '[--md-ripple-pressed-color:var(--selected-pressed-state-layer-color)]', - '[--md-ripple-pressed-opacity:var(--selected-pressed-state-layer-opacity)]', - // before - 'before:[background:var(--selected-container-color)]' - ] - } - } -}) - -const outline = tv({ - base: [ - 'inset-0', - 'absolute', - 'rounded-[inherit]', - 'pointer-events-none', - '[border:var(--outline-width)_solid_var(--outline-color)]' - ], - variants: { - selected: { - true: '[border-width:var(--selected-outline-width)]' - }, - disabled: { - true: [ - '[border-color:var(--disabled-outline-color)]', - 'opacity-[--disabled-outline-opacity]' - ] - } - } -}) - -const action = tv({ - base: [ - 'p-0', - 'flex', - 'relative', - 'no-underline', - 'outline-none', - '[border:none]', - 'items-baseline', - 'appearance-none', - '[background:none]', - 'rounded-[inherit]' - ], - variants: { - primary: { - true: ['ps-[var(--leading-space)]', 'pe-[var(--trailing-space)]'] - }, - hasIcon: { - true: '' - }, - removable: { - true: 'pe-0' - } - }, - compoundVariants: [ - { - primary: true, - hasIcon: true, - className: 'ps-[var(--with-leading-icon-leading-space)]' - } - ] -}) - -const icon = tv({ - base: ['z-[1]', 'flex', 'relative', 'self-center', 'fill-current'], - variants: { - leading: { - true: 'text[--leading-icon-color]' - } - } -}) - -const checkmark = tv({ - base: ['size-[--icon-size]', 'text-[var(--selected-leading-icon-color)]'] -}) - -const label = tv({ - base: [ - 'flex', - 'z-[1]', - 'h-full', - 'select-none', - 'items-center', - 'text-ellipsis', - 'whitespace-nowrap', - 'font-[--label-text-weight]', - 'text-[--label-text-color]', - 'leading-[--label-text-line-height]', - '[font-family:var(--label-text-font)]', - '[font-size:var(--label-text-size)]' - ], - variants: { - disabled: { - true: [ - 'text-[--disabled-label-text-color]', - 'opacity-[--disabled-label-text-opacity]' - ] - } - } -}) - -const touch = tv({ - base: [ - 'h-12', - 'z-[1]', - 'w-full', - 'absolute', - 'inset-[50%_0_0]', - '-translate-y-1/2' - ] -}) - -const ring = tv({ - base: [ - 'text-primary', - '[--md-focus-ring-shape-start-start:var(--container-shape-start-start)]', - '[--md-focus-ring-shape-start-end:var(--container-shape-start-end)]', - '[--md-focus-ring-shape-end-end:var(--container-shape-end-end)]', - '[--md-focus-ring-shape-end-start:var(--container-shape-end-start)]' - ] -}) - -interface FilterChipProps extends Omit {} - -const FilterChip = (props: FilterChipProps) => { - const { - id, - href, - index, - target, - children, - className, - elevated = false, - disabled = false, - removable = false, - label: labelString, - ...rest - } = props - - const chipId = id || `actify-filter-chip${useId()}` - - const chip = useChip() - const [hide, setHide] = useState(false) - const selected = chip.selected?.includes(index!) - - const hasIcon = React.Children.toArray(children).find( - (child) => - // @ts-ignore - child?.type?.displayName == 'Actify.Icon' - ) - ? true - : false - - const renderLeadingIcon = () => { - if (!selected) { - return ( - hasIcon && ( - - ) - ) - } - return ( - - ) - } - - const renderPrimaryAction = ({ - href, - primary - }: { - href?: string - primary: boolean - }) => { - return href ? ( - - {renderLeadingIcon()} - {labelString} - - - ) : ( - - ) - } - - const handleClick = () => { - if (selected) { - const _index = chip.selected?.findIndex((item) => item == index) - const _selected = [...chip.selected!] - _selected.splice(_index as number, 1) - chip.onChange?.(_selected) - } else { - const _selected = [...chip.selected!] - _selected.push(index!) - chip.onChange?.(_selected) - } - } - - if (hide) { - return null - } - - return ( -
- - {elevated ? ( - - ) : ( - - )} - - - {renderPrimaryAction({ href, primary: true })} - {removable && ( - - )} - -
- ) -} - -FilterChip.displayName = 'Actify.FilterChip' - -export { FilterChip } diff --git a/packages/actify/src/components/Chips/InputChip.tsx b/packages/actify/src/components/Chips/InputChip.tsx deleted file mode 100644 index 17e6b9a..0000000 --- a/packages/actify/src/components/Chips/InputChip.tsx +++ /dev/null @@ -1,339 +0,0 @@ -'use client' - -import React, { useId, useState } from 'react' - -import { ChipProps } from './ChipItem' -import { Elevation } from './../Elevation' -import { FocusRing } from './../FocusRing' -import RemoveButton from './RemoveButton' -import { Ripple } from './../Ripple' -import { tv } from 'tailwind-variants' - -const root = tv({ - base: [ - '[--container-height:var(--md-input-chip-container-height,32px)]', - '[--disabled-label-text-color:var(--md-input-chip-disabled-label-text-color,var(--md-sys-color-on-surface))]', - '[--disabled-label-text-opacity:var(--md-input-chip-disabled-label-text-opacity,0.38)]', - - '[--elevated-container-color:var(--md-input-chip-elevated-container-color,var(--md-sys-color-surface-container-low,#f7f2fa))]', - '[--elevated-container-elevation:var(--md-input-chip-elevated-container-elevation,1)]', - '[--elevated-container-shadow-color:var(--md-input-chip-elevated-container-shadow-color,var(--md-sys-color-shadow,#000))]', - '[--elevated-disabled-container-color:var(--md-input-chip-elevated-disabled-container-color,var(--md-sys-color-on-surface,#1d1b20))]', - '[--elevated-disabled-container-elevation:var(--md-input-chip-elevated-disabled-container-elevation,0)]', - '[--elevated-disabled-container-opacity:var(--md-input-chip-elevated-disabled-container-opacity,0.12)]', - '[--elevated-focus-container-elevation:var(--md-input-chip-elevated-focus-container-elevation,1)]', - '[--elevated-hover-container-elevation:var(--md-input-chip-elevated-hover-container-elevation,2)]', - '[--elevated-pressed-container-elevation:var(--md-input-chip-elevated-pressed-container-elevation,1)]', - - '[--focus-label-text-color:var(--md-input-chip-focus-label-text-color,var(--md-sys-color-on-surface))]', - '[--hover-label-text-color:var(--md-input-chip-hover-label-text-color,var(--md-sys-color-on-surface))]', - '[--hover-state-layer-color:var(--md-input-chip-hover-state-layer-color,var(--md-sys-color-on-surface))]', - '[--hover-state-layer-opacity:var(--md-input-chip-hover-state-layer-opacity,0.08)]', - '[--label-text-color:var(--md-input-chip-label-text-color,var(--on-surface))]', - '[--label-text-font:var(--md-input-chip-label-text-font,var(--md-sys-typescale-label-large-font,var(--md-ref-typeface-plain,Roboto)))]', - '[--label-text-line-height:var(--md-input-chip-label-text-line-height,var(--md-sys-typescale-label-large-line-height,1.25rem))]', - '[--label-text-size:var(--md-input-chip-label-text-size,var(--md-sys-typescale-label-large-size,0.875rem))]', - '[--label-text-weight:var(--md-input-chip-label-text-weight,var(--md-sys-typescale-label-large-weight,var(--md-ref-typeface-weight-medium, 500)))]', - '[--pressed-label-text-color:var(--md-input-chip-pressed-label-text-color,var(--md-sys-color-on-surface)))]', - '[--pressed-state-layer-color:var(--md-input-chip-pressed-state-layer-color,var(--md-sys-color-on-surface))]', - '[--pressed-state-layer-opacity:var(--md-input-chip-pressed-state-layer-opacity,0.12)]', - '[--disabled-outline-color:var(--md-input-chip-disabled-outline-color,var(--md-sys-color-on-surface))]', - '[--disabled-outline-opacity:var(--md-input-chip-disabled-outline-opacity,0.12)]', - '[--disabled-trailing-icon-color:var(--md-filter-chip-disabled-trailing-icon-color,var(--md-sys-color-on-surface))]', - '[--disabled-trailing-icon-opacity:var(--md-filter-chip-disabled-trailing-icon-opacity,0.38)]', - '[--focus-outline-color:var(--md-input-chip-focus-outline-color,var(--md-sys-color-on-surface))]', - '[--outline-color:var(--md-input-chip-outline-color,rgb(var(--md-sys-color-outline)))]', - '[--outline-width:var(--md-input-chip-outline-width,1px)]', - - '[--disabled-leading-icon-color:var(--md-input-chip-disabled-leading-icon-color,var(--md-sys-color-on-surface))]', - '[--disabled-leading-icon-opacity:var(--md-input-chip-disabled-leading-icon-opacity,0.38)]', - '[--focus-leading-icon-color:var(--md-input-chip-focus-leading-icon-color,var(--md-sys-color-primary))]', - '[--hover-leading-icon-color:var(--md-input-chip-hover-leading-icon-color,var(--md-sys-color-primary)]', - '[--leading-icon-color:var(--md-input-chip-leading-icon-color,var(--md-sys-color-primary))]', - '[--icon-size:var(--md-input-chip-icon-size,18px)]', - '[--pressed-leading-icon-color:var(--md-input-chip-pressed-leading-icon-color,var(--md-sys-color-primary))]', - - '[--disabled-trailing-icon-color:var(--md-input-chip-disabled-trailing-icon-color,var(--md-sys-color-on-surface,#1d1b20))]', - '[--disabled-trailing-icon-opacity:var(--md-input-chip-disabled-trailing-icon-opacity,0.38)]', - '[--selected-focus-trailing-icon-color:var(--md-input-chip-selected-focus-trailing-icon-color,var(--md-sys-color-on-secondary-container,#1d192b))]', - '[--selected-hover-trailing-icon-color:var(--md-input-chip-selected-hover-trailing-icon-color,var(--md-sys-color-on-secondary-container,#1d192b))]', - '[--selected-pressed-trailing-icon-color:var(--md-input-chip-selected-pressed-trailing-icon-color,var(--md-sys-color-on-secondary-container,#1d192b))]', - '[--selected-trailing-icon-color:var(--md-input-chip-selected-trailing-icon-color,var(--md-sys-color-on-secondary-container,#1d192b))]', - '[--focus-trailing-icon-color:var(--md-input-chip-focus-trailing-icon-color,var(--md-sys-color-on-surface-variant,#49454f))]', - '[--hover-trailing-icon-color:var(--md-input-chip-hover-trailing-icon-color,var(--md-sys-color-on-surface-variant,#49454f))]', - '[--pressed-trailing-icon-color:var(--md-input-chip-pressed-trailing-icon-color,var(--md-sys-color-on-surface-variant,#49454f))]', - '[--trailing-icon-color:var(--md-input-chip-trailing-icon-color,var(--md-sys-color-on-surface-variant,#49454f))]', - - '[--container-shape-start-start:var(--md-input-chip-container-shape-start-start,var(--md-input-chip-container-shape,var(--md-sys-shape-corner-small,8px)))]', - '[--container-shape-start-end:var(--md-input-chip-container-shape-start-end,var(--md-input-chip-container-shape,var(--md-sys-shape-corner-small,8px)))]', - '[--container-shape-end-end:var(--md-input-chip-container-shape-end-end,var(--md-input-chip-container-shape,var(--md-sys-shape-corner-small,8px)))]', - '[--container-shape-end-start:var(--md-input-chip-container-shape-end-start,var(--md-input-chip-container-shape,var(--md-sys-shape-corner-small,8px)))]', - '[--leading-space:var(--md-input-chip-leading-space,16px)]', - '[--trailing-space:var(--md-input-chip-trailing-space,16px)]', - '[--icon-label-space:var(--md-input-chip-icon-label-space,8px)]', - '[--with-leading-icon-leading-space:var(--md-input-chip-with-leading-icon-leading-space,8px)]', - '[--with-trailing-icon-trailing-space:var(--md-filter-chip-with-trailing-icon-trailing-space,8px)]', - // border - '[border-start-start-radius:var(--container-shape-start-start)]', - '[border-start-end-radius:var(--container-shape-start-end)]', - '[border-end-start-radius:var(--container-shape-end-start)]', - '[border-end-end-radius:var(--container-shape-end-end)]', - 'inline-flex', - 'h-[var(--container-height)]', - 'cursor-pointer', - '[-webkit-tap-highlight-color:rgba(0,0,0,0)]', - '[--md-ripple-hover-color:var(--hover-state-layer-color)]', - '[--md-ripple-hover-opacity:var(--hover-state-layer-opacity)]', - '[--md-ripple-pressed-color:var(--pressed-state-layer-color)]', - '[--md-ripple-pressed-opacity:var(--pressed-state-layer-opacity)]' - ], - variants: { - disabled: { - true: 'pointer-events-none' - } - } -}) - -const container = tv({ - base: [ - 'flex', - 'relative', - 'size-full', - 'box-border', - 'rounded-[inherit]', - // before - 'before:rounded-[inherit]', - 'before:absolute', - 'before:inset-0', - 'before:pointer-events-none' - ], - variants: { - disabled: { - true: 'pointer-events-none', - false: 'cursor-pointer' - } - } -}) - -const outline = tv({ - base: [ - 'inset-0', - 'absolute', - 'rounded-[inherit]', - 'pointer-events-none', - '[border:var(--outline-width)_solid_var(--outline-color)]' - ], - variants: { - disabled: { - true: [ - '[border-color:var(--disabled-outline-color)]', - 'opacity-[--disabled-outline-opacity]' - ] - } - } -}) - -const action = tv({ - base: [ - 'p-0', - 'flex', - 'relative', - 'no-underline', - 'outline-none', - '[border:none]', - 'items-baseline', - 'appearance-none', - '[background:none]', - 'rounded-[inherit]' - ], - variants: { - primary: { - true: ['ps-[var(--leading-space)]', 'pe-[var(--trailing-space)]'] - }, - hasIcon: { - true: '' - }, - removable: { - true: 'pe-0' - } - }, - compoundVariants: [ - { - primary: true, - hasIcon: true, - className: 'ps-[var(--with-leading-icon-leading-space)]' - } - ] -}) - -const icon = tv({ - base: ['z-[1]', 'flex', 'relative', 'self-center', 'fill-current'], - variants: { - leading: { - true: 'text[--leading-icon-color]' - } - } -}) - -const label = tv({ - base: [ - 'flex', - 'z-[1]', - 'h-full', - 'select-none', - 'items-center', - 'text-ellipsis', - 'whitespace-nowrap', - 'font-[--label-text-weight]', - 'text-[--label-text-color]', - 'leading-[--label-text-line-height]', - '[font-family:var(--label-text-font)]', - '[font-size:var(--label-text-size)]' - ], - variants: { - disabled: { - true: [ - 'text-[--disabled-label-text-color]', - 'opacity-[--disabled-label-text-opacity]' - ] - } - } -}) - -const touch = tv({ - base: [ - 'h-12', - 'z-[1]', - 'w-full', - 'absolute', - 'inset-[50%_0_0]', - '-translate-y-1/2' - ] -}) - -const ring = tv({ - base: [ - 'text-primary', - '[--md-focus-ring-shape-start-start:var(--container-shape-start-start)]', - '[--md-focus-ring-shape-start-end:var(--container-shape-start-end)]', - '[--md-focus-ring-shape-end-end:var(--container-shape-end-end)]', - '[--md-focus-ring-shape-end-start:var(--container-shape-end-start)]' - ] -}) - -interface InputChipProps extends Omit {} - -const InputChip = (props: InputChipProps) => { - const { - id, - href, - index, - target, - children, - className, - elevated = false, - disabled = false, - removable = true, - removeOnly = false, - label: content, - ...rest - } = props - - const chipId = id || `actify-assit-chip${useId()}` - - const [hide, setHide] = useState(false) - - const hasIcon = React.Children.toArray(children).find( - (child) => - // @ts-ignore - child?.type?.displayName == 'Actify.Icon' - ) - ? true - : false - - const renderLeadingIcon = () => { - return ( - hasIcon && ( - - ) - ) - } - - const renderPrimaryAction = ({ - href, - primary - }: { - href?: string - primary: boolean - }) => { - if (href) { - return ( - - {renderLeadingIcon()} - {content} - - - ) - } - - if (removeOnly) { - return ( - - {renderLeadingIcon()} - {content} - - - ) - } - - return ( - - ) - } - - if (hide) { - return null - } - - return ( -
-
- {elevated ? ( - - ) : ( - - )} - - - {renderPrimaryAction({ href, primary: true })} - {removable && } -
-
- ) -} - -InputChip.displayName = 'Actify.InputChip' - -export { InputChip } diff --git a/packages/actify/src/components/Chips/RemoveButton.tsx b/packages/actify/src/components/Chips/RemoveButton.tsx deleted file mode 100644 index f21ed92..0000000 --- a/packages/actify/src/components/Chips/RemoveButton.tsx +++ /dev/null @@ -1,96 +0,0 @@ -import React, { useId } from 'react' - -import { FocusRing } from './../FocusRing' -import { Ripple } from './../Ripple' -import { tv } from 'tailwind-variants' - -const action = tv({ - base: [ - 'p-0', - 'flex', - 'relative', - 'no-underline', - 'outline-none', - 'items-center', - 'justify-center', - '[border:none]', - 'appearance-none', - 'rounded-[inherit]', - '[background:none]', - 'ps-[--icon-label-space]', - 'pe-[--with-trailing-icon-trailing-space]' - ] -}) - -const icon = tv({ - base: [ - 'z-[1]', - 'flex', - 'relative', - 'self-center', - 'fill-current', - 'size-[--icon-size]', - 'text-[--trailing-icon-color]' - ], - variants: { - selected: { - true: ['text-[--selected-trailing-icon-color]'] - }, - disabled: { - true: [ - 'text-[--disabled-trailing-icon-color]', - 'opacity-[--disabled-trailing-icon-opacity]' - ] - } - } -}) - -const touch = tv({ - base: [ - 'z-[1]', - 'h-12', - 'w-full', - 'absolute', - 'inset-[50%_0_0]', - '-translate-y-1/2' - ] -}) - -interface RemoveButtonProps extends React.ComponentProps<'button'> { - selected?: boolean - setHide: (hide: boolean) => void -} - -const RemoveButton = (props: RemoveButtonProps) => { - const { selected, disabled, setHide } = props - const id = useId() - - const handleClick = (e: React.MouseEvent) => { - e.stopPropagation() - setHide(true) - } - return ( - - ) -} - -export default RemoveButton diff --git a/packages/actify/src/components/Chips/SuggestionChip.tsx b/packages/actify/src/components/Chips/SuggestionChip.tsx deleted file mode 100644 index 1e1ea85..0000000 --- a/packages/actify/src/components/Chips/SuggestionChip.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import { AssitChip } from './AssistChip' - -export { AssitChip as SuggestionChip } diff --git a/packages/actify/src/components/Chips/chip-group.module.css b/packages/actify/src/components/Chips/chip-group.module.css new file mode 100644 index 0000000..35b4f34 --- /dev/null +++ b/packages/actify/src/components/Chips/chip-group.module.css @@ -0,0 +1,11 @@ +.chip-group { + display: flex; + flex-direction: column; + gap: 4px; +} + +.chip-group [role='grid'] { + display: flex; + flex-wrap: wrap; + gap: 8px; +} diff --git a/packages/actify/src/components/Chips/chip.module.css b/packages/actify/src/components/Chips/chip.module.css new file mode 100644 index 0000000..ea8ee6c --- /dev/null +++ b/packages/actify/src/components/Chips/chip.module.css @@ -0,0 +1,239 @@ +.chip { + --_container-height: var(--md-assist-chip-container-height, 32px); + --_disabled-label-text-color: var( + --md-assist-chip-disabled-label-text-color, + rgb(var(--md-sys-color-on-surface)) + ); + --_disabled-label-text-opacity: var( + --md-assist-chip-disabled-label-text-opacity, + 0.38 + ); + --_elevated-container-color: var( + --md-assist-chip-elevated-container-color, + rgb(var(--md-sys-color-surface-container-low)) + ); + --_elevated-container-elevation: var( + --md-assist-chip-elevated-container-elevation, + 1 + ); + --_elevated-container-shadow-color: var( + --md-assist-chip-elevated-container-shadow-color, + rgb(var(--md-sys-color-shadow)) + ); + --_elevated-disabled-container-color: var( + --md-assist-chip-elevated-disabled-container-color, + rgb(var(--md-sys-color-on-surface)) + ); + --_elevated-disabled-container-elevation: var( + --md-assist-chip-elevated-disabled-container-elevation, + 0 + ); + --_elevated-disabled-container-opacity: var( + --md-assist-chip-elevated-disabled-container-opacity, + 0.12 + ); + --_elevated-focus-container-elevation: var( + --md-assist-chip-elevated-focus-container-elevation, + 1 + ); + --_elevated-hover-container-elevation: var( + --md-assist-chip-elevated-hover-container-elevation, + 2 + ); + --_elevated-pressed-container-elevation: var( + --md-assist-chip-elevated-pressed-container-elevation, + 1 + ); + --_focus-label-text-color: var( + --md-assist-chip-focus-label-text-color, + rgb(var(--md-sys-color-on-surface)) + ); + --_hover-label-text-color: var( + --md-assist-chip-hover-label-text-color, + rgb(var(--md-sys-color-on-surface)) + ); + --_hover-state-layer-color: var( + --md-assist-chip-hover-state-layer-color, + rgb(var(--md-sys-color-on-surface)) + ); + --_hover-state-layer-opacity: var( + --md-assist-chip-hover-state-layer-opacity, + 0.08 + ); + --_label-text-color: var( + --md-assist-chip-label-text-color, + rgb(var(--md-sys-color-on-surface)) + ); + --_label-text-font: var( + --md-assist-chip-label-text-font, + var( + --md-sys-typescale-label-large-font, + var(--md-ref-typeface-plain, Roboto) + ) + ); + --_label-text-line-height: var( + --md-assist-chip-label-text-line-height, + var(--md-sys-typescale-label-large-line-height, 1.25rem) + ); + --_label-text-size: var( + --md-assist-chip-label-text-size, + var(--md-sys-typescale-label-large-size, 0.875rem) + ); + --_label-text-weight: var( + --md-assist-chip-label-text-weight, + var( + --md-sys-typescale-label-large-weight, + var(--md-ref-typeface-weight-medium, 500) + ) + ); + --_pressed-label-text-color: var( + --md-assist-chip-pressed-label-text-color, + rgb(var(--md-sys-color-on-surface)) + ); + --_pressed-state-layer-color: var( + --md-assist-chip-pressed-state-layer-color, + rgb(var(--md-sys-color-on-surface)) + ); + --_pressed-state-layer-opacity: var( + --md-assist-chip-pressed-state-layer-opacity, + 0.12 + ); + --_disabled-outline-color: var( + --md-assist-chip-disabled-outline-color, + rgb(var(--md-sys-color-on-surface)) + ); + --_disabled-outline-opacity: var( + --md-assist-chip-disabled-outline-opacity, + 0.12 + ); + --_focus-outline-color: var( + --md-assist-chip-focus-outline-color, + rgb(var(--md-sys-color-on-surface)) + ); + --_outline-color: var( + --md-assist-chip-outline-color, + rgb(var(--md-sys-color-outline)) + ); + --_outline-width: var(--md-assist-chip-outline-width, 1px); + --_selected-container-color: var( + --md-filter-chip-selected-container-color, + rgb(var(--md-sys-color-secondary-container)) + ); + --_selected-outline-width: var(--md-filter-chip-selected-outline-width, 0px); + --_selected-label-text-color: var( + --md-filter-chip-selected-label-text-color, + rgb(var(--md-sys-color-on-secondary-container)) + ); + --_disabled-leading-icon-color: var( + --md-assist-chip-disabled-leading-icon-color, + rgb(var(--md-sys-color-on-surface)) + ); + --_disabled-leading-icon-opacity: var( + --md-assist-chip-disabled-leading-icon-opacity, + 0.38 + ); + --_focus-leading-icon-color: var( + --md-assist-chip-focus-leading-icon-color, + rgb(var(--md-sys-color-primary)) + ); + --_hover-leading-icon-color: var( + --md-assist-chip-hover-leading-icon-color, + rgb(var(--md-sys-color-primary)) + ); + --_leading-icon-color: var( + --md-assist-chip-leading-icon-color, + rgb(var(--md-sys-color-primary)) + ); + --_icon-size: var(--md-assist-chip-icon-size, 18px); + --_pressed-leading-icon-color: var( + --md-assist-chip-pressed-leading-icon-color, + rgb(var(--md-sys-color-primary)) + ); + --_container-shape-start-start: var( + --md-assist-chip-container-shape-start-start, + var(--md-assist-chip-container-shape, var(--md-sys-shape-corner-small, 8px)) + ); + --_container-shape-start-end: var( + --md-assist-chip-container-shape-start-end, + var(--md-assist-chip-container-shape, var(--md-sys-shape-corner-small, 8px)) + ); + --_container-shape-end-end: var( + --md-assist-chip-container-shape-end-end, + var(--md-assist-chip-container-shape, var(--md-sys-shape-corner-small, 8px)) + ); + --_container-shape-end-start: var( + --md-assist-chip-container-shape-end-start, + var(--md-assist-chip-container-shape, var(--md-sys-shape-corner-small, 8px)) + ); + --_leading-space: var(--md-assist-chip-leading-space, 16px); + --_trailing-space: var(--md-assist-chip-trailing-space, 16px); + --_icon-label-space: var(--md-assist-chip-icon-label-space, 8px); + --_with-leading-icon-leading-space: var( + --md-assist-chip-with-leading-icon-leading-space, + 8px + ); + --_icon-size: var(--md-filter-chip-icon-size, 18px); + outline: none; +} +.cell { + position: relative; + padding-inline-start: var(--_leading-space); + padding-inline-end: var(--_trailing-space); + border-start-start-radius: var(--_container-shape-start-start); + border-start-end-radius: var(--_container-shape-start-end); + border-end-start-radius: var(--_container-shape-end-start); + border-end-end-radius: var(--_container-shape-end-end); + display: inline-flex; + align-items: center; + height: var(--_container-height); + cursor: pointer; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + --md-ripple-hover-color: var(--_hover-state-layer-color); + --md-ripple-hover-opacity: var(--_hover-state-layer-opacity); + --md-ripple-pressed-color: var(--_pressed-state-layer-color); + --md-ripple-pressed-opacity: var(--_pressed-state-layer-opacity); +} +.cell:before { + border-radius: inherit; + content: ''; + inset: 0; + pointer-events: none; + position: absolute; +} +[aria-selected='true'] .cell:before { + background: var(--_selected-container-color); +} +.leading-icon { + display: none; + padding-inline-end: var(--_icon-label-space); +} +[aria-selected='true'] .leading-icon { + display: flex; + z-index: 1; +} +.cell.has-trailing { + padding-inline-end: 0; +} +.label { + z-index: 1; + align-items: center; + color: var(--_label-text-color); + display: flex; + font-family: var(--_label-text-font); + font-size: var(--_label-text-size); + font-weight: var(--_label-text-weight); + height: 100%; + line-height: var(--_label-text-line-height); + overflow: hidden; + user-select: none; +} +[aria-selected='true'] .label { + color: var(--_selected-label-text-color); +} +.outline { + border: var(--_outline-width) solid var(--_outline-color); + border-radius: inherit; + inset: 0; + pointer-events: none; + position: absolute; +} diff --git a/packages/actify/src/components/Chips/index.ts b/packages/actify/src/components/Chips/index.ts index 877198b..0873e26 100644 --- a/packages/actify/src/components/Chips/index.ts +++ b/packages/actify/src/components/Chips/index.ts @@ -1 +1,2 @@ -export { default as Chip } from './Chip' +export { ChipGroup } from './ChipGroup' +export { useListData, Item as ChipItem, type Selection } from 'react-stately'