Skip to content

Commit

Permalink
Merge pull request #452 from AppQuality/develop
Browse files Browse the repository at this point in the history
Add menu/select items stories and add player.shortcuts
  • Loading branch information
d-beezee authored Nov 29, 2024
2 parents d49b93f + 68a7b9e commit 83705c4
Show file tree
Hide file tree
Showing 20 changed files with 488 additions and 99 deletions.
5 changes: 5 additions & 0 deletions src/assets/icons/arrow-left.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icons/arrow-right.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
80 changes: 80 additions & 0 deletions src/stories/dotsMenu/dotsmenuitem.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import type { Meta, StoryObj } from "@storybook/react";
import { StatusRunningIcon } from "../icons";

import { DotsMenu } from ".";

type Args = React.ComponentProps<typeof DotsMenu.Item> & {
contentType?: string;
};

const meta = {
title: "Atoms/DotsMenuItem",
component: DotsMenu.Item,

parameters: {
docs: {
description: {
component: "Available only inside a `DotsMenu` component.",
},
},
},
argTypes: {
contentType: {
options: ["simple", "withMeta"],
control: {
type: "select",
},
},
},

decorators: [
(Story) => (
<DotsMenu isExpanded={true}>
<Story />
</DotsMenu>
),
],

render: ({ contentType, ...args }) => {
return (
<DotsMenu.Item {...args}>
{contentType === "simple" && "Acacia"}
{contentType === "withMeta" && (
<>
Acacia
<DotsMenu.Item.Meta>Daisy</DotsMenu.Item.Meta>
</>
)}
</DotsMenu.Item>
);
},
args: {
contentType: "simple",
value: "acacia",
},
} satisfies Meta<Args>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {
args: {},
};

export const WithMeta: Story = {
args: {
contentType: "withMeta",
},
};

export const Disabled: Story = {
args: {
isDisabled: true,
},
};

export const WithIcon: Story = {
args: {
icon: <StatusRunningIcon />,
},
};
29 changes: 15 additions & 14 deletions src/stories/dropdowns/autocomplete/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import {
IComboboxProps,
IOptGroupProps,
IOptionProps,
Option,
OptionValue,
} from "@zendeskgarden/react-dropdowns.next";
import { useCallback, useEffect, useMemo, useState } from "react";
import useDebounce from "../../../hooks/useDebounce";
import { SelectOption } from "../../selectOption";
import { OptGroup } from "../optGroup";

export interface OnOptionClickArgs {
Expand Down Expand Up @@ -100,13 +100,13 @@ const Autocomplete = ({
isHidden: isHidden(opt, debouncedInputValue),
};
}),
[_options, debouncedInputValue]
[_options, debouncedInputValue],
);

// check if there are visible options
const thereAreVisibleOptions = useMemo(
() => flatOptions(matchingOptions).some((opt) => opt.isHidden !== true),
[matchingOptions]
[matchingOptions],
);

const handleChange = useCallback<NonNullable<IComboboxProps["onChange"]>>(
Expand All @@ -118,16 +118,17 @@ const Autocomplete = ({
if (event.type === "input:change" && event.inputValue !== undefined) {
const sanitizedInputValue = event.inputValue.replace(
/[.*+?^${}()|[\]\\]/giu,
"\\$&"
"\\$&",
);
setInputValue(sanitizedInputValue);
if (typeof onInputChange === "function")
onInputChange(sanitizedInputValue);
}
if (
(event.type === "option:click" || event.type === "input:keyDown:Enter")
&& typeof onOptionClick === "function"
&& event.selectionValue // address the issue of clicking enter on an empty input
(event.type === "option:click" ||
event.type === "input:keyDown:Enter") &&
typeof onOptionClick === "function" &&
event.selectionValue // address the issue of clicking enter on an empty input
) {
setInputValue(undefined);
onOptionClick({
Expand All @@ -136,7 +137,7 @@ const Autocomplete = ({
});
}
},
[]
[],
);

return (
Expand All @@ -146,20 +147,20 @@ const Autocomplete = ({
return (
<OptGroup key={option.id} {...option}>
{option.options.map((opt) => (
<Option key={opt.id} {...opt} />
<SelectOption key={opt.id} {...opt} />
))}
</OptGroup>
);
}
return <Option key={index} {...option} />;
return <SelectOption key={index} {...option} />;
})}
{!thereAreVisibleOptions && (
<Option value="" isDisabled>
<SelectOption value="" isDisabled>
No results found
</Option>
</SelectOption>
)}
{isCreatable && debouncedInputValue && (
<Option
<SelectOption
type="add"
value={debouncedInputValue}
title={debouncedInputValue}
Expand All @@ -171,7 +172,7 @@ const Autocomplete = ({
}}
>
{`Add "${debouncedInputValue}"`}
</Option>
</SelectOption>
)}
</Combobox>
);
Expand Down
26 changes: 11 additions & 15 deletions src/stories/dropdowns/countermultiselect/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import {
Combobox,
Field,
Label,
Option,
} from "@zendeskgarden/react-dropdowns.next";
import { Combobox, Field, Label } from "@zendeskgarden/react-dropdowns.next";
import { useEffect, useState } from "react";
import styled from "styled-components";
import { SelectOption } from "../../selectOption";
import { CounterMultiselectArgs } from "./_types";

const StyledComboBox = styled(Combobox)<{ isPrimary?: boolean }>`
Expand Down Expand Up @@ -36,7 +32,7 @@ const CounterMultiselect = ({
isCompact,
}: CounterMultiselectArgs) => {
const [selectedItems, setSelectedItems] = useState(
options.filter((o) => o.selected)
options.filter((o) => o.selected),
);
const [inputValue, setInputValue] = useState("");
const [matchingOptions, setMatchingOptions] = useState(options);
Expand All @@ -48,8 +44,8 @@ const CounterMultiselect = ({
option.label
.trim()
.toLowerCase()
.indexOf(inputValue.trim().toLowerCase()) !== -1
)
.indexOf(inputValue.trim().toLowerCase()) !== -1,
),
);
}, [inputValue, options]);

Expand All @@ -74,7 +70,7 @@ const CounterMultiselect = ({
? i18n?.counterText
? i18n.counterText(selectedItems.length)
: `Items (${selectedItems.length})`
: i18n?.noItems ?? "No items";
: (i18n?.noItems ?? "No items");
}}
isMultiselectable
onChange={({ type, selectionValue, inputValue }) => {
Expand All @@ -85,7 +81,7 @@ const CounterMultiselect = ({
onChange
) {
const newOptions = options.filter((o) =>
selectionValue.includes(o.itemId.toString())
selectionValue.includes(o.itemId.toString()),
);
onChange(newOptions);
setSelectedItems(newOptions);
Expand All @@ -97,7 +93,7 @@ const CounterMultiselect = ({
}}
>
{options.map((option) => (
<Option
<SelectOption
key={option.itemId}
value={option.itemId.toString()}
label={option.label}
Expand All @@ -106,16 +102,16 @@ const CounterMultiselect = ({
}}
isHidden={
!matchingOptions.some(
(matchingOption) => matchingOption.itemId === option.itemId
(matchingOption) => matchingOption.itemId === option.itemId,
)
}
isSelected={selectedItems.some(
(selectedItem) => selectedItem.itemId === option.itemId
(selectedItem) => selectedItem.itemId === option.itemId,
)}
/>
))}
{matchingOptions.length === 0 && (
<Option
<SelectOption
isDisabled
value=""
label={i18n?.noMatches ?? "No matches found"}
Expand Down
7 changes: 4 additions & 3 deletions src/stories/dropdowns/select/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from "@zendeskgarden/react-dropdowns.next";
import { ComponentProps } from "react";
import styled from "styled-components";
import { SelectOption } from "../../selectOption";
import { SelectArgs } from "./_types";

const StyledComboBox = styled(Combobox)<{ isPrimary?: boolean }>`
Expand Down Expand Up @@ -46,7 +47,7 @@ const Select = ({
onChange={(changeEvent) => {
if (
["input:keyDown:Enter", "option:click"].includes(
changeEvent.type
changeEvent.type,
) &&
changeEvent.selectionValue &&
onSelect
Expand All @@ -62,7 +63,7 @@ const Select = ({
);
};

Select.Option = Option;
Select.Option = SelectOption;

const StyledMenuOption = styled(Option)`
padding-left: ${({ theme }) => theme.space.sm};
Expand All @@ -80,7 +81,7 @@ const StyledMenuOption = styled(Option)`
`;

Select.MenuOption = (
props: Omit<ComponentProps<typeof Select.Option>, "isDisabled">
props: Omit<ComponentProps<typeof Select.Option>, "isDisabled">,
) => {
return <StyledMenuOption {...props} isDisabled />;
};
Expand Down
24 changes: 11 additions & 13 deletions src/stories/multiselect/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
import {
Combobox,
Field,
Label,
Option,
} from "@zendeskgarden/react-dropdowns.next";
import { Combobox, Field, Label } from "@zendeskgarden/react-dropdowns.next";
import { useEffect, useState } from "react";
import { ReactComponent as GridAddIcon } from "../../assets/icons/plus.svg";
import { Separator } from "../dropdowns/menu";
import { SelectOption } from "../selectOption";
import { theme } from "../theme";
import { MultiSelectProps } from "./_types";

Expand All @@ -27,7 +23,7 @@ export const MultiSelect = ({
option.label
.trim()
.toLowerCase()
.indexOf(inputValue.trim().toLowerCase()) !== -1
.indexOf(inputValue.trim().toLowerCase()) !== -1,
);

setMatchingOptions(matchedOptions);
Expand Down Expand Up @@ -76,7 +72,9 @@ export const MultiSelect = ({
}
if (
onChange &&
(type === "fn:setSelectionValue" || type === "option:click" || type === "input:keyDown:Enter") &&
(type === "fn:setSelectionValue" ||
type === "option:click" ||
type === "input:keyDown:Enter") &&
Array.isArray(selectionValue)
) {
const ss = selectionValue.map((s) => {
Expand All @@ -100,13 +98,13 @@ export const MultiSelect = ({
...o,
selected: selectedOptions.some((i) => i.id === o.id),
})),
newOption ? newOption : undefined
newOption ? newOption : undefined,
).then(() => setInputValue(""));
}
}}
>
{options.map((option) => (
<Option
<SelectOption
isHidden={!matchingOptions.some((o) => o.id === option.id)}
key={option.id}
value={option.id.toString()}
Expand All @@ -118,7 +116,7 @@ export const MultiSelect = ({
/>
))}
{matchingOptions.length === 0 && !creatable && (
<Option
<SelectOption
isDisabled
value=""
label={i18n?.noMatches ?? "No matches found"}
Expand All @@ -127,11 +125,11 @@ export const MultiSelect = ({
{creatable &&
inputValue.length > 0 &&
!matchingOptions.find(
(item) => item.label.toLowerCase() === inputValue.toLowerCase()
(item) => item.label.toLowerCase() === inputValue.toLowerCase(),
) ? (
<>
<Separator />
<Option
<SelectOption
tagProps={{ isPill: true }}
value={inputValue}
icon={<GridAddIcon />}
Expand Down
5 changes: 5 additions & 0 deletions src/stories/player/_types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ export interface PlayerArgs extends HTMLAttributes<HTMLVideoElement> {
export interface PlayerI18n {
beforeHighlight?: string;
onHighlight?: string;
playpause?: string;
mute?: string;
observations?: string;
forward?: string;
backward?: string;
}

export interface IBookmark {
Expand Down
Loading

0 comments on commit 83705c4

Please sign in to comment.