UNPKG

@workday/canvas-kit-docs

Version:

Documentation components of Canvas Kit components

150 lines (149 loc) • 8.46 kB
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import * as React from 'react'; import { AccessibleHide, AriaLiveRegion, composeHooks, createComponent, createElemPropsHook, createSubcomponent, useUniqueId, } from '@workday/canvas-kit-react/common'; import { system } from '@workday/canvas-tokens-web'; import { calc, createStyles, px2rem } from '@workday/canvas-kit-styling'; import { notificationsIcon, inboxIcon, justifyIcon, assistantIcon, searchIcon, } from '@workday/canvas-system-icons-web'; import { SecondaryButton, TertiaryButton } from '@workday/canvas-kit-react/button'; import { Avatar } from '@workday/canvas-kit-preview-react/avatar'; import { Flex } from '@workday/canvas-kit-react/layout'; import { Tooltip } from '@workday/canvas-kit-react/tooltip'; import { Combobox, useComboboxModel, useComboboxInput, useComboboxLoader, } from '@workday/canvas-kit-react/combobox'; import { InputGroup, TextInput } from '@workday/canvas-kit-react/text-input'; import { StyledMenuItem } from '@workday/canvas-kit-react/menu'; import { SystemIcon } from '@workday/canvas-kit-react/icon'; import { CountBadge } from '@workday/canvas-kit-react/badge'; const tasks = ['Request Time Off', 'Create Expense Report', 'Change Benefits']; const styleOverrides = { headerWrapper: createStyles({ display: 'flex', alignItems: 'center', justifyContent: 'space-between', boxSizing: 'border-box', ...system.type.subtext.large, WebkitFontSmoothing: 'antialiased', MozOsxFontSmoothing: 'grayscale', backgroundColor: system.color.bg.default, padding: system.space.x1, }), flexItems: createStyles({ gap: system.space.x4, alignItems: 'center', marginX: system.space.x3, }), inputGroupInner: createStyles({ marginLeft: '1rem', width: px2rem(20), transition: 'opacity 100ms ease', }), comboboxContainer: createStyles({ margin: 'auto', width: '100%', maxWidth: calc.multiply(system.space.x20, 6), }), comboboxInput: createStyles({ borderRadius: px2rem(1000), width: '20rem', }), comboboxMenuList: createStyles({ maxHeight: px2rem(200), }), menuButtonStyles: createStyles({ textDecoration: 'none', color: system.color.fg.strong, }), notificationContainerStyles: createStyles({ boxSizing: 'border-box', position: 'relative', }), countBadgeStyles: createStyles({ boxSizing: 'border-box', position: 'absolute', top: calc.negate(system.space.x1), insetInlineEnd: calc.negate(system.space.x1), }), actionButtonStyles: createStyles({ gap: system.space.x4, margin: system.space.x4, }), }; const useAutocompleteInput = composeHooks(createElemPropsHook(useComboboxModel)(model => { return { onKeyPress(event) { model.events.show(event); }, }; }), useComboboxInput); const AutoCompleteInput = createSubcomponent(TextInput)({ modelHook: useComboboxModel, elemPropsHook: useAutocompleteInput, })((elemProps, Element) => { return _jsx(Combobox.Input, { as: Element, ...elemProps }); }); export const Basic = () => { const [notifications, setNotifications] = React.useState(0); function handleAdd() { setNotifications(prev => prev + 1); } function handleClear() { setNotifications(0); } return (_jsxs("header", { children: [_jsx(GlobalHeader, { notifications: notifications }), _jsxs(Flex, { cs: styleOverrides.actionButtonStyles, children: [_jsx(SecondaryButton, { onClick: handleAdd, children: "Add notification" }), _jsx(TertiaryButton, { onClick: handleClear, children: "Clear" })] })] })); }; export const GlobalHeader = createComponent('div')({ displayName: 'GlobalHeader', Component: ({ notifications, ...props }) => (_jsxs("div", { className: styleOverrides.headerWrapper, children: [_jsxs(Flex, { cs: styleOverrides.flexItems, children: [_jsx(Tooltip, { title: "Global Navigation", type: "describe", children: _jsx(TertiaryButton, { icon: justifyIcon, cs: styleOverrides.menuButtonStyles, children: "MENU" }) }), _jsx(Tooltip, { title: "Workday Home", children: _jsx(TertiaryButton, { children: _jsx("img", { src: "https://design.workday.com/images/ck-dub-logo-blue.svg", alt: "" }) }) })] }), _jsx(Flex, { cs: styleOverrides.flexItems, children: _jsx(Autocomplete, { "aria-label": "Search Workday" }) }), _jsxs(Flex, { cs: styleOverrides.flexItems, children: [_jsx(Tooltip, { title: "Assistant", children: _jsx(TertiaryButton, { icon: assistantIcon }) }), _jsx(NotificationLiveBadge, { cnt: notifications }), _jsx(Tooltip, { title: "My Tasks", children: _jsx(TertiaryButton, { icon: inboxIcon }) }), _jsx(Tooltip, { title: "Profile", children: _jsx(Avatar, { name: "Logan McNeil", isDecorative: true }) })] })] })), }); const Autocomplete = createComponent('div')({ displayName: 'Autocomplete', Component: props => { const [searchText, setSearchText] = React.useState(''); function handleChange(e) { setSearchText(e.target.value); } const { model, loader } = useComboboxLoader({ // You can start with any number that makes sense. total: 0, // Pick whatever number makes sense for your API pageSize: 20, // A load function that will be called by the loader. You must return a promise that returns // an object like `{items: [], total: 0}`. The `items` will be merged into the loader's cache async load({ pageNumber, pageSize, filter }) { return new Promise(resolve => { // simulate a server response by resolving after a period of time setTimeout(() => { // simulate paging and filtering based on pre-computed items const start = (pageNumber - 1) * pageSize; const end = start + pageSize; const filteredTasks = tasks.filter(i => { if (searchText.trim() === '' || typeof searchText !== 'string') { return true; } return i.toLowerCase().includes(searchText.trim().toLowerCase()); }); const total = filteredTasks.length; const items = filteredTasks.slice(start, end); resolve({ items, total, }); }, 300); }); }, onShow() { // The `shouldLoad` cancels while the combobox menu is hidden, so let's load when it is // visible loader.load(); }, }, useComboboxModel); return (_jsxs(Combobox, { model: model, children: [_jsxs(InputGroup, { children: [_jsx(InputGroup.InnerStart, { cs: styleOverrides.inputGroupInner, children: _jsx(SystemIcon, { icon: searchIcon }) }), _jsx(InputGroup.Input, { as: AutoCompleteInput, cs: styleOverrides.comboboxInput, onChange: handleChange, value: searchText, ...props })] }), _jsx(Combobox.Menu.Popper, { children: _jsx(Combobox.Menu.Card, { children: model.state.items.length === 0 ? (_jsx(StyledMenuItem, { as: "span", children: "No Results Found" })) : (model.state.items.length > 0 && (_jsx(Combobox.Menu.List, { maxHeight: px2rem(200), children: item => _jsx(Combobox.Menu.Item, { children: item }) }))) }) })] })); }, }); const NotificationLiveBadge = createComponent('span')({ displayName: 'NotificationLiveBadge', Component: ({ cnt = 0, ...props }) => { const btnId = useUniqueId(); const badgeId = useUniqueId(); return (_jsxs(Flex, { cs: styleOverrides.notificationContainerStyles, children: [_jsx(Tooltip, { title: "Notifications", children: _jsx(TertiaryButton, { id: btnId, icon: notificationsIcon, "aria-describedby": cnt > 0 ? badgeId : undefined, ...props }) }), _jsx(AriaLiveRegion, { "aria-labelledby": btnId, children: cnt > 0 && (_jsxs(_Fragment, { children: [_jsx(CountBadge, { id: badgeId, count: cnt, limit: 100, cs: styleOverrides.countBadgeStyles }), _jsx(AccessibleHide, { children: "New" })] })) })] })); }, });