mirror of
https://github.com/bitwarden/browser
synced 2025-12-11 22:03:36 +00:00
[PM-21882] Lit Components Cleanup (#14872)
* rename item row component to cipher item row * move CipherItem into CipherItemRow instead of passing a generic children prop * remove redundant embedded stories * add mock data to dropdown button story
This commit is contained in:
@@ -1,83 +0,0 @@
|
|||||||
import { Meta, Controls, Primary } from "@storybook/addon-docs";
|
|
||||||
|
|
||||||
import * as stories from "./cipher-action.lit-stories";
|
|
||||||
|
|
||||||
<Meta title="Components/Ciphers/Cipher Action" of={stories} />
|
|
||||||
|
|
||||||
## Cipher Action
|
|
||||||
|
|
||||||
The `CipherAction` component is a functional UI element that handles actions related to ciphers in a
|
|
||||||
secure environment. Built with the `lit` library and styled for consistency across themes, it
|
|
||||||
provides flexibility and accessibility while supporting various notification types.
|
|
||||||
|
|
||||||
<Primary />
|
|
||||||
<Controls />
|
|
||||||
|
|
||||||
## Props
|
|
||||||
|
|
||||||
| **Prop** | **Type** | **Required** | **Description** |
|
|
||||||
| ------------------ | --------------------------------------------------- | ------------ | -------------------------------------------------------------- |
|
|
||||||
| `handleAction` | `(e: Event) => void` | No | Function to execute when an action is triggered. |
|
|
||||||
| `notificationType` | `NotificationTypes.Change \| NotificationTypes.Add` | Yes | Specifies the type of notification associated with the action. |
|
|
||||||
| `theme` | `Theme` | Yes | The theme to style the component. Must match the `Theme` enum. |
|
|
||||||
|
|
||||||
## Installation and Setup
|
|
||||||
|
|
||||||
1. Ensure the necessary dependencies are installed:
|
|
||||||
|
|
||||||
- `lit`: Used to render the component.
|
|
||||||
|
|
||||||
2. Pass the required props when rendering the component:
|
|
||||||
- `handleAction`: Optional function to handle the triggered action.
|
|
||||||
- `notificationType`: Mandatory type from `NotificationTypes` to define the action context.
|
|
||||||
- `theme`: The styling theme (must be a valid `Theme` enum value).
|
|
||||||
|
|
||||||
## Accessibility (WCAG) Compliance
|
|
||||||
|
|
||||||
The `CipherAction` component is designed to be accessible, ensuring usability across diverse user
|
|
||||||
bases. Below are the key considerations for accessibility:
|
|
||||||
|
|
||||||
### Keyboard Accessibility
|
|
||||||
|
|
||||||
- Fully navigable using the keyboard.
|
|
||||||
- The action can be triggered using the `Enter` or `Space` key for users relying on keyboard
|
|
||||||
interaction.
|
|
||||||
|
|
||||||
### Screen Reader Compatibility
|
|
||||||
|
|
||||||
- The semantic elements used in the `CipherAction` component ensure that assistive technologies can
|
|
||||||
interpret the component correctly.
|
|
||||||
- Text associated with the `notificationType` is programmatically linked, providing clarity for
|
|
||||||
screen reader users.
|
|
||||||
|
|
||||||
### Focus Management
|
|
||||||
|
|
||||||
- The component includes focus styles to ensure visibility during navigation.
|
|
||||||
- Proper focus management ensures the component works seamlessly with keyboard navigation.
|
|
||||||
|
|
||||||
### Visual Feedback
|
|
||||||
|
|
||||||
- Provides distinct visual states for different themes and states:
|
|
||||||
- **Hover:** Adjustments to background, border, and text for enhanced visibility.
|
|
||||||
- **Active:** Highlights the button with a focus state when activated.
|
|
||||||
- **Disabled:** Grays out the component to indicate inactivity.
|
|
||||||
|
|
||||||
## Usage Example
|
|
||||||
|
|
||||||
Here's an example of how to integrate the `CipherAction` component:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
import { CipherAction } from "../../cipher/cipher-action";
|
|
||||||
import { ThemeTypes } from "@bitwarden/common/platform/enums/theme-type.enum";
|
|
||||||
import { NotificationTypes } from "../../../../notification/abstractions/notification-bar";
|
|
||||||
|
|
||||||
const handleAction = (e: Event) => {
|
|
||||||
console.log("Cipher action triggered!", e);
|
|
||||||
};
|
|
||||||
|
|
||||||
<CipherAction
|
|
||||||
handleAction={handleAction}
|
|
||||||
notificationType={NotificationTypes.Change}
|
|
||||||
theme={ThemeTypes.Dark}
|
|
||||||
/>;
|
|
||||||
```
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
import { Meta, Controls, Primary } from "@storybook/addon-docs";
|
|
||||||
|
|
||||||
import * as stories from "./cipher-icon.lit-stories";
|
|
||||||
|
|
||||||
<Meta title="Components/Ciphers/Cipher Icon" of={stories} />
|
|
||||||
|
|
||||||
## Cipher Icon
|
|
||||||
|
|
||||||
The `CipherIcon` component is a versatile icon renderer designed for secure environments. It
|
|
||||||
dynamically supports custom icons provided via URIs or displays a default icon (`Globe`) styled
|
|
||||||
based on the theme and provided properties.
|
|
||||||
|
|
||||||
<Primary />
|
|
||||||
<Controls />
|
|
||||||
|
|
||||||
## Props
|
|
||||||
|
|
||||||
| **Prop** | **Type** | **Required** | **Description** |
|
|
||||||
| -------- | ------------------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
||||||
| `color` | `string` | Yes | A contextual color override applied when the `uri` is not provided, ensuring consistent styling of the default icon. |
|
|
||||||
| `size` | `string` | Yes | A valid CSS `width` value representing the width basis of the graphic. The height adjusts to maintain the original aspect ratio of the graphic. |
|
|
||||||
| `theme` | `Theme` | Yes | The styling theme for the icon, matching the `Theme` enum. |
|
|
||||||
| `uri` | `string` (optional) | No | A URL to an external graphic. If provided, the component displays this icon. If omitted, a default icon (`Globe`) styled with the provided `color` and `theme`. |
|
|
||||||
|
|
||||||
## Installation and Setup
|
|
||||||
|
|
||||||
1. Ensure the necessary dependencies are installed:
|
|
||||||
|
|
||||||
- `lit`: Renders the component.
|
|
||||||
- `@emotion/css`: Styles the component.
|
|
||||||
|
|
||||||
2. Pass the necessary props when using the component:
|
|
||||||
- `color`: Used when no `uri` is provided to style the default icon.
|
|
||||||
- `size`: Defines the width of the icon. Height maintains aspect ratio.
|
|
||||||
- `theme`: Specifies the theme for styling.
|
|
||||||
- `uri` (optional): If provided, this URI is used to display a custom icon.
|
|
||||||
|
|
||||||
## Accessibility (WCAG) Compliance
|
|
||||||
|
|
||||||
The `CipherIcon` component ensures accessible and user-friendly interactions through thoughtful
|
|
||||||
design:
|
|
||||||
|
|
||||||
### Semantic Rendering
|
|
||||||
|
|
||||||
- When the `uri` is provided, the component renders an `<img>` element, which is semantically
|
|
||||||
appropriate for external graphics.
|
|
||||||
- If no `uri` is provided, the default icon is wrapped in a `<span>`, ensuring proper context for
|
|
||||||
screen readers.
|
|
||||||
|
|
||||||
### Visual Feedback
|
|
||||||
|
|
||||||
- The component visually adjusts based on the `size`, `color`, and `theme`, ensuring the icon
|
|
||||||
remains clear and legible across different environments.
|
|
||||||
|
|
||||||
### Keyboard and Screen Reader Support
|
|
||||||
|
|
||||||
- Ensure that any container or parent component provides appropriate `alt` text or labeling when
|
|
||||||
`uri` is used with an `<img>` tag for additional accessibility.
|
|
||||||
|
|
||||||
## Usage Example
|
|
||||||
|
|
||||||
Here's an example of how to integrate the `CipherIcon` component:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
import { CipherIcon } from "./cipher-icon";
|
|
||||||
import { ThemeTypes } from "@bitwarden/common/platform/enums/theme-type.enum";
|
|
||||||
|
|
||||||
<CipherIcon
|
|
||||||
color="blue"
|
|
||||||
size="32px"
|
|
||||||
theme={ThemeTypes.Light}
|
|
||||||
uri="https://example.com/icon.png"
|
|
||||||
/>;
|
|
||||||
```
|
|
||||||
|
|
||||||
This configuration displays a custom icon from the provided URI with a width of 32px, styled for the
|
|
||||||
light theme. If the URI is omitted, the Globe icon is used as the fallback, colored in blue.
|
|
||||||
|
|
||||||
### Default Styles
|
|
||||||
|
|
||||||
- The default styles ensure responsive and clean design:
|
|
||||||
|
|
||||||
- Width: Defined by the size prop.
|
|
||||||
- Height: Automatically adjusts to maintain the aspect ratio.
|
|
||||||
- Fit Content: Ensures the icon does not overflow or distort its container.
|
|
||||||
|
|
||||||
### Notes
|
|
||||||
|
|
||||||
- Always validate the uri provided to ensure it points to a secure and accessible location.
|
|
||||||
- Use the color and theme props for consistent fallback styling when uri is not provided.
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
import { Meta, Controls, Primary } from "@storybook/addon-docs";
|
|
||||||
|
|
||||||
import * as stories from "./cipher-indicator-icon.lit-stories";
|
|
||||||
|
|
||||||
<Meta title="Components/Ciphers/Cipher Indicator Icon" of={stories} />
|
|
||||||
|
|
||||||
## Cipher Info Indicator Icons
|
|
||||||
|
|
||||||
The `CipherInfoIndicatorIcons` component displays a set of icons indicating specific attributes
|
|
||||||
related to cipher information. It supports business and family organization indicators, styled
|
|
||||||
dynamically based on the provided theme.
|
|
||||||
|
|
||||||
<Primary />
|
|
||||||
<Controls />
|
|
||||||
|
|
||||||
## Props
|
|
||||||
|
|
||||||
| **Prop** | **Type** | **Required** | **Description** |
|
|
||||||
| ------------------ | --------- | ------------ | ----------------------------------------------------------------------- |
|
|
||||||
| `showBusinessIcon` | `boolean` | No | Displays the business organization icon when set to `true`. |
|
|
||||||
| `showFamilyIcon` | `boolean` | No | Displays the family organization icon when set to `true`. |
|
|
||||||
| `theme` | `Theme` | Yes | Defines the theme used to style the icons. Must match the `Theme` enum. |
|
|
||||||
|
|
||||||
## Installation and Setup
|
|
||||||
|
|
||||||
1. Ensure the necessary dependencies are installed:
|
|
||||||
|
|
||||||
- `lit`: Renders the component.
|
|
||||||
- `@emotion/css`: Used for styling.
|
|
||||||
|
|
||||||
2. Pass the required props when using the component:
|
|
||||||
- `showBusinessIcon`: A boolean that, when `true`, displays the business icon.
|
|
||||||
- `showFamilyIcon`: A boolean that, when `true`, displays the family icon.
|
|
||||||
- `theme`: Specifies the theme for styling the icons.
|
|
||||||
|
|
||||||
## Accessibility (WCAG) Compliance
|
|
||||||
|
|
||||||
The `CipherInfoIndicatorIcons` component ensures accessibility and usability through its design:
|
|
||||||
|
|
||||||
### Screen Reader Compatibility
|
|
||||||
|
|
||||||
- Icons are rendered as `<svg>` elements, and parent components should provide appropriate labeling
|
|
||||||
or descriptions to convey their meaning to screen readers.
|
|
||||||
|
|
||||||
### Visual Feedback
|
|
||||||
|
|
||||||
- Icons are styled dynamically based on the `theme` to ensure visual clarity and contrast in all
|
|
||||||
supported themes.
|
|
||||||
- The size of the icons is fixed at `12px` in height to maintain a consistent visual appearance.
|
|
||||||
|
|
||||||
## Usage Example
|
|
||||||
|
|
||||||
Here's an example of how to integrate the `CipherInfoIndicatorIcons` component:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
import { CipherInfoIndicatorIcons } from "./cipher-info-indicator-icons";
|
|
||||||
import { ThemeTypes } from "@bitwarden/common/platform/enums/theme-type.enum";
|
|
||||||
|
|
||||||
<CipherInfoIndicatorIcons
|
|
||||||
showBusinessIcon={true}
|
|
||||||
showFamilyIcon={false}
|
|
||||||
theme={ThemeTypes.Dark}
|
|
||||||
/>;
|
|
||||||
```
|
|
||||||
|
|
||||||
This example displays the business organization icon, styled for the dark theme, and omits the
|
|
||||||
family organization icon.
|
|
||||||
|
|
||||||
### Styling Details
|
|
||||||
|
|
||||||
- The component includes the following styles:
|
|
||||||
|
|
||||||
- Icons: Rendered as SVGs with a height of 12px and a width that adjusts to maintain their aspect
|
|
||||||
ratio.
|
|
||||||
- Color: Icons are dynamically styled based on the theme, using muted text colors for a subtle
|
|
||||||
appearance.
|
|
||||||
|
|
||||||
### Notes
|
|
||||||
|
|
||||||
- If neither showBusinessIcon nor showFamilyIcon is set to true, the component renders nothing. This
|
|
||||||
behavior should be handled by the parent component.
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
import { Meta, StoryObj } from "@storybook/web-components";
|
|
||||||
|
|
||||||
import { ThemeTypes } from "@bitwarden/common/platform/enums/theme-type.enum";
|
|
||||||
|
|
||||||
import { NotificationTypes } from "../../../../notification/abstractions/notification-bar";
|
|
||||||
import { CipherAction, CipherActionProps } from "../../cipher/cipher-action";
|
|
||||||
import { mockI18n } from "../mock-data";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
title: "Components/Ciphers/Cipher Action",
|
|
||||||
argTypes: {
|
|
||||||
theme: { control: "select", options: [...Object.values(ThemeTypes)] },
|
|
||||||
notificationType: {
|
|
||||||
control: "select",
|
|
||||||
options: [NotificationTypes.Change, NotificationTypes.Add],
|
|
||||||
},
|
|
||||||
handleAction: { control: false },
|
|
||||||
},
|
|
||||||
args: {
|
|
||||||
theme: ThemeTypes.Light,
|
|
||||||
notificationType: NotificationTypes.Change,
|
|
||||||
handleAction: () => alert("Action triggered!"),
|
|
||||||
i18n: mockI18n,
|
|
||||||
},
|
|
||||||
} as Meta<CipherActionProps>;
|
|
||||||
|
|
||||||
const Template = (args: CipherActionProps) => CipherAction({ ...args });
|
|
||||||
|
|
||||||
export const Default: StoryObj<CipherActionProps> = {
|
|
||||||
render: Template,
|
|
||||||
};
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
import { Meta, StoryObj } from "@storybook/web-components";
|
|
||||||
import { html } from "lit";
|
|
||||||
|
|
||||||
import { ThemeTypes } from "@bitwarden/common/platform/enums/theme-type.enum";
|
|
||||||
|
|
||||||
import { CipherIcon, CipherIconProps } from "../../cipher/cipher-icon";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
title: "Components/Ciphers/Cipher Icon",
|
|
||||||
argTypes: {
|
|
||||||
color: { control: "color" },
|
|
||||||
size: { control: "text" },
|
|
||||||
theme: { control: "select", options: [...Object.values(ThemeTypes)] },
|
|
||||||
uri: { control: "text" },
|
|
||||||
},
|
|
||||||
args: {
|
|
||||||
size: "50px",
|
|
||||||
theme: ThemeTypes.Light,
|
|
||||||
uri: "",
|
|
||||||
},
|
|
||||||
} as Meta<CipherIconProps>;
|
|
||||||
|
|
||||||
const Template = (args: CipherIconProps) => {
|
|
||||||
return html`
|
|
||||||
<div style="width: ${args.size}; height: ${args.size}; overflow: hidden;">
|
|
||||||
${CipherIcon({ ...args })}
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Default: StoryObj<CipherIconProps> = {
|
|
||||||
render: Template,
|
|
||||||
};
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
import { Meta, StoryObj } from "@storybook/web-components";
|
|
||||||
import { html } from "lit";
|
|
||||||
|
|
||||||
import { ThemeTypes } from "@bitwarden/common/platform/enums/theme-type.enum";
|
|
||||||
|
|
||||||
import {
|
|
||||||
CipherInfoIndicatorIcons,
|
|
||||||
CipherInfoIndicatorIconsProps,
|
|
||||||
} from "../../cipher/cipher-indicator-icons";
|
|
||||||
import { OrganizationCategories } from "../../cipher/types";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
title: "Components/Ciphers/Cipher Indicator Icons",
|
|
||||||
argTypes: {
|
|
||||||
theme: { control: "select", options: [...Object.values(ThemeTypes)] },
|
|
||||||
},
|
|
||||||
args: {
|
|
||||||
theme: ThemeTypes.Light,
|
|
||||||
organizationCategories: [...Object.values(OrganizationCategories)],
|
|
||||||
},
|
|
||||||
} as Meta<CipherInfoIndicatorIconsProps>;
|
|
||||||
|
|
||||||
const Template: StoryObj<CipherInfoIndicatorIconsProps>["render"] = (args) =>
|
|
||||||
html`<div>${CipherInfoIndicatorIcons({ ...args })}</div>`;
|
|
||||||
|
|
||||||
export const Default: StoryObj<CipherInfoIndicatorIconsProps> = {
|
|
||||||
render: Template,
|
|
||||||
};
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
import { Meta, StoryObj } from "@storybook/web-components";
|
|
||||||
|
|
||||||
import { ThemeTypes } from "@bitwarden/common/platform/enums/theme-type.enum";
|
|
||||||
|
|
||||||
import { CipherInfo, CipherInfoProps } from "../../cipher/cipher-info";
|
|
||||||
import { mockCiphers } from "../mock-data";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
title: "Components/Ciphers/Cipher Info",
|
|
||||||
argTypes: {
|
|
||||||
theme: { control: "select", options: [...Object.values(ThemeTypes)] },
|
|
||||||
},
|
|
||||||
args: {
|
|
||||||
cipher: mockCiphers[0],
|
|
||||||
theme: ThemeTypes.Light,
|
|
||||||
},
|
|
||||||
} as Meta<CipherInfoProps>;
|
|
||||||
|
|
||||||
const Template = (args: CipherInfoProps) => CipherInfo({ ...args });
|
|
||||||
|
|
||||||
export const Default: StoryObj<CipherInfoProps> = {
|
|
||||||
render: Template,
|
|
||||||
};
|
|
||||||
@@ -4,6 +4,7 @@ import { ThemeTypes } from "@bitwarden/common/platform/enums/theme-type.enum";
|
|||||||
|
|
||||||
import { themes } from "../../constants/styles";
|
import { themes } from "../../constants/styles";
|
||||||
import { ButtonRow, ButtonRowProps } from "../../rows/button-row";
|
import { ButtonRow, ButtonRowProps } from "../../rows/button-row";
|
||||||
|
import { mockBrowserI18nGetMessage } from "../mock-data";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: "Components/Rows/Button Row",
|
title: "Components/Rows/Button Row",
|
||||||
@@ -15,6 +16,49 @@ export default {
|
|||||||
window.alert("Button clicked!");
|
window.alert("Button clicked!");
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
selectButtons: [
|
||||||
|
{
|
||||||
|
id: "select-1",
|
||||||
|
label: "select 1",
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
text: "item 1",
|
||||||
|
value: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: true,
|
||||||
|
text: "item 2",
|
||||||
|
value: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "item 3",
|
||||||
|
value: 3,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "select-2",
|
||||||
|
label: "select 2",
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
text: "item a",
|
||||||
|
value: "a",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "item b",
|
||||||
|
value: "b",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "item c",
|
||||||
|
value: "c",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "item d",
|
||||||
|
value: "d",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
} as Meta<ButtonRowProps>;
|
} as Meta<ButtonRowProps>;
|
||||||
|
|
||||||
@@ -51,3 +95,10 @@ export const Dark: StoryObj<ButtonRowProps> = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
window.chrome = {
|
||||||
|
...window.chrome,
|
||||||
|
i18n: {
|
||||||
|
getMessage: mockBrowserI18nGetMessage,
|
||||||
|
},
|
||||||
|
} as typeof chrome;
|
||||||
|
|||||||
@@ -3,30 +3,30 @@ import { Meta, StoryObj } from "@storybook/web-components";
|
|||||||
import { ThemeTypes } from "@bitwarden/common/platform/enums/theme-type.enum";
|
import { ThemeTypes } from "@bitwarden/common/platform/enums/theme-type.enum";
|
||||||
|
|
||||||
import { NotificationTypes } from "../../../../notification/abstractions/notification-bar";
|
import { NotificationTypes } from "../../../../notification/abstractions/notification-bar";
|
||||||
import { CipherItem, CipherItemProps } from "../../cipher/cipher-item";
|
import { CipherItemRow, CipherItemRowProps } from "../../rows/cipher-item-row";
|
||||||
import { mockCiphers, mockI18n } from "../mock-data";
|
import { mockCiphers, mockI18n } from "../mock-data";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: "Components/Ciphers/Cipher Item",
|
title: "Components/Rows/Cipher Item Row",
|
||||||
argTypes: {
|
argTypes: {
|
||||||
theme: { control: "select", options: [...Object.values(ThemeTypes)] },
|
theme: { control: "select", options: [...Object.values(ThemeTypes)] },
|
||||||
handleAction: { control: false },
|
|
||||||
notificationType: {
|
notificationType: {
|
||||||
control: "select",
|
control: "select",
|
||||||
options: [NotificationTypes.Change, NotificationTypes.Add],
|
options: [...Object.values(NotificationTypes)],
|
||||||
},
|
},
|
||||||
|
handleAction: { control: false },
|
||||||
},
|
},
|
||||||
args: {
|
args: {
|
||||||
cipher: mockCiphers[0],
|
cipher: mockCiphers[0],
|
||||||
theme: ThemeTypes.Light,
|
|
||||||
notificationType: NotificationTypes.Change,
|
|
||||||
handleAction: () => alert("Clicked"),
|
|
||||||
i18n: mockI18n,
|
i18n: mockI18n,
|
||||||
|
notificationType: NotificationTypes.Change,
|
||||||
|
theme: ThemeTypes.Light,
|
||||||
|
handleAction: () => window.alert("clicked!"),
|
||||||
},
|
},
|
||||||
} as Meta<CipherItemProps>;
|
} as Meta<CipherItemRowProps>;
|
||||||
|
|
||||||
const Template = (args: CipherItemProps) => CipherItem({ ...args });
|
const Template = (props: CipherItemRowProps) => CipherItemRow({ ...props });
|
||||||
|
|
||||||
export const Default: StoryObj<CipherItemProps> = {
|
export const Default: StoryObj<CipherItemRowProps> = {
|
||||||
render: Template,
|
render: Template,
|
||||||
};
|
};
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
import { Meta, StoryObj } from "@storybook/web-components";
|
|
||||||
|
|
||||||
import { ThemeTypes } from "@bitwarden/common/platform/enums/theme-type.enum";
|
|
||||||
|
|
||||||
import { ItemRow, ItemRowProps } from "../../rows/item-row";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
title: "Components/Rows/Item Row",
|
|
||||||
argTypes: {
|
|
||||||
theme: { control: "select", options: [...Object.values(ThemeTypes)] },
|
|
||||||
children: { control: "object" },
|
|
||||||
},
|
|
||||||
args: {
|
|
||||||
theme: ThemeTypes.Light,
|
|
||||||
},
|
|
||||||
} as Meta<ItemRowProps>;
|
|
||||||
|
|
||||||
const Template = (args: ItemRowProps) => ItemRow({ ...args });
|
|
||||||
|
|
||||||
export const Default: StoryObj<ItemRowProps> = {
|
|
||||||
render: Template,
|
|
||||||
};
|
|
||||||
@@ -4,11 +4,10 @@ import { html } from "lit";
|
|||||||
import { Theme, ThemeTypes } from "@bitwarden/common/platform/enums";
|
import { Theme, ThemeTypes } from "@bitwarden/common/platform/enums";
|
||||||
|
|
||||||
import { NotificationType } from "../../../notification/abstractions/notification-bar";
|
import { NotificationType } from "../../../notification/abstractions/notification-bar";
|
||||||
import { CipherItem } from "../cipher";
|
|
||||||
import { NotificationCipherData } from "../cipher/types";
|
import { NotificationCipherData } from "../cipher/types";
|
||||||
import { I18n } from "../common-types";
|
import { I18n } from "../common-types";
|
||||||
import { scrollbarStyles, spacing, themes, typography } from "../constants/styles";
|
import { scrollbarStyles, spacing, themes, typography } from "../constants/styles";
|
||||||
import { ItemRow } from "../rows/item-row";
|
import { CipherItemRow } from "../rows/cipher-item-row";
|
||||||
|
|
||||||
export const componentClassPrefix = "notification-body";
|
export const componentClassPrefix = "notification-body";
|
||||||
|
|
||||||
@@ -37,16 +36,13 @@ export function NotificationBody({
|
|||||||
return html`
|
return html`
|
||||||
<div class=${notificationBodyStyles({ isSafari, theme })}>
|
<div class=${notificationBodyStyles({ isSafari, theme })}>
|
||||||
${ciphers.map((cipher) =>
|
${ciphers.map((cipher) =>
|
||||||
ItemRow({
|
CipherItemRow({
|
||||||
theme,
|
|
||||||
children: CipherItem({
|
|
||||||
cipher,
|
cipher,
|
||||||
|
theme,
|
||||||
i18n,
|
i18n,
|
||||||
notificationType,
|
notificationType,
|
||||||
theme,
|
|
||||||
handleAction: handleEditOrUpdateAction,
|
handleAction: handleEditOrUpdateAction,
|
||||||
}),
|
}),
|
||||||
}),
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
import { css } from "@emotion/css";
|
||||||
|
import { html } from "lit";
|
||||||
|
|
||||||
|
import { Theme } from "@bitwarden/common/platform/enums";
|
||||||
|
|
||||||
|
import { NotificationType } from "../../../notification/abstractions/notification-bar";
|
||||||
|
import { CipherItem } from "../cipher/cipher-item";
|
||||||
|
import { NotificationCipherData } from "../cipher/types";
|
||||||
|
import { I18n } from "../common-types";
|
||||||
|
import { spacing, themes, typography } from "../constants/styles";
|
||||||
|
|
||||||
|
export type CipherItemRowProps = {
|
||||||
|
cipher: NotificationCipherData;
|
||||||
|
i18n: I18n;
|
||||||
|
notificationType?: NotificationType;
|
||||||
|
theme: Theme;
|
||||||
|
handleAction: (e: Event) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function CipherItemRow({
|
||||||
|
cipher,
|
||||||
|
i18n,
|
||||||
|
notificationType,
|
||||||
|
theme,
|
||||||
|
handleAction,
|
||||||
|
}: CipherItemRowProps) {
|
||||||
|
return html`
|
||||||
|
<div class=${cipherItemRowStyles({ theme })}>
|
||||||
|
${CipherItem({
|
||||||
|
cipher,
|
||||||
|
i18n,
|
||||||
|
notificationType,
|
||||||
|
theme,
|
||||||
|
handleAction,
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cipherItemRowStyles = ({ theme }: { theme: Theme }) => css`
|
||||||
|
${typography.body1}
|
||||||
|
|
||||||
|
gap: ${spacing["2"]};
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
border-width: 0 0 0.5px 0;
|
||||||
|
border-style: solid;
|
||||||
|
border-radius: ${spacing["2"]};
|
||||||
|
border-color: ${themes[theme].secondary["300"]};
|
||||||
|
background-color: ${themes[theme].background.DEFAULT};
|
||||||
|
padding: ${spacing["2"]} ${spacing["3"]};
|
||||||
|
min-height: min-content;
|
||||||
|
max-height: 52px;
|
||||||
|
overflow-x: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
color: ${themes[theme].text.main};
|
||||||
|
font-weight: 400;
|
||||||
|
|
||||||
|
> div {
|
||||||
|
:first-child {
|
||||||
|
flex: 3 3 75%;
|
||||||
|
min-width: 25%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:not(:first-child) {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
justify-content: flex-end;
|
||||||
|
max-width: 25%;
|
||||||
|
|
||||||
|
> button {
|
||||||
|
max-width: min-content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
import { css } from "@emotion/css";
|
|
||||||
import { html, TemplateResult } from "lit";
|
|
||||||
|
|
||||||
import { Theme, ThemeTypes } from "@bitwarden/common/platform/enums";
|
|
||||||
|
|
||||||
import { spacing, themes, typography } from "../../../content/components/constants/styles";
|
|
||||||
|
|
||||||
export type ItemRowProps = {
|
|
||||||
theme: Theme;
|
|
||||||
children: TemplateResult | TemplateResult[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ItemRow({ theme = ThemeTypes.Light, children }: ItemRowProps) {
|
|
||||||
return html` <div class=${itemRowStyles({ theme })}>${children}</div> `;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const itemRowStyles = ({ theme }: { theme: Theme }) => css`
|
|
||||||
${typography.body1}
|
|
||||||
|
|
||||||
gap: ${spacing["2"]};
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
border-width: 0 0 0.5px 0;
|
|
||||||
border-style: solid;
|
|
||||||
border-radius: ${spacing["2"]};
|
|
||||||
border-color: ${themes[theme].secondary["300"]};
|
|
||||||
background-color: ${themes[theme].background.DEFAULT};
|
|
||||||
padding: ${spacing["2"]} ${spacing["3"]};
|
|
||||||
min-height: min-content;
|
|
||||||
max-height: 52px;
|
|
||||||
overflow-x: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
color: ${themes[theme].text.main};
|
|
||||||
font-weight: 400;
|
|
||||||
|
|
||||||
> div {
|
|
||||||
:first-child {
|
|
||||||
flex: 3 3 75%;
|
|
||||||
min-width: 25%;
|
|
||||||
}
|
|
||||||
|
|
||||||
:not(:first-child) {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
justify-content: flex-end;
|
|
||||||
max-width: 25%;
|
|
||||||
|
|
||||||
> button {
|
|
||||||
max-width: min-content;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
Reference in New Issue
Block a user