= createStore(
+ combineReducers({
+ calling: (state = {}) => state,
+ conversations: (
+ state = {
+ conversationLookup: {},
+ targetedConversationPanels: {},
+ }
+ ) => state,
+ globalModals: (state = {}) => state,
+ user: (state = {}) => state,
+ })
+);
+
+// eslint-disable-next-line
+const noop = () => {};
+
+window.Whisper = window.Whisper || {};
+window.Whisper.events = {
+ on: noop,
+};
+
+window.SignalContext = {
+ i18n,
+
+ activeWindowService: {
+ isActive: () => true,
+ registerForActive: noop,
+ unregisterForActive: noop,
+ registerForChange: noop,
+ unregisterForChange: noop,
+ },
+
+ nativeThemeListener: {
+ getSystemTheme: () => 'light',
+ subscribe: noop,
+ unsubscribe: noop,
+ update: () => 'light',
+ },
+ Settings: {
+ themeSetting: {
+ getValue: async () => 'light',
+ setValue: async () => 'light',
+ },
+ waitForChange: () => new Promise(noop),
+ },
+ OS: {
+ hasCustomTitleBar: () => false,
+ getClassName: () => '',
+ platform: '',
+ release: '',
+ },
+ usernames: {
+ hash: input => Buffer.from(input),
+ } as any,
+ config: {} as any,
+
+ getHourCyclePreference: () => HourCyclePreference.UnknownPreference,
+ getPreferredSystemLocales: () => ['en'],
+ getResolvedMessagesLocaleDirection: () => 'ltr',
+};
+
+window.i18n = i18n;
+window.ConversationController = window.ConversationController || {};
+window.ConversationController.isSignalConversationId = () => false;
+window.ConversationController.onConvoMessageMount = noop;
+window.reduxStore = mockStore;
const withModeAndThemeProvider = (Story, context) => {
const theme =
@@ -75,7 +152,29 @@ const withModeAndThemeProvider = (Story, context) => {
);
};
-export const decorators = [withModeAndThemeProvider];
+function withMockStoreProvider(Story, context) {
+ return (
+
+
+
+ );
+}
+
+function withScrollLockProvider(Story, context) {
+ return (
+ {})}
+ >
+
+
+ );
+}
+
+export const decorators = [
+ withModeAndThemeProvider,
+ withMockStoreProvider,
+ withScrollLockProvider,
+];
export const parameters = {
axe: {
diff --git a/.storybook/webpack.config.js b/.storybook/webpack.config.js
deleted file mode 100644
index c11fdbe046c4..000000000000
--- a/.storybook/webpack.config.js
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2019 Signal Messenger, LLC
-// SPDX-License-Identifier: AGPL-3.0-only
-
-const webpack = require('webpack');
-
-module.exports = ({ config }) => {
- config.entry.unshift('!!style-loader!css-loader!sanitize.css');
-
- config.cache = {
- type: 'filesystem',
- };
-
- config.module.rules.unshift({
- test: /\.scss$/,
- use: [
- { loader: 'style-loader' },
- { loader: 'css-loader?modules=true&localsConvention=camelCaseOnly' },
- { loader: 'sass-loader' },
- ],
- });
-
- config.node = { global: true };
-
- config.externals = {
- net: 'commonjs net',
- vm: 'commonjs vm',
- fs: 'commonjs fs',
- async_hooks: 'commonjs async_hooks',
- module: 'commonjs module',
- stream: 'commonjs stream',
- tls: 'commonjs tls',
- dns: 'commonjs dns',
- http: 'commonjs http',
- https: 'commonjs https',
- os: 'commonjs os',
- constants: 'commonjs constants',
- zlib: 'commonjs zlib',
- '@signalapp/libsignal-client': 'commonjs @signalapp/libsignal-client',
- '@signalapp/libsignal-client/zkgroup':
- 'commonjs @signalapp/libsignal-client/zkgroup',
- '@signalapp/ringrtc': 'commonjs @signalapp/ringrtc',
- '@signalapp/better-sqlite3': 'commonjs @signalapp/better-sqlite3',
- electron: 'commonjs electron',
- 'fs-xattr': 'commonjs fs-xattr',
- fsevents: 'commonjs fsevents',
- 'mac-screen-capture-permissions': 'commonjs mac-screen-capture-permissions',
- sass: 'commonjs sass',
- bufferutil: 'commonjs bufferutil',
- 'utf-8-validate': 'commonjs utf-8-validate',
- };
-
- return config;
-};
diff --git a/.yarnclean b/.yarnclean
index 4593ef707b33..230d0afc6570 100644
--- a/.yarnclean
+++ b/.yarnclean
@@ -41,3 +41,6 @@ Gruntfile.js
# asset directories
!nyc/node_modules/istanbul-reports/lib/html/assets
+
+# bad matches
+!patch-package/node_modules/yaml/dist/doc
diff --git a/package.json b/package.json
index cc393d360b8c..f54e3f8553b5 100644
--- a/package.json
+++ b/package.json
@@ -62,11 +62,11 @@
"clean-transpile": "yarn run clean-transpile-once && yarn run clean-transpile-once",
"open-coverage": "open coverage/lcov-report/index.html",
"ready": "npm-run-all --print-label clean-transpile generate --parallel lint lint-deps lint-intl test-node test-electron",
- "dev": "run-p --print-label dev:*",
- "dev:transpile": "run-p \"check:types --watch\" dev:esbuild",
- "dev:esbuild": "node scripts/esbuild.js --watch",
- "dev:storybook": "cross-env SIGNAL_ENV=storybook start-storybook -p 6006 -s ./",
- "dev:sass": "yarn sass --watch",
+ "dev": "yarn build-protobuf && cross-env SIGNAL_ENV=storybook storybook dev --port 6006",
+ "build:storybook": "yarn build-protobuf && cross-env SIGNAL_ENV=storybook storybook build",
+ "test:storybook": "yarn build:storybook && run-p --race test:storybook:*",
+ "test:storybook:serve": "http-server storybook-static --port 6006 --silent",
+ "test:storybook:test": "wait-on http://127.0.0.1:6006/ --timeout 5000 && test-storybook",
"build": "run-s --print-label generate build:esbuild:prod build:release",
"build-linux": "yarn generate && yarn build:esbuild:prod && yarn build:release -- --publish=never",
"build:acknowledgments": "node scripts/generate-acknowledgments.js",
@@ -184,33 +184,33 @@
"zod": "3.21.4"
},
"devDependencies": {
- "@babel/core": "7.14.3",
- "@babel/plugin-proposal-class-properties": "7.17.12",
- "@babel/plugin-proposal-nullish-coalescing-operator": "7.17.12",
- "@babel/plugin-proposal-optional-chaining": "7.17.12",
- "@babel/plugin-transform-runtime": "7.18.2",
- "@babel/plugin-transform-typescript": "7.18.4",
- "@babel/preset-react": "7.17.12",
- "@babel/preset-typescript": "7.17.12",
+ "@babel/core": "7.23.0",
+ "@babel/plugin-proposal-class-properties": "7.18.6",
+ "@babel/plugin-proposal-nullish-coalescing-operator": "7.18.6",
+ "@babel/plugin-proposal-optional-chaining": "7.21.0",
+ "@babel/plugin-transform-runtime": "7.22.15",
+ "@babel/plugin-transform-typescript": "7.22.15",
+ "@babel/preset-react": "7.22.15",
+ "@babel/preset-typescript": "7.23.0",
"@electron/fuses": "1.5.0",
"@formatjs/intl": "2.6.7",
"@mixer/parallel-prettier": "2.0.3",
"@signalapp/mock-server": "4.1.2",
- "@storybook/addon-a11y": "6.5.6",
- "@storybook/addon-actions": "6.5.6",
- "@storybook/addon-controls": "6.5.6",
- "@storybook/addon-interactions": "6.5.9",
- "@storybook/addon-knobs": "6.4.0",
- "@storybook/addon-measure": "6.5.6",
- "@storybook/addon-toolbars": "6.5.6",
- "@storybook/addon-viewport": "6.5.6",
- "@storybook/addons": "6.5.6",
- "@storybook/builder-webpack5": "6.5.15",
- "@storybook/jest": "0.0.10",
- "@storybook/manager-webpack5": "6.5.15",
- "@storybook/react": "6.5.6",
- "@storybook/testing-library": "0.0.13",
- "@types/backbone": "1.4.5",
+ "@storybook/addon-a11y": "7.4.5",
+ "@storybook/addon-actions": "7.4.5",
+ "@storybook/addon-controls": "7.4.5",
+ "@storybook/addon-interactions": "7.4.5",
+ "@storybook/addon-jest": "7.4.5",
+ "@storybook/addon-measure": "7.4.5",
+ "@storybook/addon-toolbars": "7.4.5",
+ "@storybook/addon-viewport": "7.4.5",
+ "@storybook/addons": "7.4.5",
+ "@storybook/jest": "0.2.2",
+ "@storybook/react": "7.4.5",
+ "@storybook/react-webpack5": "7.4.5",
+ "@storybook/test-runner": "0.13.0",
+ "@storybook/testing-library": "0.2.2",
+ "@types/backbone": "1.4.16",
"@types/blueimp-load-image": "5.14.1",
"@types/chai": "4.2.18",
"@types/chai-as-promised": "7.1.4",
@@ -258,7 +258,7 @@
"asar": "3.1.0",
"axe-core": "4.1.4",
"babel-core": "7.0.0-bridge.0",
- "babel-loader": "8.0.6",
+ "babel-loader": "9.1.3",
"babel-plugin-lodash": "3.3.4",
"casual": "1.6.2",
"chai": "4.3.4",
@@ -285,19 +285,23 @@
"eslint-plugin-react": "7.31.10",
"execa": "5.1.1",
"html-webpack-plugin": "5.3.1",
+ "http-server": "14.1.1",
"json-to-ast": "2.1.0",
+ "mini-css-extract-plugin": "2.7.6",
"mocha": "9.1.3",
"node-gyp": "9.0.0",
"npm-run-all": "4.1.5",
"nyc": "11.4.1",
"p-limit": "3.1.0",
- "patch-package": "6.4.7",
+ "patch-package": "8.0.0",
"playwright": "1.33.0",
"prettier": "2.8.0",
"protobufjs-cli": "1.1.1",
+ "resolve-url-loader": "5.0.0",
"sass": "1.49.7",
"sass-loader": "10.2.0",
"sinon": "11.1.1",
+ "storybook": "7.4.5",
"style-loader": "1.0.0",
"stylelint": "15.4.0",
"stylelint-config-css-modules": "4.2.0",
@@ -309,7 +313,8 @@
"ts-node": "8.3.0",
"typed-scss-modules": "4.1.1",
"typescript": "5.1.3",
- "webpack": "5.76.0",
+ "wait-on": "7.0.1",
+ "webpack": "5.88.2",
"webpack-cli": "4.9.2",
"webpack-dev-server": "4.11.1"
},
diff --git a/patches/@storybook+manager-api+7.4.5.patch b/patches/@storybook+manager-api+7.4.5.patch
new file mode 100644
index 000000000000..ecba613a45b4
--- /dev/null
+++ b/patches/@storybook+manager-api+7.4.5.patch
@@ -0,0 +1,13 @@
+diff --git a/node_modules/@storybook/manager-api/dist/index.d.ts b/node_modules/@storybook/manager-api/dist/index.d.ts
+index 7afb86e..a15b801 100644
+--- a/node_modules/@storybook/manager-api/dist/index.d.ts
++++ b/node_modules/@storybook/manager-api/dist/index.d.ts
+@@ -822,7 +822,7 @@ declare class ManagerProvider extends Component {
+ static getDerivedStateFromProps(props: ManagerProviderProps, state: State): State;
+ shouldComponentUpdate(nextProps: ManagerProviderProps, nextState: State): boolean;
+ initModules: () => void;
+- render(): React.JSX.Element;
++ render(): JSX.Element;
+ }
+ interface ManagerConsumerProps {
+ filter?: (combo: Combo) => P;
diff --git a/patches/@storybook+router+7.4.5.patch b/patches/@storybook+router+7.4.5.patch
new file mode 100644
index 000000000000..793a975dbee6
--- /dev/null
+++ b/patches/@storybook+router+7.4.5.patch
@@ -0,0 +1,22 @@
+diff --git a/node_modules/@storybook/router/dist/index.d.ts b/node_modules/@storybook/router/dist/index.d.ts
+index ed699f7..71f48eb 100644
+--- a/node_modules/@storybook/router/dist/index.d.ts
++++ b/node_modules/@storybook/router/dist/index.d.ts
+@@ -335,7 +335,7 @@ declare const useNavigate: () => (to: To | number, { plain, ...options }?: any)
+ * A component that will navigate to a new location/path when clicked
+ */
+ declare const Link: {
+- ({ to, children, ...rest }: LinkProps): React__default.JSX.Element;
++ ({ to, children, ...rest }: LinkProps): JSX.Element;
+ displayName: string;
+ };
+ /**
+@@ -343,7 +343,7 @@ declare const Link: {
+ * and will be called whenever it changes when it changes
+ */
+ declare const Location: {
+- ({ children }: LocationProps): React__default.JSX.Element;
++ ({ children }: LocationProps): JSX.Element;
+ displayName: string;
+ };
+ /**
diff --git a/patches/@types+backbone+1.4.16.patch b/patches/@types+backbone+1.4.16.patch
new file mode 100644
index 000000000000..ed2430deb183
--- /dev/null
+++ b/patches/@types+backbone+1.4.16.patch
@@ -0,0 +1,49 @@
+diff --git a/node_modules/@types/backbone/index.d.ts b/node_modules/@types/backbone/index.d.ts
+index 3935075..22a4c2e 100644
+--- a/node_modules/@types/backbone/index.d.ts
++++ b/node_modules/@types/backbone/index.d.ts
+@@ -81,7 +81,7 @@ declare namespace Backbone {
+ collection?: Collection | undefined;
+ }
+
+- type CombinedModelConstructorOptions = Model> = ModelConstructorOptions & E;
++ type CombinedModelConstructorOptions = Model> = ModelConstructorOptions & E;
+
+ interface ModelSetOptions extends Silenceable, Validable {}
+
+@@ -219,7 +219,7 @@ declare namespace Backbone {
+ */
+ static extend(properties: any, classProperties?: any): any;
+
+- attributes: Partial;
++ attributes: T;
+ changed: Partial;
+ cidPrefix: string;
+ cid: string;
+@@ -235,7 +235,7 @@ declare namespace Backbone {
+ * That works only if you set it in the constructor or the initialize method.
+ */
+ defaults(): Partial;
+- id: string | number;
++ id: string;
+ idAttribute: string;
+ validationError: any;
+
+@@ -266,7 +266,7 @@ declare namespace Backbone {
+ * return super.get("name");
+ * }
+ */
+- get>(attributeName: A): T[A] | undefined;
++ get>(attributeName: A): T[A];
+
+ /**
+ * For strongly-typed assignment of attributes, use the `set` method only privately in public setter properties.
+@@ -300,7 +300,7 @@ declare namespace Backbone {
+ previousAttributes(): Partial;
+ save(attributes?: Partial | null, options?: ModelSaveOptions): JQueryXHR;
+ unset(attribute: _StringKey, options?: Silenceable): this;
+- validate(attributes: Partial, options?: any): any;
++ validate(attributes: T, options?: any): any;
+ private _validate(attributes: Partial, options: any): boolean;
+
+ // mixins from underscore
diff --git a/patches/@types+backbone+1.4.5.patch b/patches/@types+backbone+1.4.5.patch
deleted file mode 100644
index 57bfcd8a8a68..000000000000
--- a/patches/@types+backbone+1.4.5.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-diff --git a/node_modules/@types/backbone/index.d.ts b/node_modules/@types/backbone/index.d.ts
-index a172230..2c62e92 100644
---- a/node_modules/@types/backbone/index.d.ts
-+++ b/node_modules/@types/backbone/index.d.ts
-@@ -81,7 +81,7 @@ declare namespace Backbone {
- collection?: Backbone.Collection;
- }
-
-- type CombinedModelConstructorOptions = Model> = ModelConstructorOptions & E;
-+ type CombinedModelConstructorOptions = Model> = ModelConstructorOptions & E;
-
- interface ModelSetOptions extends Silenceable, Validable {
- }
-@@ -218,14 +218,14 @@ declare namespace Backbone {
- * E - Extensions to the model constructor options. You can accept additional constructor options
- * by listing them in the E parameter.
- */
-- class Model extends ModelBase implements Events {
-+ class Model = any, S = Backbone.ModelSetOptions, E = {}> extends ModelBase implements Events {
-
- /**
- * Do not use, prefer TypeScript's extend functionality.
- **/
- public static extend(properties: any, classProperties?: any): any;
-
-- attributes: any;
-+ attributes: T;
- changed: any[];
- cidPrefix: string;
- cid: string;
diff --git a/patches/@types+express+4.17.13.patch b/patches/@types+express+4.17.18.patch
similarity index 100%
rename from patches/@types+express+4.17.13.patch
rename to patches/@types+express+4.17.18.patch
diff --git a/patches/@types+jest+28.1.1.patch b/patches/@types+jest+28.1.3.patch
similarity index 94%
rename from patches/@types+jest+28.1.1.patch
rename to patches/@types+jest+28.1.3.patch
index b33bddd34a48..77ea181e8e60 100644
--- a/patches/@types+jest+28.1.1.patch
+++ b/patches/@types+jest+28.1.3.patch
@@ -1,10 +1,10 @@
diff --git a/node_modules/@types/jest/index.d.ts b/node_modules/@types/jest/index.d.ts
-index 272822a..87ebd1f 100755
+index b37b188..1908c0c 100755
--- a/node_modules/@types/jest/index.d.ts
+++ b/node_modules/@types/jest/index.d.ts
@@ -30,18 +30,18 @@
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
- // Minimum TypeScript Version: 3.8
+ // Minimum TypeScript Version: 4.3
-declare var beforeAll: jest.Lifecycle;
-declare var beforeEach: jest.Lifecycle;
diff --git a/ts/Crypto.ts b/ts/Crypto.ts
index 09cee51db901..ceb3273b7046 100644
--- a/ts/Crypto.ts
+++ b/ts/Crypto.ts
@@ -13,8 +13,6 @@ import { getBytesSubarray } from './util/uuidToBytes';
export { HashType, CipherType };
-export const UUID_BYTE_SIZE = 16;
-
const PROFILE_IV_LENGTH = 12; // bytes
const PROFILE_KEY_LENGTH = 32; // bytes
diff --git a/ts/background.ts b/ts/background.ts
index add167359199..ff7316ef7927 100644
--- a/ts/background.ts
+++ b/ts/background.ts
@@ -3288,13 +3288,14 @@ export async function startApp(): Promise {
'onDeliveryReceipt: missing valid sourceServiceId'
);
strictAssert(sourceDevice, 'onDeliveryReceipt: missing sourceDevice');
+ strictAssert(sourceConversation, 'onDeliveryReceipt: missing conversation');
const attributes: MessageReceiptAttributesType = {
envelopeId: ev.deliveryReceipt.envelopeId,
removeFromMessageReceiverCache: ev.confirm,
messageSentAt: timestamp,
receiptTimestamp: envelopeTimestamp,
- sourceConversationId: sourceConversation?.id,
+ sourceConversationId: sourceConversation.id,
sourceServiceId,
sourceDevice,
type: MessageReceipts.MessageReceiptType.Delivery,
diff --git a/ts/components/AddGroupMemberErrorDialog.stories.tsx b/ts/components/AddGroupMemberErrorDialog.stories.tsx
index 9ced0f47f75b..5db6945b6c0e 100644
--- a/ts/components/AddGroupMemberErrorDialog.stories.tsx
+++ b/ts/components/AddGroupMemberErrorDialog.stories.tsx
@@ -5,8 +5,10 @@ import React from 'react';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
import { setupI18n } from '../util/setupI18n';
import enMessages from '../../_locales/en/messages.json';
+import type { PropsType } from './AddGroupMemberErrorDialog';
import {
AddGroupMemberErrorDialog,
AddGroupMemberErrorDialogMode,
@@ -16,24 +18,22 @@ const i18n = setupI18n('en', enMessages);
export default {
title: 'Components/AddGroupMemberErrorDialog',
-};
+} satisfies Meta;
const defaultProps = {
i18n,
onClose: action('onClose'),
};
-export const _MaximumGroupSize = (): JSX.Element => (
-
-);
-
-_MaximumGroupSize.story = {
- name: 'Maximum group size',
-};
+export function MaximumGroupSize(): JSX.Element {
+ return (
+
+ );
+}
export function MaximumRecommendedGroupSize(): JSX.Element {
return (
@@ -44,7 +44,3 @@ export function MaximumRecommendedGroupSize(): JSX.Element {
/>
);
}
-
-MaximumRecommendedGroupSize.story = {
- name: 'Maximum recommended group size',
-};
diff --git a/ts/components/AddGroupMemberErrorDialog.tsx b/ts/components/AddGroupMemberErrorDialog.tsx
index cae318cfa251..7cb81962dc82 100644
--- a/ts/components/AddGroupMemberErrorDialog.tsx
+++ b/ts/components/AddGroupMemberErrorDialog.tsx
@@ -23,7 +23,7 @@ type PropsDataType =
recommendedMaximumNumberOfContacts: number;
};
-type PropsType = {
+export type PropsType = {
i18n: LocalizerType;
onClose: () => void;
} & PropsDataType;
diff --git a/ts/components/AddUserToAnotherGroupModal.stories.tsx b/ts/components/AddUserToAnotherGroupModal.stories.tsx
index 4848542fa9c8..b3ffe7e60745 100644
--- a/ts/components/AddUserToAnotherGroupModal.stories.tsx
+++ b/ts/components/AddUserToAnotherGroupModal.stories.tsx
@@ -1,8 +1,9 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
-import React from 'react';
-import type { Meta, Story } from '@storybook/react';
+import React, { useContext } from 'react';
+import type { Meta, StoryFn } from '@storybook/react';
+import { action } from '@storybook/addon-actions';
import type { Props } from './AddUserToAnotherGroupModal';
import enMessages from '../../_locales/en/messages.json';
@@ -19,28 +20,25 @@ const i18n = setupI18n('en', enMessages);
export default {
title: 'Components/AddUserToAnotherGroupModal',
component: AddUserToAnotherGroupModal,
- argTypes: {
- candidateConversations: {
- defaultValue: Array.from(Array(100), () => getDefaultGroup()),
- },
- contact: {
- defaultValue: getDefaultConversation(),
- },
- i18n: {
- defaultValue: i18n,
- },
- addMembersToGroup: { action: true },
- toggleAddUserToAnotherGroupModal: { action: true },
+ args: {
+ i18n,
+ candidateConversations: Array.from(Array(100), () => getDefaultGroup()),
+ contact: getDefaultConversation(),
},
-} as Meta;
+} satisfies Meta;
// eslint-disable-next-line react/function-component-definition
-const Template: Story = args => (
-
-);
+const Template: StoryFn = args => {
+ return (
+
+ );
+};
export const Modal = Template.bind({});
-Modal.args = {};
diff --git a/ts/components/Alert.stories.tsx b/ts/components/Alert.stories.tsx
index d590dcef9fcf..272b6af0d4e3 100644
--- a/ts/components/Alert.stories.tsx
+++ b/ts/components/Alert.stories.tsx
@@ -2,18 +2,18 @@
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
-
import { action } from '@storybook/addon-actions';
-
+import type { Meta } from '@storybook/react';
import { setupI18n } from '../util/setupI18n';
import enMessages from '../../_locales/en/messages.json';
+import type { PropsType } from './Alert';
import { Alert } from './Alert';
const i18n = setupI18n('en', enMessages);
export default {
title: 'Components/Alert',
-};
+} satisfies Meta;
const defaultProps = {
i18n,
@@ -33,10 +33,6 @@ export function TitleAndBodyAreStrings(): JSX.Element {
);
}
-TitleAndBodyAreStrings.story = {
- name: 'Title and body are strings',
-};
-
export function BodyIsAReactNode(): JSX.Element {
return (
);
}
-
-LongBodyWithTitle.story = {
- name: 'Long body (with title)',
-};
diff --git a/ts/components/Alert.tsx b/ts/components/Alert.tsx
index c9ac714b7d6c..56eec431d7dc 100644
--- a/ts/components/Alert.tsx
+++ b/ts/components/Alert.tsx
@@ -9,7 +9,7 @@ import type { Theme } from '../util/theme';
import { Button } from './Button';
import { Modal } from './Modal';
-type PropsType = {
+export type PropsType = {
body: ReactNode;
i18n: LocalizerType;
onClose: () => void;
diff --git a/ts/components/AnimatedEmojiGalore.stories.tsx b/ts/components/AnimatedEmojiGalore.stories.tsx
index 491e2eec0343..acc4edc314cd 100644
--- a/ts/components/AnimatedEmojiGalore.stories.tsx
+++ b/ts/components/AnimatedEmojiGalore.stories.tsx
@@ -4,12 +4,13 @@
import React from 'react';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
import type { PropsType } from './AnimatedEmojiGalore';
import { AnimatedEmojiGalore } from './AnimatedEmojiGalore';
export default {
title: 'Components/AnimatedEmojiGalore',
-};
+} satisfies Meta;
function getDefaultProps(): PropsType {
return {
diff --git a/ts/components/Avatar.stories.tsx b/ts/components/Avatar.stories.tsx
index ec29c5cad142..d09181694d7a 100644
--- a/ts/components/Avatar.stories.tsx
+++ b/ts/components/Avatar.stories.tsx
@@ -1,13 +1,12 @@
// Copyright 2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
-import type { Meta, Story } from '@storybook/react';
+import type { Meta, StoryFn } from '@storybook/react';
import * as React from 'react';
import { action } from '@storybook/addon-actions';
-import { expect } from '@storybook/jest';
+import { expect, jest } from '@storybook/jest';
import { isBoolean } from 'lodash';
import { within, userEvent } from '@storybook/testing-library';
-
import type { AvatarColorType } from '../types/Colors';
import type { Props } from './Avatar';
import enMessages from '../../_locales/en/messages.json';
@@ -42,7 +41,6 @@ export default {
},
blur: {
control: { type: 'radio' },
- defaultValue: undefined,
options: {
Undefined: undefined,
NoBlur: AvatarBlur.NoBlur,
@@ -51,14 +49,12 @@ export default {
},
},
color: {
- defaultValue: AvatarColors[0],
options: colorMap,
},
conversationType: {
control: { type: 'radio' },
options: conversationTypeMap,
},
- onClick: { action: true },
size: {
control: false,
},
@@ -68,11 +64,16 @@ export default {
},
theme: {
control: { type: 'radio' },
- defaultValue: ThemeType.light,
options: ThemeType,
},
},
-} as Meta;
+ args: {
+ blur: undefined,
+ color: AvatarColors[0],
+ onClick: action('onClick'),
+ theme: ThemeType.light,
+ },
+} satisfies Meta;
const createProps = (overrideProps: Partial = {}): Props => ({
acceptedMessageRequest: isBoolean(overrideProps.acceptedMessageRequest)
@@ -87,7 +88,7 @@ const createProps = (overrideProps: Partial = {}): Props => ({
isMe: false,
loading: Boolean(overrideProps.loading),
noteToSelf: Boolean(overrideProps.noteToSelf),
- onClick: action('onClick'),
+ onClick: jest.fn(action('onClick')),
onClickBadge: action('onClickBadge'),
phoneNumber: overrideProps.phoneNumber || '',
searchResult: Boolean(overrideProps.searchResult),
@@ -103,16 +104,18 @@ const sizes = Object.values(AvatarSize).filter(
) as Array;
// eslint-disable-next-line react/function-component-definition
-const Template: Story = args => (
- <>
- {sizes.map(size => (
-
- ))}
- >
-);
+const Template: StoryFn = (args: Props) => {
+ return (
+ <>
+ {sizes.map(size => (
+
+ ))}
+ >
+ );
+};
// eslint-disable-next-line react/function-component-definition
-const TemplateSingle: Story = args => (
+const TemplateSingle: StoryFn = (args: Props) => (
);
@@ -120,72 +123,50 @@ export const Default = Template.bind({});
Default.args = createProps({
avatarPath: '/fixtures/giphy-GVNvOUpeYmI7e.gif',
});
-Default.play = async ({ args, canvasElement }) => {
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+Default.play = async (context: any) => {
+ const { args, canvasElement } = context;
const canvas = within(canvasElement);
const [avatar] = canvas.getAllByRole('button');
await userEvent.click(avatar);
await expect(args.onClick).toHaveBeenCalled();
};
-Default.story = {
- name: 'Avatar',
-};
export const WithBadge = Template.bind({});
WithBadge.args = createProps({
avatarPath: '/fixtures/kitten-3-64-64.jpg',
badge: getFakeBadge(),
});
-WithBadge.story = {
- name: 'With badge',
-};
export const WideImage = Template.bind({});
WideImage.args = createProps({
avatarPath: '/fixtures/wide.jpg',
});
-WideImage.story = {
- name: 'Wide image',
-};
export const OneWordName = Template.bind({});
OneWordName.args = createProps({
title: 'John',
});
-OneWordName.story = {
- name: 'One-word Name',
-};
export const TwoWordName = Template.bind({});
TwoWordName.args = createProps({
title: 'John Smith',
});
-TwoWordName.story = {
- name: 'Two-word Name',
-};
export const WideInitials = Template.bind({});
WideInitials.args = createProps({
title: 'Walter White',
});
-WideInitials.story = {
- name: 'Wide initials',
-};
export const ThreeWordName = Template.bind({});
ThreeWordName.args = createProps({
title: 'Walter H. White',
});
-ThreeWordName.story = {
- name: 'Three-word name',
-};
export const NoteToSelf = Template.bind({});
NoteToSelf.args = createProps({
noteToSelf: true,
});
-NoteToSelf.story = {
- name: 'Note to Self',
-};
export const ContactIcon = Template.bind({});
ContactIcon.args = createProps();
@@ -227,9 +208,6 @@ BrokenAvatarForGroup.args = createProps({
avatarPath: 'badimage.png',
conversationType: 'group',
});
-BrokenAvatarForGroup.story = {
- name: 'Broken Avatar for Group',
-};
export const Loading = Template.bind({});
Loading.args = createProps({
@@ -242,42 +220,26 @@ BlurredBasedOnProps.args = createProps({
avatarPath: '/fixtures/kitten-3-64-64.jpg',
});
-BlurredBasedOnProps.story = {
- name: 'Blurred based on props',
-};
-
export const ForceBlurred = TemplateSingle.bind({});
ForceBlurred.args = createProps({
avatarPath: '/fixtures/kitten-3-64-64.jpg',
blur: AvatarBlur.BlurPicture,
});
-ForceBlurred.story = {
- name: 'Force-blurred',
-};
export const BlurredWithClickToView = TemplateSingle.bind({});
BlurredWithClickToView.args = createProps({
avatarPath: '/fixtures/kitten-3-64-64.jpg',
blur: AvatarBlur.BlurPictureWithClickToView,
});
-BlurredWithClickToView.story = {
- name: 'Blurred with "click to view"',
-};
export const StoryUnread = TemplateSingle.bind({});
StoryUnread.args = createProps({
avatarPath: '/fixtures/kitten-3-64-64.jpg',
storyRing: HasStories.Unread,
});
-StoryUnread.story = {
- name: 'Story: unread',
-};
export const StoryRead = TemplateSingle.bind({});
StoryRead.args = createProps({
avatarPath: '/fixtures/kitten-3-64-64.jpg',
storyRing: HasStories.Read,
});
-StoryRead.story = {
- name: 'Story: read',
-};
diff --git a/ts/components/AvatarColorPicker.stories.tsx b/ts/components/AvatarColorPicker.stories.tsx
index c66e745de557..43e03caa3367 100644
--- a/ts/components/AvatarColorPicker.stories.tsx
+++ b/ts/components/AvatarColorPicker.stories.tsx
@@ -4,6 +4,7 @@
import React from 'react';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
import { setupI18n } from '../util/setupI18n';
import enMessages from '../../_locales/en/messages.json';
@@ -21,7 +22,7 @@ const createProps = (overrideProps: Partial = {}): PropsType => ({
export default {
title: 'Components/AvatarColorPicker',
-};
+} satisfies Meta;
export function Default(): JSX.Element {
return ;
diff --git a/ts/components/AvatarEditor.stories.tsx b/ts/components/AvatarEditor.stories.tsx
index f4ef76f54063..6301b4c23320 100644
--- a/ts/components/AvatarEditor.stories.tsx
+++ b/ts/components/AvatarEditor.stories.tsx
@@ -4,6 +4,7 @@
import React from 'react';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
import { setupI18n } from '../util/setupI18n';
import enMessages from '../../_locales/en/messages.json';
@@ -80,7 +81,7 @@ const createProps = (overrideProps: Partial = {}): PropsType => ({
export default {
title: 'Components/AvatarEditor',
-};
+} satisfies Meta;
export function NoAvatarGroup(): JSX.Element {
return (
@@ -93,20 +94,12 @@ export function NoAvatarGroup(): JSX.Element {
);
}
-NoAvatarGroup.story = {
- name: 'No Avatar (group)',
-};
-
export function NoAvatarMe(): JSX.Element {
return (
);
}
-NoAvatarMe.story = {
- name: 'No Avatar (me)',
-};
-
export function HasAvatar(): JSX.Element {
return (
= {}): PropsType => ({
export default {
title: 'Components/AvatarIconEditor',
-};
+} satisfies Meta;
export function PersonalIcon(): JSX.Element {
return (
diff --git a/ts/components/AvatarLightbox.stories.tsx b/ts/components/AvatarLightbox.stories.tsx
index c06b7984816e..a9e5bdc70c54 100644
--- a/ts/components/AvatarLightbox.stories.tsx
+++ b/ts/components/AvatarLightbox.stories.tsx
@@ -2,10 +2,8 @@
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
-
import { action } from '@storybook/addon-actions';
-import { select } from '@storybook/addon-knobs';
-
+import type { Meta } from '@storybook/react';
import enMessages from '../../_locales/en/messages.json';
import { AvatarColors } from '../types/Colors';
import type { PropsType } from './AvatarLightbox';
@@ -15,51 +13,37 @@ import { getDefaultConversation } from '../test-both/helpers/getDefaultConversat
const i18n = setupI18n('en', enMessages);
-const createProps = (overrideProps: Partial = {}): PropsType => ({
- avatarColor: select(
- 'Color',
- AvatarColors,
- overrideProps.avatarColor || AvatarColors[0]
- ),
- avatarPath: overrideProps.avatarPath,
- conversationTitle: overrideProps.conversationTitle,
- i18n,
- isGroup: Boolean(overrideProps.isGroup),
- onClose: action('onClose'),
-});
-
export default {
title: 'Components/AvatarLightbox',
-};
+ component: AvatarLightbox,
+ argTypes: {
+ avatarColor: {
+ control: { type: 'select' },
+ options: AvatarColors,
+ },
+ },
+ args: {
+ i18n,
+ avatarColor: AvatarColors[0],
+ onClose: action('onClose'),
+ },
+} satisfies Meta;
-export function Group(): JSX.Element {
- return (
-
- );
+export function Group(args: PropsType): JSX.Element {
+ return ;
}
-export function Person(): JSX.Element {
+export function Person(args: PropsType): JSX.Element {
const conversation = getDefaultConversation();
return (
);
}
-export function Photo(): JSX.Element {
- return (
-
- );
+export function Photo(args: PropsType): JSX.Element {
+ return ;
}
diff --git a/ts/components/AvatarModalButtons.stories.tsx b/ts/components/AvatarModalButtons.stories.tsx
index d4488f6645d9..10005459ee7b 100644
--- a/ts/components/AvatarModalButtons.stories.tsx
+++ b/ts/components/AvatarModalButtons.stories.tsx
@@ -5,6 +5,7 @@ import React from 'react';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
import enMessages from '../../_locales/en/messages.json';
import type { PropsType } from './AvatarModalButtons';
import { AvatarModalButtons } from './AvatarModalButtons';
@@ -21,7 +22,7 @@ const createProps = (overrideProps: Partial = {}): PropsType => ({
export default {
title: 'Components/AvatarModalButtons',
-};
+} satisfies Meta;
export function HasChanges(): JSX.Element {
return (
@@ -33,14 +34,6 @@ export function HasChanges(): JSX.Element {
);
}
-HasChanges.story = {
- name: 'Has changes',
-};
-
export function NoChanges(): JSX.Element {
return ;
}
-
-NoChanges.story = {
- name: 'No changes',
-};
diff --git a/ts/components/AvatarPreview.stories.tsx b/ts/components/AvatarPreview.stories.tsx
index 3868ef0c40b7..bedde737a8d4 100644
--- a/ts/components/AvatarPreview.stories.tsx
+++ b/ts/components/AvatarPreview.stories.tsx
@@ -6,6 +6,7 @@ import { chunk } from 'lodash';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
import type { PropsType } from './AvatarPreview';
import { AvatarPreview } from './AvatarPreview';
import { AvatarColors } from '../types/Colors';
@@ -37,7 +38,7 @@ const createProps = (overrideProps: Partial = {}): PropsType => ({
export default {
title: 'Components/AvatarPreview',
-};
+} satisfies Meta;
export function NoStatePersonal(): JSX.Element {
return (
@@ -50,10 +51,6 @@ export function NoStatePersonal(): JSX.Element {
);
}
-NoStatePersonal.story = {
- name: 'No state (personal)',
-};
-
export function NoStateGroup(): JSX.Element {
return (
;
}
-Value.story = {
- name: 'value',
-};
-
export function Path(): JSX.Element {
return (
);
}
-
-Style.story = {
- name: 'style',
-};
diff --git a/ts/components/AvatarTextEditor.stories.tsx b/ts/components/AvatarTextEditor.stories.tsx
index 3d113be24806..8058bb77640f 100644
--- a/ts/components/AvatarTextEditor.stories.tsx
+++ b/ts/components/AvatarTextEditor.stories.tsx
@@ -4,6 +4,7 @@
import React from 'react';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
import { setupI18n } from '../util/setupI18n';
import enMessages from '../../_locales/en/messages.json';
@@ -22,7 +23,7 @@ const createProps = (overrideProps: Partial = {}): PropsType => ({
export default {
title: 'Components/AvatarTextEditor',
-};
+} satisfies Meta;
export function Empty(): JSX.Element {
return ;
@@ -42,10 +43,6 @@ export function WithData(): JSX.Element {
);
}
-WithData.story = {
- name: 'with Data',
-};
-
export function WithWideCharacters(): JSX.Element {
return (
);
}
-
-WithWideCharacters.story = {
- name: 'with wide characters',
-};
diff --git a/ts/components/AvatarUploadButton.stories.tsx b/ts/components/AvatarUploadButton.stories.tsx
index 1f4aed996b5a..6a866de04861 100644
--- a/ts/components/AvatarUploadButton.stories.tsx
+++ b/ts/components/AvatarUploadButton.stories.tsx
@@ -4,6 +4,7 @@
import React from 'react';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
import { setupI18n } from '../util/setupI18n';
import enMessages from '../../_locales/en/messages.json';
@@ -20,7 +21,7 @@ const createProps = (overrideProps: Partial = {}): PropsType => ({
export default {
title: 'Components/AvatarUploadButton',
-};
+} satisfies Meta;
export function Default(): JSX.Element {
return ;
diff --git a/ts/components/BadgeDescription.stories.tsx b/ts/components/BadgeDescription.stories.tsx
index 5edb8e2d518d..fe9b1a8f14bd 100644
--- a/ts/components/BadgeDescription.stories.tsx
+++ b/ts/components/BadgeDescription.stories.tsx
@@ -3,11 +3,13 @@
import React from 'react';
+import type { Meta } from '@storybook/react';
+import type { Props } from './BadgeDescription';
import { BadgeDescription } from './BadgeDescription';
export default {
title: 'Components/BadgeDescription',
-};
+} satisfies Meta;
export function NormalName(): JSX.Element {
return (
@@ -19,11 +21,7 @@ export function NormalName(): JSX.Element {
);
}
-NormalName.story = {
- name: 'Normal name',
-};
-
-export function NameWithRtlOverrides(): JSX.Element {
+export function NameWithRTLOverrides(): JSX.Element {
return (
);
}
-
-NameWithRtlOverrides.story = {
- name: 'Name with RTL overrides',
-};
diff --git a/ts/components/BadgeDescription.tsx b/ts/components/BadgeDescription.tsx
index e5343fa92735..5fee7f4a0269 100644
--- a/ts/components/BadgeDescription.tsx
+++ b/ts/components/BadgeDescription.tsx
@@ -5,15 +5,17 @@ import type { ReactChild, ReactElement } from 'react';
import React from 'react';
import { ContactName } from './conversation/ContactName';
+export type Props = Readonly<{
+ firstName?: string;
+ template: string;
+ title: string;
+}>;
+
export function BadgeDescription({
firstName,
template,
title,
-}: Readonly<{
- firstName?: string;
- template: string;
- title: string;
-}>): ReactElement {
+}: Props): ReactElement {
const result: Array = [];
let lastIndex = 0;
diff --git a/ts/components/BadgeDialog.stories.tsx b/ts/components/BadgeDialog.stories.tsx
index 36ff3b2dccd0..c45deeea0b74 100644
--- a/ts/components/BadgeDialog.stories.tsx
+++ b/ts/components/BadgeDialog.stories.tsx
@@ -5,18 +5,20 @@ import type { ComponentProps } from 'react';
import React from 'react';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
import { setupI18n } from '../util/setupI18n';
import enMessages from '../../_locales/en/messages.json';
import { getFakeBadge, getFakeBadges } from '../test-both/helpers/getFakeBadge';
import { repeat, zipObject } from '../util/iterables';
import { BadgeImageTheme } from '../badges/BadgeImageTheme';
+import type { PropsType } from './BadgeDialog';
import { BadgeDialog } from './BadgeDialog';
const i18n = setupI18n('en', enMessages);
export default {
title: 'Components/BadgeDialog',
-};
+} satisfies Meta;
const defaultProps: ComponentProps = {
areWeASubscriber: false,
@@ -31,18 +33,10 @@ export function NoBadgesClosedImmediately(): JSX.Element {
return ;
}
-NoBadgesClosedImmediately.story = {
- name: 'No badges (closed immediately)',
-};
-
export function OneBadge(): JSX.Element {
return ;
}
-OneBadge.story = {
- name: 'One badge',
-};
-
export function BadgeWithNoImageShouldBeImpossible(): JSX.Element {
return (
;
}
-FiveBadges.story = {
- name: 'Five badges',
-};
-
export function ManyBadges(): JSX.Element {
return ;
}
-ManyBadges.story = {
- name: 'Many badges',
-};
-
export function ManyBadgesUserIsASubscriber(): JSX.Element {
return (
);
}
-
-ManyBadgesUserIsASubscriber.story = {
- name: 'Many badges, user is a subscriber',
-};
diff --git a/ts/components/BadgeDialog.tsx b/ts/components/BadgeDialog.tsx
index 2224d6e76175..fafc7c7b4944 100644
--- a/ts/components/BadgeDialog.tsx
+++ b/ts/components/BadgeDialog.tsx
@@ -15,7 +15,7 @@ import { BadgeImage } from './BadgeImage';
import { BadgeCarouselIndex } from './BadgeCarouselIndex';
import { BadgeSustainerInstructionsDialog } from './BadgeSustainerInstructionsDialog';
-type PropsType = Readonly<{
+export type PropsType = Readonly<{
areWeASubscriber: boolean;
badges: ReadonlyArray;
firstName?: string;
diff --git a/ts/components/BetterAvatar.stories.tsx b/ts/components/BetterAvatar.stories.tsx
index e07cae81c426..6a15a926f635 100644
--- a/ts/components/BetterAvatar.stories.tsx
+++ b/ts/components/BetterAvatar.stories.tsx
@@ -5,6 +5,7 @@ import React from 'react';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
import enMessages from '../../_locales/en/messages.json';
import { AvatarColors } from '../types/Colors';
import { GroupAvatarIcons, PersonalAvatarIcons } from '../types/Avatar';
@@ -28,7 +29,7 @@ const createProps = (overrideProps: Partial = {}): PropsType => ({
export default {
title: 'Components/BetterAvatar',
-};
+} satisfies Meta;
export function Text(): JSX.Element {
return (
diff --git a/ts/components/BetterAvatarBubble.stories.tsx b/ts/components/BetterAvatarBubble.stories.tsx
index b4921bc95d33..c4fa5f1ded41 100644
--- a/ts/components/BetterAvatarBubble.stories.tsx
+++ b/ts/components/BetterAvatarBubble.stories.tsx
@@ -5,6 +5,7 @@ import React from 'react';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
import enMessages from '../../_locales/en/messages.json';
import { AvatarColors } from '../types/Colors';
import type { PropsType } from './BetterAvatarBubble';
@@ -25,7 +26,7 @@ const createProps = (overrideProps: Partial = {}): PropsType => ({
export default {
title: 'Components/BetterAvatarBubble',
-};
+} satisfies Meta;
export function Children(): JSX.Element {
return (
diff --git a/ts/components/Button.stories.tsx b/ts/components/Button.stories.tsx
index 7ad08a7f3eb1..c745533933ea 100644
--- a/ts/components/Button.stories.tsx
+++ b/ts/components/Button.stories.tsx
@@ -3,12 +3,13 @@
import React from 'react';
import { action } from '@storybook/addon-actions';
-
+import type { Meta } from '@storybook/react';
+import type { PropsType } from './Button';
import { Button, ButtonSize, ButtonVariant } from './Button';
export default {
title: 'Components/Button',
-};
+} satisfies Meta;
export function KitchenSink(): JSX.Element {
return (
@@ -44,10 +45,6 @@ export function KitchenSink(): JSX.Element {
);
}
-KitchenSink.story = {
- name: 'Kitchen sink',
-};
-
export function AriaLabel(): JSX.Element {
return (
);
}
-
-CustomStyles.story = {
- name: 'Custom styles',
-};
diff --git a/ts/components/Button.tsx b/ts/components/Button.tsx
index ce39c7bb45f3..36dee96f5001 100644
--- a/ts/components/Button.tsx
+++ b/ts/components/Button.tsx
@@ -40,7 +40,7 @@ export enum ButtonIconType {
video = 'video',
}
-type PropsType = {
+export type PropsType = {
className?: string;
disabled?: boolean;
icon?: ButtonIconType;
diff --git a/ts/components/CallManager.stories.tsx b/ts/components/CallManager.stories.tsx
index 4a176796a3d7..a9d43496c3bf 100644
--- a/ts/components/CallManager.stories.tsx
+++ b/ts/components/CallManager.stories.tsx
@@ -3,8 +3,7 @@
import * as React from 'react';
import { action } from '@storybook/addon-actions';
-import { boolean, select, text } from '@storybook/addon-knobs';
-
+import type { Meta } from '@storybook/react';
import type { PropsType } from './CallManager';
import { CallManager } from './CallManager';
import {
@@ -16,7 +15,6 @@ import {
GroupCallJoinState,
} from '../types/Calling';
import type { ConversationTypeType } from '../state/ducks/conversations';
-import type { AvatarColorType } from '../types/Colors';
import { AvatarColors } from '../types/Colors';
import { generateAci } from '../types/ServiceId';
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
@@ -33,13 +31,9 @@ const getConversation = () =>
getDefaultConversation({
id: '3051234567',
avatarPath: undefined,
- color: select(
- 'Callee color',
- AvatarColors,
- 'ultramarine' as AvatarColorType
- ),
- title: text('Callee Title', 'Rick Sanchez'),
- name: text('Callee Name', 'Rick Sanchez'),
+ color: AvatarColors[0],
+ title: 'Rick Sanchez',
+ name: 'Rick Sanchez',
phoneNumber: '3051234567',
profileName: 'Rick Sanchez',
markedUnread: false,
@@ -50,18 +44,14 @@ const getConversation = () =>
const getCommonActiveCallData = () => ({
conversation: getConversation(),
joinedAt: Date.now(),
- hasLocalAudio: boolean('hasLocalAudio', true),
- hasLocalVideo: boolean('hasLocalVideo', false),
- localAudioLevel: select('localAudioLevel', [0, 0.5, 1], 0),
- viewMode: select(
- 'viewMode',
- [CallViewMode.Grid, CallViewMode.Presentation, CallViewMode.Speaker],
- CallViewMode.Grid
- ),
- outgoingRing: boolean('outgoingRing', true),
- pip: boolean('pip', false),
- settingsDialogOpen: boolean('settingsDialogOpen', false),
- showParticipantsList: boolean('showParticipantsList', false),
+ hasLocalAudio: true,
+ hasLocalVideo: false,
+ localAudioLevel: 0,
+ viewMode: CallViewMode.Grid,
+ outgoingRing: true,
+ pip: false,
+ settingsDialogOpen: false,
+ showParticipantsList: false,
});
const createProps = (storyProps: Partial = {}): PropsType => ({
@@ -83,12 +73,8 @@ const createProps = (storyProps: Partial = {}): PropsType => ({
keyChangeOk: action('key-change-ok'),
me: {
...getDefaultConversation({
- color: select(
- 'Caller color',
- AvatarColors,
- 'ultramarine' as AvatarColorType
- ),
- title: text('Caller Title', 'Morty Smith'),
+ color: AvatarColors[0],
+ title: 'Morty Smith',
}),
serviceId: generateAci(),
},
@@ -123,7 +109,9 @@ const createProps = (storyProps: Partial = {}): PropsType => ({
export default {
title: 'Components/CallManager',
-};
+ argTypes: {},
+ args: {},
+} satisfies Meta;
export function NoCall(): JSX.Element {
return ;
@@ -184,10 +172,6 @@ export function RingingDirectCall(): JSX.Element {
);
}
-RingingDirectCall.story = {
- name: 'Ringing (direct call)',
-};
-
export function RingingGroupCall(): JSX.Element {
return (
);
}
-
-GroupCallSafetyNumberChanged.story = {
- name: 'Group call - Safety Number Changed',
-};
diff --git a/ts/components/CallScreen.stories.tsx b/ts/components/CallScreen.stories.tsx
index 1af74d0cc90f..06e699243d07 100644
--- a/ts/components/CallScreen.stories.tsx
+++ b/ts/components/CallScreen.stories.tsx
@@ -3,9 +3,9 @@
import * as React from 'react';
import { times } from 'lodash';
-import { boolean, select, number } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
import type { GroupCallRemoteParticipantType } from '../types/Calling';
import {
CallMode,
@@ -60,6 +60,7 @@ type GroupCallOverrideProps = OverridePropsBase & {
connectionState?: GroupCallConnectionState;
peekedParticipants?: Array;
remoteParticipants?: Array;
+ remoteAudioLevel?: number;
};
const createActiveDirectCallProp = (
@@ -67,18 +68,11 @@ const createActiveDirectCallProp = (
) => ({
callMode: CallMode.Direct as CallMode.Direct,
conversation,
- callState: select(
- 'callState',
- CallState,
- overrideProps.callState || CallState.Accepted
- ),
+ callState: overrideProps.callState ?? CallState.Accepted,
peekedParticipants: [] as [],
remoteParticipants: [
{
- hasRemoteVideo: boolean(
- 'hasRemoteVideo',
- Boolean(overrideProps.hasRemoteVideo)
- ),
+ hasRemoteVideo: overrideProps.hasRemoteVideo ?? false,
presenting: false,
title: 'test',
},
@@ -109,12 +103,7 @@ const createActiveGroupCallProp = (overrideProps: GroupCallOverrideProps) => ({
remoteAudioLevels: new Map(
overrideProps.remoteParticipants?.map((_participant, index) => [
index,
- number('remoteAudioLevel', 0, {
- range: true,
- min: 0,
- max: 1,
- step: 0.01,
- }),
+ overrideProps.remoteAudioLevel ?? 0,
])
),
});
@@ -125,24 +114,10 @@ const createActiveCallProp = (
const baseResult = {
joinedAt: Date.now(),
conversation,
- hasLocalAudio: boolean(
- 'hasLocalAudio',
- overrideProps.hasLocalAudio || false
- ),
- hasLocalVideo: boolean(
- 'hasLocalVideo',
- overrideProps.hasLocalVideo || false
- ),
- localAudioLevel: select(
- 'localAudioLevel',
- [0, 0.5, 1],
- overrideProps.localAudioLevel || 0
- ),
- viewMode: select(
- 'viewMode',
- [CallViewMode.Grid, CallViewMode.Speaker, CallViewMode.Presentation],
- overrideProps.viewMode || CallViewMode.Grid
- ),
+ hasLocalAudio: overrideProps.hasLocalAudio ?? false,
+ hasLocalVideo: overrideProps.hasLocalVideo ?? false,
+ localAudioLevel: overrideProps.localAudioLevel ?? 0,
+ viewMode: overrideProps.viewMode ?? CallViewMode.Grid,
outgoingRing: true,
pip: false,
settingsDialogOpen: false,
@@ -184,7 +159,7 @@ const createProps = (
setLocalVideo: action('set-local-video'),
setPresenting: action('toggle-presenting'),
setRendererCanvas: action('set-renderer-canvas'),
- stickyControls: boolean('stickyControls', false),
+ stickyControls: false,
switchToPresentationView: action('switch-to-presentation-view'),
switchFromPresentationView: action('switch-from-presentation-view'),
toggleParticipants: action('toggle-participants'),
@@ -198,7 +173,9 @@ const createProps = (
export default {
title: 'Components/CallScreen',
-};
+ argTypes: {},
+ args: {},
+} satisfies Meta;
export function Default(): JSX.Element {
return ;
@@ -215,11 +192,7 @@ export function PreRing(): JSX.Element {
);
}
-PreRing.story = {
- name: 'Pre-Ring',
-};
-
-export const _Ringing = (): JSX.Element => {
+export function Ringing(): JSX.Element {
return (
{
})}
/>
);
-};
+}
-export const _Reconnecting = (): JSX.Element => {
+export function Reconnecting(): JSX.Element {
return (
{
})}
/>
);
-};
+}
-export const _Ended = (): JSX.Element => {
+export function Ended(): JSX.Element {
return (
{
})}
/>
);
-};
+}
export function HasLocalAudio(): JSX.Element {
return (
@@ -263,10 +236,6 @@ export function HasLocalAudio(): JSX.Element {
);
}
-HasLocalAudio.story = {
- name: 'hasLocalAudio',
-};
-
export function HasLocalVideo(): JSX.Element {
return (
({
aci: generateAci(),
@@ -347,24 +304,12 @@ export function GroupCallMany(): JSX.Element {
);
}
-GroupCallMany.story = {
- name: 'Group call - Many',
-};
-
export function GroupCallReconnecting(): JSX.Element {
return (
);
}
-
-GroupCallSomeoneIsSharingScreenAndYoureReconnecting.story = {
- name: "Group call - someone is sharing screen and you're reconnecting",
-};
diff --git a/ts/components/CallingAudioIndicator.stories.tsx b/ts/components/CallingAudioIndicator.stories.tsx
index ae0f02ba7aa3..5090a4eaf38e 100644
--- a/ts/components/CallingAudioIndicator.stories.tsx
+++ b/ts/components/CallingAudioIndicator.stories.tsx
@@ -2,8 +2,8 @@
// SPDX-License-Identifier: AGPL-3.0-only
import React, { useState, useEffect } from 'react';
-import { boolean } from '@storybook/addon-knobs';
-
+import type { Meta } from '@storybook/react';
+import type { Props } from './CallingAudioIndicator';
import {
CallingAudioIndicator,
SPEAKING_LINGER_MS,
@@ -13,9 +13,18 @@ import { useValueAtFixedRate } from '../hooks/useValueAtFixedRate';
export default {
title: 'Components/CallingAudioIndicator',
-};
+ component: CallingAudioIndicator,
+ argTypes: {
+ hasAudio: {
+ control: { type: 'boolean' },
+ },
+ },
+ args: {
+ hasAudio: true,
+ },
+} satisfies Meta;
-export function Extreme(): JSX.Element {
+export function Extreme(args: Props): JSX.Element {
const [audioLevel, setAudioLevel] = useState(1);
useEffect(() => {
@@ -32,14 +41,14 @@ export function Extreme(): JSX.Element {
return (
);
}
-export function Random(): JSX.Element {
+export function Random(args: Props): JSX.Element {
const [audioLevel, setAudioLevel] = useState(1);
useEffect(() => {
@@ -56,7 +65,7 @@ export function Random(): JSX.Element {
return (
diff --git a/ts/components/CallingAudioIndicator.tsx b/ts/components/CallingAudioIndicator.tsx
index 4a0eb5b193cb..f3d1266d6770 100644
--- a/ts/components/CallingAudioIndicator.tsx
+++ b/ts/components/CallingAudioIndicator.tsx
@@ -99,15 +99,17 @@ function Bars({ audioLevel }: { audioLevel: number }): ReactElement {
);
}
+export type Props = Readonly<{
+ hasAudio: boolean;
+ audioLevel: number;
+ shouldShowSpeaking: boolean;
+}>;
+
export function CallingAudioIndicator({
hasAudio,
audioLevel,
shouldShowSpeaking,
-}: Readonly<{
- hasAudio: boolean;
- audioLevel: number;
- shouldShowSpeaking: boolean;
-}>): ReactElement {
+}: Props): ReactElement {
if (!hasAudio) {
return (
= {}): PropsType => ({
- buttonType:
- overrideProps.buttonType ||
- select('buttonType', CallingButtonType, CallingButtonType.HANG_UP),
- i18n,
- onClick: action('on-click'),
- onMouseEnter: action('on-mouse-enter'),
- onMouseLeave: action('on-mouse-leave'),
- tooltipDirection: select(
- 'tooltipDirection',
- TooltipPlacement,
- overrideProps.tooltipDirection || TooltipPlacement.Bottom
- ),
-});
-
export default {
title: 'Components/CallingButton',
-};
+ component: CallingButton,
+ argTypes: {
+ buttonType: {
+ control: { type: 'select' },
+ options: Object.values(CallingButtonType),
+ },
+ tooltipDirection: {
+ control: { type: 'select' },
+ options: Object.values(TooltipPlacement),
+ },
+ },
+ args: {
+ buttonType: CallingButtonType.HANG_UP,
+ i18n,
+ onClick: action('on-click'),
+ onMouseEnter: action('on-mouse-enter'),
+ onMouseLeave: action('on-mouse-leave'),
+ tooltipDirection: TooltipPlacement.Bottom,
+ },
+} satisfies Meta
;
-export function KitchenSink(): JSX.Element {
+export function KitchenSink(args: PropsType): JSX.Element {
return (
<>
- {Object.keys(CallingButtonType).map(buttonType => (
-
+ {Object.values(CallingButtonType).map(buttonType => (
+
))}
>
);
}
-export function AudioOn(): JSX.Element {
- const props = createProps({
- buttonType: CallingButtonType.AUDIO_ON,
- });
- return ;
+export function AudioOn(args: PropsType): JSX.Element {
+ return ;
}
-export function AudioOff(): JSX.Element {
- const props = createProps({
- buttonType: CallingButtonType.AUDIO_OFF,
- });
- return ;
+export function AudioOff(args: PropsType): JSX.Element {
+ return ;
}
-export function AudioDisabled(): JSX.Element {
- const props = createProps({
- buttonType: CallingButtonType.AUDIO_DISABLED,
- });
- return ;
+export function AudioDisabled(args: PropsType): JSX.Element {
+ return (
+
+ );
}
-export function VideoOn(): JSX.Element {
- const props = createProps({
- buttonType: CallingButtonType.VIDEO_ON,
- });
- return ;
+export function VideoOn(args: PropsType): JSX.Element {
+ return ;
}
-export function VideoOff(): JSX.Element {
- const props = createProps({
- buttonType: CallingButtonType.VIDEO_OFF,
- });
- return ;
+export function VideoOff(args: PropsType): JSX.Element {
+ return ;
}
-export function VideoDisabled(): JSX.Element {
- const props = createProps({
- buttonType: CallingButtonType.VIDEO_DISABLED,
- });
- return ;
+export function VideoDisabled(args: PropsType): JSX.Element {
+ return (
+
+ );
}
-export function TooltipRight(): JSX.Element {
- const props = createProps({
- tooltipDirection: TooltipPlacement.Right,
- });
- return ;
+export function TooltipRight(args: PropsType): JSX.Element {
+ return ;
}
-TooltipRight.story = {
- name: 'Tooltip right',
-};
-
-export function PresentingOn(): JSX.Element {
- const props = createProps({
- buttonType: CallingButtonType.PRESENTING_ON,
- });
- return ;
+export function PresentingOn(args: PropsType): JSX.Element {
+ return (
+
+ );
}
-export function PresentingOff(): JSX.Element {
- const props = createProps({
- buttonType: CallingButtonType.PRESENTING_OFF,
- });
- return ;
+export function PresentingOff(args: PropsType): JSX.Element {
+ return (
+
+ );
}
diff --git a/ts/components/CallingDeviceSelection.stories.tsx b/ts/components/CallingDeviceSelection.stories.tsx
index 0c2935c3893e..c75828e1c6fd 100644
--- a/ts/components/CallingDeviceSelection.stories.tsx
+++ b/ts/components/CallingDeviceSelection.stories.tsx
@@ -4,6 +4,7 @@
import * as React from 'react';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
import type { Props } from './CallingDeviceSelection';
import { CallingDeviceSelection } from './CallingDeviceSelection';
import { setupI18n } from '../util/setupI18n';
@@ -39,7 +40,7 @@ const createProps = ({
export default {
title: 'Components/CallingDeviceSelection',
-};
+} satisfies Meta;
export function Default(): JSX.Element {
return ;
diff --git a/ts/components/CallingHeader.stories.tsx b/ts/components/CallingHeader.stories.tsx
index e00400db2a1c..45e0275fb240 100644
--- a/ts/components/CallingHeader.stories.tsx
+++ b/ts/components/CallingHeader.stories.tsx
@@ -2,9 +2,8 @@
// SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react';
-import { boolean, number } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions';
-
+import type { Meta } from '@storybook/react';
import type { PropsType } from './CallingHeader';
import { CallingHeader } from './CallingHeader';
import { setupI18n } from '../util/setupI18n';
@@ -12,36 +11,35 @@ import enMessages from '../../_locales/en/messages.json';
const i18n = setupI18n('en', enMessages);
-const createProps = (overrideProps: Partial = {}): PropsType => ({
- i18n,
- isGroupCall: boolean('isGroupCall', Boolean(overrideProps.isGroupCall)),
- message: overrideProps.message,
- participantCount: number(
- 'participantCount',
- overrideProps.participantCount || 0
- ),
- showParticipantsList: boolean(
- 'showParticipantsList',
- Boolean(overrideProps.showParticipantsList)
- ),
- title: overrideProps.title || 'With Someone',
- toggleParticipants: () => action('toggle-participants'),
- togglePip: () => action('toggle-pip'),
- toggleSettings: () => action('toggle-settings'),
-});
-
export default {
title: 'Components/CallingHeader',
-};
+ component: CallingHeader,
+ argTypes: {
+ isGroupCall: { control: { type: 'boolean' } },
+ participantCount: { control: { type: 'number' } },
+ title: { control: { type: 'text' } },
+ },
+ args: {
+ i18n,
+ isGroupCall: false,
+ message: '',
+ participantCount: 0,
+ showParticipantsList: false,
+ title: 'With Someone',
+ toggleParticipants: action('toggle-participants'),
+ togglePip: action('toggle-pip'),
+ toggleSettings: action('toggle-settings'),
+ },
+} satisfies Meta;
-export function Default(): JSX.Element {
- return ;
+export function Default(args: PropsType): JSX.Element {
+ return ;
}
-export function LobbyStyle(): JSX.Element {
+export function LobbyStyle(args: PropsType): JSX.Element {
return (
;
+}
-export function WithParticipants(): JSX.Element {
+export function WithParticipantsShown(args: PropsType): JSX.Element {
return (
);
}
-export function WithParticipantsShown(): JSX.Element {
+export function LongTitle(args: PropsType): JSX.Element {
return (
);
}
-WithParticipantsShown.story = {
- name: 'With Participants (shown)',
-};
-
-export function LongTitle(): JSX.Element {
+export function TitleWithMessage(args: PropsType): JSX.Element {
return (
-
+
);
}
-
-export function TitleWithMessage(): JSX.Element {
- return (
-
- );
-}
-
-TitleWithMessage.story = {
- name: 'Title with message',
-};
diff --git a/ts/components/CallingLobby.stories.tsx b/ts/components/CallingLobby.stories.tsx
index 645218b6d967..adff3383014d 100644
--- a/ts/components/CallingLobby.stories.tsx
+++ b/ts/components/CallingLobby.stories.tsx
@@ -3,10 +3,10 @@
import * as React from 'react';
import { times } from 'lodash';
-import { boolean } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions';
import { v4 as generateUuid } from 'uuid';
+import type { Meta } from '@storybook/react';
import { AvatarColors } from '../types/Colors';
import type { ConversationType } from '../state/ducks/conversations';
import type { PropsType } from './CallingLobby';
@@ -32,10 +32,7 @@ const camera = {
};
const createProps = (overrideProps: Partial = {}): PropsType => {
- const isGroupCall = boolean(
- 'isGroupCall',
- overrideProps.isGroupCall || false
- );
+ const isGroupCall = overrideProps.isGroupCall ?? false;
const conversation = isGroupCall
? getDefaultConversation({
title: 'Tahoe Trip',
@@ -49,19 +46,13 @@ const createProps = (overrideProps: Partial = {}): PropsType => {
groupMembers:
overrideProps.groupMembers ||
(isGroupCall ? times(3, () => getDefaultConversation()) : undefined),
- hasLocalAudio: boolean(
- 'hasLocalAudio',
- overrideProps.hasLocalAudio ?? true
- ),
- hasLocalVideo: boolean(
- 'hasLocalVideo',
- overrideProps.hasLocalVideo ?? false
- ),
+ hasLocalAudio: overrideProps.hasLocalAudio ?? true,
+ hasLocalVideo: overrideProps.hasLocalVideo ?? false,
i18n,
isGroupCall,
isGroupCallOutboundRingEnabled: true,
isConversationTooBigToRing: false,
- isCallFull: boolean('isCallFull', overrideProps.isCallFull || false),
+ isCallFull: overrideProps.isCallFull ?? false,
me:
overrideProps.me ||
getDefaultConversation({
@@ -71,16 +62,13 @@ const createProps = (overrideProps: Partial = {}): PropsType => {
}),
onCallCanceled: action('on-call-canceled'),
onJoinCall: action('on-join-call'),
- outgoingRing: boolean('outgoingRing', Boolean(overrideProps.outgoingRing)),
+ outgoingRing: overrideProps.outgoingRing ?? false,
peekedParticipants: overrideProps.peekedParticipants || [],
setLocalAudio: action('set-local-audio'),
setLocalPreview: action('set-local-preview'),
setLocalVideo: action('set-local-video'),
setOutgoingRing: action('set-outgoing-ring'),
- showParticipantsList: boolean(
- 'showParticipantsList',
- Boolean(overrideProps.showParticipantsList)
- ),
+ showParticipantsList: overrideProps.showParticipantsList ?? false,
toggleParticipants: action('toggle-participants'),
toggleSettings: action('toggle-settings'),
};
@@ -93,7 +81,9 @@ const fakePeekedParticipant = (conversationProps: Partial) =>
export default {
title: 'Components/CallingLobby',
-};
+ argTypes: {},
+ args: {},
+} satisfies Meta;
export function Default(): JSX.Element {
const props = createProps();
@@ -107,10 +97,6 @@ export function NoCameraNoAvatar(): JSX.Element {
return ;
}
-NoCameraNoAvatar.story = {
- name: 'No Camera, no avatar',
-};
-
export function NoCameraLocalAvatar(): JSX.Element {
const props = createProps({
availableCameras: [],
@@ -124,10 +110,6 @@ export function NoCameraLocalAvatar(): JSX.Element {
return ;
}
-NoCameraLocalAvatar.story = {
- name: 'No Camera, local avatar',
-};
-
export function LocalVideo(): JSX.Element {
const props = createProps({
hasLocalVideo: true,
@@ -142,20 +124,12 @@ export function InitiallyMuted(): JSX.Element {
return ;
}
-InitiallyMuted.story = {
- name: 'Initially muted',
-};
-
-export function GroupCall0PeekedParticipants(): JSX.Element {
+export function GroupCallWithNoPeekedParticipants(): JSX.Element {
const props = createProps({ isGroupCall: true, peekedParticipants: [] });
return ;
}
-GroupCall0PeekedParticipants.story = {
- name: 'Group Call - 0 peeked participants',
-};
-
-export function GroupCall1PeekedParticipant(): JSX.Element {
+export function GroupCallWith1PeekedParticipant(): JSX.Element {
const props = createProps({
isGroupCall: true,
peekedParticipants: [{ title: 'Sam' }].map(fakePeekedParticipant),
@@ -163,11 +137,7 @@ export function GroupCall1PeekedParticipant(): JSX.Element {
return ;
}
-GroupCall1PeekedParticipant.story = {
- name: 'Group Call - 1 peeked participant',
-};
-
-export function GroupCall1PeekedParticipantSelf(): JSX.Element {
+export function GroupCallWith1PeekedParticipantSelf(): JSX.Element {
const serviceId = generateAci();
const props = createProps({
isGroupCall: true,
@@ -180,11 +150,7 @@ export function GroupCall1PeekedParticipantSelf(): JSX.Element {
return ;
}
-GroupCall1PeekedParticipantSelf.story = {
- name: 'Group Call - 1 peeked participant (self)',
-};
-
-export function GroupCall4PeekedParticipants(): JSX.Element {
+export function GroupCallWith4PeekedParticipants(): JSX.Element {
const props = createProps({
isGroupCall: true,
peekedParticipants: ['Sam', 'Cayce', 'April', 'Logan', 'Carl'].map(title =>
@@ -194,11 +160,7 @@ export function GroupCall4PeekedParticipants(): JSX.Element {
return ;
}
-GroupCall4PeekedParticipants.story = {
- name: 'Group Call - 4 peeked participants',
-};
-
-export function GroupCall4PeekedParticipantsParticipantsList(): JSX.Element {
+export function GroupCallWith4PeekedParticipantsParticipantsList(): JSX.Element {
const props = createProps({
isGroupCall: true,
peekedParticipants: ['Sam', 'Cayce', 'April', 'Logan', 'Carl'].map(title =>
@@ -209,11 +171,7 @@ export function GroupCall4PeekedParticipantsParticipantsList(): JSX.Element {
return ;
}
-GroupCall4PeekedParticipantsParticipantsList.story = {
- name: 'Group Call - 4 peeked participants (participants list)',
-};
-
-export function GroupCallCallFull(): JSX.Element {
+export function GroupCallWithCallFull(): JSX.Element {
const props = createProps({
isGroupCall: true,
isCallFull: true,
@@ -224,18 +182,10 @@ export function GroupCallCallFull(): JSX.Element {
return ;
}
-GroupCallCallFull.story = {
- name: 'Group Call - call full',
-};
-
-export function GroupCall0PeekedParticipantsBigGroup(): JSX.Element {
+export function GroupCallWith0PeekedParticipantsBigGroup(): JSX.Element {
const props = createProps({
isGroupCall: true,
groupMembers: times(100, () => getDefaultConversation()),
});
return ;
}
-
-GroupCall0PeekedParticipantsBigGroup.story = {
- name: 'Group Call - 0 peeked participants, big group',
-};
diff --git a/ts/components/CallingParticipantsList.stories.tsx b/ts/components/CallingParticipantsList.stories.tsx
index 683932523346..e048994c8711 100644
--- a/ts/components/CallingParticipantsList.stories.tsx
+++ b/ts/components/CallingParticipantsList.stories.tsx
@@ -5,6 +5,7 @@ import * as React from 'react';
import { sample } from 'lodash';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
import type { PropsType } from './CallingParticipantsList';
import { CallingParticipantsList } from './CallingParticipantsList';
import { AvatarColors } from '../types/Colors';
@@ -47,17 +48,13 @@ const createProps = (overrideProps: Partial = {}): PropsType => ({
export default {
title: 'Components/CallingParticipantsList',
-};
+} satisfies Meta;
export function NoOne(): JSX.Element {
const props = createProps();
return ;
}
-NoOne.story = {
- name: 'No one',
-};
-
export function SoloCall(): JSX.Element {
const props = createProps({
participants: [
diff --git a/ts/components/CallingPip.stories.tsx b/ts/components/CallingPip.stories.tsx
index 1049e597a09b..2cfc22afc154 100644
--- a/ts/components/CallingPip.stories.tsx
+++ b/ts/components/CallingPip.stories.tsx
@@ -3,9 +3,8 @@
import * as React from 'react';
import { times } from 'lodash';
-import { boolean, select } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions';
-
+import type { Meta } from '@storybook/react';
import { AvatarColors } from '../types/Colors';
import type { ConversationType } from '../state/ducks/conversations';
import type { PropsType } from './CallingPip';
@@ -35,16 +34,19 @@ const conversation: ConversationType = getDefaultConversation({
profileName: 'Rick Sanchez',
});
-const getCommonActiveCallData = () => ({
+type Overrides = {
+ hasLocalAudio?: boolean;
+ hasLocalVideo?: boolean;
+ localAudioLevel?: number;
+ viewMode?: CallViewMode;
+};
+
+const getCommonActiveCallData = (overrides: Overrides) => ({
conversation,
- hasLocalAudio: boolean('hasLocalAudio', true),
- hasLocalVideo: boolean('hasLocalVideo', false),
- localAudioLevel: select('localAudioLevel', [0, 0.5, 1], 0),
- viewMode: select(
- 'viewMode',
- [CallViewMode.Grid, CallViewMode.Speaker, CallViewMode.Presentation],
- CallViewMode.Grid
- ),
+ hasLocalAudio: overrides.hasLocalAudio ?? true,
+ hasLocalVideo: overrides.hasLocalVideo ?? false,
+ localAudioLevel: overrides.localAudioLevel ?? 0,
+ viewMode: overrides.viewMode ?? CallViewMode.Grid,
joinedAt: Date.now(),
outgoingRing: true,
pip: true,
@@ -52,92 +54,93 @@ const getCommonActiveCallData = () => ({
showParticipantsList: false,
});
-const defaultCall: ActiveDirectCallType = {
- ...getCommonActiveCallData(),
- callMode: CallMode.Direct as CallMode.Direct,
- callState: CallState.Accepted,
- peekedParticipants: [],
- remoteParticipants: [
- { hasRemoteVideo: true, presenting: false, title: 'Arsene' },
- ],
+const getDefaultCall = (overrides: Overrides): ActiveDirectCallType => {
+ return {
+ ...getCommonActiveCallData(overrides),
+ callMode: CallMode.Direct as CallMode.Direct,
+ callState: CallState.Accepted,
+ peekedParticipants: [],
+ remoteParticipants: [
+ { hasRemoteVideo: true, presenting: false, title: 'Arsene' },
+ ],
+ };
};
-const createProps = (overrideProps: Partial = {}): PropsType => ({
- activeCall: overrideProps.activeCall || defaultCall,
- getGroupCallVideoFrameSource: fakeGetGroupCallVideoFrameSource,
- hangUpActiveCall: action('hang-up-active-call'),
- hasLocalVideo: boolean('hasLocalVideo', overrideProps.hasLocalVideo || false),
- i18n,
- setGroupCallVideoRequest: action('set-group-call-video-request'),
- setLocalPreview: action('set-local-preview'),
- setRendererCanvas: action('set-renderer-canvas'),
- switchFromPresentationView: action('switch-to-presentation-view'),
- switchToPresentationView: action('switch-to-presentation-view'),
- togglePip: action('toggle-pip'),
-});
-
export default {
title: 'Components/CallingPip',
-};
+ argTypes: {
+ hasLocalVideo: { control: { type: 'boolean' } },
+ },
+ args: {
+ activeCall: getDefaultCall({}),
+ getGroupCallVideoFrameSource: fakeGetGroupCallVideoFrameSource,
+ hangUpActiveCall: action('hang-up-active-call'),
+ hasLocalVideo: false,
+ i18n,
+ setGroupCallVideoRequest: action('set-group-call-video-request'),
+ setLocalPreview: action('set-local-preview'),
+ setRendererCanvas: action('set-renderer-canvas'),
+ switchFromPresentationView: action('switch-to-presentation-view'),
+ switchToPresentationView: action('switch-to-presentation-view'),
+ togglePip: action('toggle-pip'),
+ },
+} satisfies Meta;
-export function Default(): JSX.Element {
- const props = createProps({});
- return ;
+export function Default(args: PropsType): JSX.Element {
+ return ;
}
-export function ContactWithAvatarAndNoVideo(): JSX.Element {
- const props = createProps({
- activeCall: {
- ...defaultCall,
- conversation: {
- ...conversation,
- avatarPath: 'https://www.fillmurray.com/64/64',
- },
- remoteParticipants: [
- { hasRemoteVideo: false, presenting: false, title: 'Julian' },
- ],
- },
- });
- return ;
+export function ContactWithAvatarAndNoVideo(args: PropsType): JSX.Element {
+ return (
+
+ );
}
-ContactWithAvatarAndNoVideo.story = {
- name: 'Contact (with avatar and no video)',
-};
-
-export function ContactNoColor(): JSX.Element {
- const props = createProps({
- activeCall: {
- ...defaultCall,
- conversation: {
- ...conversation,
- color: undefined,
- },
- },
- });
- return ;
+export function ContactNoColor(args: PropsType): JSX.Element {
+ return (
+
+ );
}
-ContactNoColor.story = {
- name: 'Contact (no color)',
-};
-
-export function GroupCall(): JSX.Element {
- const props = createProps({
- activeCall: {
- ...getCommonActiveCallData(),
- callMode: CallMode.Group as CallMode.Group,
- connectionState: GroupCallConnectionState.Connected,
- conversationsWithSafetyNumberChanges: [],
- groupMembers: times(3, () => getDefaultConversation()),
- isConversationTooBigToRing: false,
- joinState: GroupCallJoinState.Joined,
- maxDevices: 5,
- deviceCount: 0,
- peekedParticipants: [],
- remoteParticipants: [],
- remoteAudioLevels: new Map(),
- },
- });
- return ;
+export function GroupCall(args: PropsType): JSX.Element {
+ return (
+ getDefaultConversation()),
+ isConversationTooBigToRing: false,
+ joinState: GroupCallJoinState.Joined,
+ maxDevices: 5,
+ deviceCount: 0,
+ peekedParticipants: [],
+ remoteParticipants: [],
+ remoteAudioLevels: new Map(),
+ }}
+ />
+ );
}
diff --git a/ts/components/CallingPreCallInfo.stories.tsx b/ts/components/CallingPreCallInfo.stories.tsx
index 4297403e6b02..c20e0d8940f1 100644
--- a/ts/components/CallingPreCallInfo.stories.tsx
+++ b/ts/components/CallingPreCallInfo.stories.tsx
@@ -3,10 +3,11 @@
import React from 'react';
import { times } from 'lodash';
+import type { Meta } from '@storybook/react';
import { setupI18n } from '../util/setupI18n';
import enMessages from '../../_locales/en/messages.json';
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
-
+import type { PropsType } from './CallingPreCallInfo';
import { CallingPreCallInfo, RingMode } from './CallingPreCallInfo';
const i18n = setupI18n('en', enMessages);
@@ -22,7 +23,7 @@ const otherMembers = times(6, () => getDefaultConversation());
export default {
title: 'Components/CallingPreCallInfo',
-};
+} satisfies Meta;
export function DirectConversation(): JSX.Element {
return (
@@ -35,10 +36,6 @@ export function DirectConversation(): JSX.Element {
);
}
-DirectConversation.story = {
- name: 'Direct conversation',
-};
-
export function Ring0(): JSX.Element {
return (
);
}
-
-GroupConversationCallIsFull.story = {
- name: 'Group conversation, call is full',
-};
diff --git a/ts/components/CallingPreCallInfo.tsx b/ts/components/CallingPreCallInfo.tsx
index 72992f33fd48..d0be1edf92fd 100644
--- a/ts/components/CallingPreCallInfo.tsx
+++ b/ts/components/CallingPreCallInfo.tsx
@@ -15,7 +15,7 @@ export enum RingMode {
IsRinging,
}
-type PropsType = {
+export type PropsType = {
conversation: Pick<
ConversationType,
| 'acceptedMessageRequest'
diff --git a/ts/components/CallingScreenSharingController.stories.tsx b/ts/components/CallingScreenSharingController.stories.tsx
index 76211b4887fc..08a1c30430f4 100644
--- a/ts/components/CallingScreenSharingController.stories.tsx
+++ b/ts/components/CallingScreenSharingController.stories.tsx
@@ -4,6 +4,7 @@
import React from 'react';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
import type { PropsType } from './CallingScreenSharingController';
import { CallingScreenSharingController } from './CallingScreenSharingController';
@@ -21,7 +22,7 @@ const createProps = (overrideProps: Partial = {}): PropsType => ({
export default {
title: 'Components/CallingScreenSharingController',
-};
+} satisfies Meta;
export function Controller(): JSX.Element {
return ;
@@ -37,7 +38,3 @@ export function ReallyLongAppName(): JSX.Element {
/>
);
}
-
-ReallyLongAppName.story = {
- name: 'Really long app name',
-};
diff --git a/ts/components/CallingSelectPresentingSourcesModal.stories.tsx b/ts/components/CallingSelectPresentingSourcesModal.stories.tsx
index e48a88539a5e..ce7332176ec6 100644
--- a/ts/components/CallingSelectPresentingSourcesModal.stories.tsx
+++ b/ts/components/CallingSelectPresentingSourcesModal.stories.tsx
@@ -4,6 +4,7 @@
import React from 'react';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
import type { PropsType } from './CallingSelectPresentingSourcesModal';
import { CallingSelectPresentingSourcesModal } from './CallingSelectPresentingSourcesModal';
@@ -55,7 +56,7 @@ const createProps = (): PropsType => ({
export default {
title: 'Components/CallingSelectPresentingSourcesModal',
-};
+} satisfies Meta;
export function Modal(): JSX.Element {
return ;
diff --git a/ts/components/CaptchaDialog.stories.tsx b/ts/components/CaptchaDialog.stories.tsx
index b52aefd6bead..d9071414db36 100644
--- a/ts/components/CaptchaDialog.stories.tsx
+++ b/ts/components/CaptchaDialog.stories.tsx
@@ -3,36 +3,33 @@
import React, { useState } from 'react';
import { action } from '@storybook/addon-actions';
-import { boolean } from '@storybook/addon-knobs';
-
+import type { Meta } from '@storybook/react';
+import type { PropsType } from './CaptchaDialog';
import { CaptchaDialog } from './CaptchaDialog';
import { Button } from './Button';
import { setupI18n } from '../util/setupI18n';
import enMessages from '../../_locales/en/messages.json';
-export default {
- title: 'Components/CaptchaDialog',
-};
-
const i18n = setupI18n('en', enMessages);
-export const _CaptchaDialog = (): JSX.Element => {
+export default {
+ title: 'Components/CaptchaDialog',
+ argTypes: {
+ isPending: { control: { type: 'boolean' } },
+ },
+ args: {
+ i18n,
+ isPending: false,
+ onContinue: action('onContinue'),
+ },
+} satisfies Meta;
+
+export function Basic(args: PropsType): JSX.Element {
const [isSkipped, setIsSkipped] = useState(false);
if (isSkipped) {
return ;
}
- return (
- setIsSkipped(true)}
- />
- );
-};
-
-_CaptchaDialog.story = {
- name: 'CaptchaDialog',
-};
+ return setIsSkipped(true)} />;
+}
diff --git a/ts/components/CaptchaDialog.tsx b/ts/components/CaptchaDialog.tsx
index 8f864f0a0dc6..0b9091960df7 100644
--- a/ts/components/CaptchaDialog.tsx
+++ b/ts/components/CaptchaDialog.tsx
@@ -8,7 +8,7 @@ import { Button, ButtonVariant } from './Button';
import { Modal } from './Modal';
import { Spinner } from './Spinner';
-type PropsType = {
+export type PropsType = {
i18n: LocalizerType;
isPending: boolean;
diff --git a/ts/components/ChatColorPicker.stories.tsx b/ts/components/ChatColorPicker.stories.tsx
index 597caa4e74e1..c8b534115b16 100644
--- a/ts/components/ChatColorPicker.stories.tsx
+++ b/ts/components/ChatColorPicker.stories.tsx
@@ -2,21 +2,45 @@
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
-
import { action } from '@storybook/addon-actions';
-import { select } from '@storybook/addon-knobs';
-
+import type { Meta } from '@storybook/react';
import enMessages from '../../_locales/en/messages.json';
import type { PropsType } from './ChatColorPicker';
import { ChatColorPicker } from './ChatColorPicker';
import { ConversationColors } from '../types/Colors';
import { setupI18n } from '../util/setupI18n';
+const i18n = setupI18n('en', enMessages);
+
export default {
title: 'Components/ChatColorPicker',
-};
-
-const i18n = setupI18n('en', enMessages);
+ argTypes: {
+ selectedColor: {
+ control: {
+ type: 'select',
+ options: ConversationColors,
+ },
+ },
+ },
+ args: {
+ addCustomColor: action('addCustomColor'),
+ colorSelected: action('colorSelected'),
+ editCustomColor: action('editCustomColor'),
+ getConversationsWithCustomColor: (_: string) => Promise.resolve([]),
+ i18n,
+ removeCustomColor: action('removeCustomColor'),
+ removeCustomColorOnConversations: action(
+ 'removeCustomColorOnConversations'
+ ),
+ resetAllChatColors: action('resetAllChatColors'),
+ resetDefaultChatColor: action('resetDefaultChatColor'),
+ selectedColor: 'basil',
+ selectedCustomColor: {},
+ setGlobalDefaultConversationColor: action(
+ 'setGlobalDefaultConversationColor'
+ ),
+ },
+} satisfies Meta;
const SAMPLE_CUSTOM_COLOR = {
deg: 90,
@@ -24,25 +48,8 @@ const SAMPLE_CUSTOM_COLOR = {
start: { hue: 315, saturation: 78 },
};
-const createProps = (): PropsType => ({
- addCustomColor: action('addCustomColor'),
- colorSelected: action('colorSelected'),
- editCustomColor: action('editCustomColor'),
- getConversationsWithCustomColor: (_: string) => Promise.resolve([]),
- i18n,
- removeCustomColor: action('removeCustomColor'),
- removeCustomColorOnConversations: action('removeCustomColorOnConversations'),
- resetAllChatColors: action('resetAllChatColors'),
- resetDefaultChatColor: action('resetDefaultChatColor'),
- selectedColor: select('selectedColor', ConversationColors, 'basil' as const),
- selectedCustomColor: {},
- setGlobalDefaultConversationColor: action(
- 'setGlobalDefaultConversationColor'
- ),
-});
-
-export function Default(): JSX.Element {
- return ;
+export function Default(args: PropsType): JSX.Element {
+ return ;
}
const CUSTOM_COLORS = {
@@ -62,10 +69,10 @@ const CUSTOM_COLORS = {
},
};
-export function CustomColors(): JSX.Element {
+export function CustomColors(args: PropsType): JSX.Element {
return (
({
export default {
title: 'Components/Checkbox',
-};
+} satisfies Meta;
export function Normal(): JSX.Element {
return ;
diff --git a/ts/components/CircleCheckbox.stories.tsx b/ts/components/CircleCheckbox.stories.tsx
index 0a7260251ebf..1e8b033b3f7d 100644
--- a/ts/components/CircleCheckbox.stories.tsx
+++ b/ts/components/CircleCheckbox.stories.tsx
@@ -3,7 +3,7 @@
import React from 'react';
import { action } from '@storybook/addon-actions';
-
+import type { Meta } from '@storybook/react';
import type { Props } from './CircleCheckbox';
import { CircleCheckbox, Variant } from './CircleCheckbox';
@@ -15,7 +15,7 @@ const createProps = (): Props => ({
export default {
title: 'Components/CircleCheckbox',
-};
+} satisfies Meta;
export function Normal(): JSX.Element {
return ;
diff --git a/ts/components/ClearingData.stories.tsx b/ts/components/ClearingData.stories.tsx
index 3dacf136b654..e6e183f84154 100644
--- a/ts/components/ClearingData.stories.tsx
+++ b/ts/components/ClearingData.stories.tsx
@@ -2,23 +2,19 @@
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
-
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
import { setupI18n } from '../util/setupI18n';
import enMessages from '../../_locales/en/messages.json';
-
+import type { PropsType } from './ClearingData';
import { ClearingData } from './ClearingData';
const i18n = setupI18n('en', enMessages);
export default {
title: 'Components/ClearingData',
-};
+} satisfies Meta;
-export const _ClearingData = (): JSX.Element => (
-
-);
-
-_ClearingData.story = {
- name: 'Clearing data',
-};
+export function Basic(): JSX.Element {
+ return ;
+}
diff --git a/ts/components/CompositionArea.stories.tsx b/ts/components/CompositionArea.stories.tsx
index 58d414ce2850..3dde92c340a5 100644
--- a/ts/components/CompositionArea.stories.tsx
+++ b/ts/components/CompositionArea.stories.tsx
@@ -1,12 +1,9 @@
// Copyright 2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
-import type { DecoratorFunction } from '@storybook/addons';
-import * as React from 'react';
-
+import React, { useContext } from 'react';
import { action } from '@storybook/addon-actions';
-import { boolean, select } from '@storybook/addon-knobs';
-
+import type { Meta } from '@storybook/react';
import { IMAGE_JPEG } from '../types/MIME';
import type { Props } from './CompositionArea';
import { CompositionArea } from './CompositionArea';
@@ -28,287 +25,256 @@ export default {
decorators: [
// necessary for the add attachment button to render properly
storyFn => {storyFn()}
,
- ] as Array>,
-};
+ ],
+ argTypes: {
+ recordingState: {
+ control: { type: 'select' },
+ options: Object.keys(RecordingState),
+ mappings: RecordingState,
+ },
+ messageRequestsEnabled: { control: { type: 'boolean' } },
+ announcementsOnly: { control: { type: 'boolean' } },
+ areWePendingApproval: { control: { type: 'boolean' } },
+ },
+ args: {
+ addAttachment: action('addAttachment'),
+ conversationId: '123',
+ convertDraftBodyRangesIntoHydrated: () => undefined,
+ discardEditMessage: action('discardEditMessage'),
+ focusCounter: 0,
+ sendCounter: 0,
+ i18n,
+ isDisabled: false,
+ isFormattingFlagEnabled: true,
+ isFormattingSpoilersFlagEnabled: true,
+ isFormattingEnabled: true,
+ messageCompositionId: '456',
+ sendEditedMessage: action('sendEditedMessage'),
+ sendMultiMediaMessage: action('sendMultiMediaMessage'),
+ platform: 'darwin',
+ processAttachments: action('processAttachments'),
+ removeAttachment: action('removeAttachment'),
+ setComposerFocus: action('setComposerFocus'),
+ setMessageToEdit: action('setMessageToEdit'),
+ setQuoteByMessageId: action('setQuoteByMessageId'),
+ showToast: action('showToast'),
-const useProps = (overrideProps: Partial = {}): Props => ({
- addAttachment: action('addAttachment'),
- conversationId: '123',
- convertDraftBodyRangesIntoHydrated: () => undefined,
- discardEditMessage: action('discardEditMessage'),
- focusCounter: 0,
- sendCounter: 0,
- i18n,
- isDisabled: false,
- isFormattingFlagEnabled:
- overrideProps.isFormattingFlagEnabled === false
- ? overrideProps.isFormattingFlagEnabled
- : true,
- isFormattingSpoilersFlagEnabled:
- overrideProps.isFormattingSpoilersFlagEnabled === false
- ? overrideProps.isFormattingSpoilersFlagEnabled
- : true,
- isFormattingEnabled:
- overrideProps.isFormattingEnabled === false
- ? overrideProps.isFormattingEnabled
- : true,
- messageCompositionId: '456',
- sendEditedMessage: action('sendEditedMessage'),
- sendMultiMediaMessage: action('sendMultiMediaMessage'),
- platform: 'darwin',
- processAttachments: action('processAttachments'),
- removeAttachment: action('removeAttachment'),
- theme: React.useContext(StorybookThemeContext),
- setComposerFocus: action('setComposerFocus'),
- setMessageToEdit: action('setMessageToEdit'),
- setQuoteByMessageId: action('setQuoteByMessageId'),
- showToast: action('showToast'),
+ // AttachmentList
+ draftAttachments: [],
+ onClearAttachments: action('onClearAttachments'),
+ // AudioCapture
+ cancelRecording: action('cancelRecording'),
+ completeRecording: action('completeRecording'),
+ errorRecording: action('errorRecording'),
+ recordingState: RecordingState.Idle,
+ startRecording: action('startRecording'),
+ // StagedLinkPreview
+ linkPreviewLoading: false,
+ linkPreviewResult: undefined,
+ onCloseLinkPreview: action('onCloseLinkPreview'),
+ // Quote
+ quotedMessageProps: undefined,
+ scrollToMessage: action('scrollToMessage'),
+ // MediaEditor
+ imageToBlurHash: async () => 'LDA,FDBnm+I=p{tkIUI;~UkpELV]',
+ // MediaQualitySelector
+ setMediaQualitySetting: action('setMediaQualitySetting'),
+ shouldSendHighQualityAttachments: false,
+ // CompositionInput
+ onEditorStateChange: action('onEditorStateChange'),
+ onTextTooLong: action('onTextTooLong'),
+ draftText: undefined,
+ clearQuotedMessage: action('clearQuotedMessage'),
+ getPreferredBadge: () => undefined,
+ getQuotedMessage: action('getQuotedMessage'),
+ sortedGroupMembers: [],
+ // EmojiButton
+ onPickEmoji: action('onPickEmoji'),
+ onSetSkinTone: action('onSetSkinTone'),
+ recentEmojis: [],
+ skinTone: 1,
+ // StickerButton
+ knownPacks: [],
+ receivedPacks: [],
+ installedPacks: [],
+ blessedPacks: [],
+ recentStickers: [],
+ clearInstalledStickerPack: action('clearInstalledStickerPack'),
+ pushPanelForConversation: action('pushPanelForConversation'),
+ sendStickerMessage: action('sendStickerMessage'),
+ clearShowIntroduction: action('clearShowIntroduction'),
+ showPickerHint: false,
+ clearShowPickerHint: action('clearShowPickerHint'),
+ // Message Requests
+ conversationType: 'direct',
+ acceptConversation: action('acceptConversation'),
+ blockConversation: action('blockConversation'),
+ blockAndReportSpam: action('blockAndReportSpam'),
+ deleteConversation: action('deleteConversation'),
+ messageRequestsEnabled: false,
+ title: '',
+ // GroupV1 Disabled Actions
+ showGV2MigrationDialog: action('showGV2MigrationDialog'),
+ // GroupV2
+ announcementsOnly: false,
+ areWeAdmin: false,
+ areWePendingApproval: false,
+ groupAdmins: [],
+ cancelJoinRequest: action('cancelJoinRequest'),
+ showConversation: action('showConversation'),
+ // SMS-only
+ isSMSOnly: false,
+ isFetchingUUID: false,
+ renderSmartCompositionRecording: _ => RECORDING
,
+ renderSmartCompositionRecordingDraft: _ => RECORDING DRAFT
,
+ // Select mode
+ selectedMessageIds: undefined,
+ toggleSelectMode: action('toggleSelectMode'),
+ toggleForwardMessagesModal: action('toggleForwardMessagesModal'),
+ },
+} satisfies Meta;
- // AttachmentList
- draftAttachments: overrideProps.draftAttachments || [],
- onClearAttachments: action('onClearAttachments'),
- // AudioCapture
- cancelRecording: action('cancelRecording'),
- completeRecording: action('completeRecording'),
- errorRecording: action('errorRecording'),
- recordingState: select(
- 'recordingState',
- RecordingState,
- overrideProps.recordingState || RecordingState.Idle
- ),
- startRecording: action('startRecording'),
- // StagedLinkPreview
- linkPreviewLoading: Boolean(overrideProps.linkPreviewLoading),
- linkPreviewResult: overrideProps.linkPreviewResult,
- onCloseLinkPreview: action('onCloseLinkPreview'),
- // Quote
- quotedMessageProps: overrideProps.quotedMessageProps,
- scrollToMessage: action('scrollToMessage'),
- // MediaEditor
- imageToBlurHash: async () => 'LDA,FDBnm+I=p{tkIUI;~UkpELV]',
- // MediaQualitySelector
- setMediaQualitySetting: action('setMediaQualitySetting'),
- shouldSendHighQualityAttachments: Boolean(
- overrideProps.shouldSendHighQualityAttachments
- ),
- // CompositionInput
- onEditorStateChange: action('onEditorStateChange'),
- onTextTooLong: action('onTextTooLong'),
- draftText: overrideProps.draftText || undefined,
- clearQuotedMessage: action('clearQuotedMessage'),
- getPreferredBadge: () => undefined,
- getQuotedMessage: action('getQuotedMessage'),
- sortedGroupMembers: [],
- // EmojiButton
- onPickEmoji: action('onPickEmoji'),
- onSetSkinTone: action('onSetSkinTone'),
- recentEmojis: [],
- skinTone: 1,
- // StickerButton
- knownPacks: overrideProps.knownPacks || [],
- receivedPacks: [],
- installedPacks: [],
- blessedPacks: [],
- recentStickers: [],
- clearInstalledStickerPack: action('clearInstalledStickerPack'),
- pushPanelForConversation: action('pushPanelForConversation'),
- sendStickerMessage: action('sendStickerMessage'),
- clearShowIntroduction: action('clearShowIntroduction'),
- showPickerHint: false,
- clearShowPickerHint: action('clearShowPickerHint'),
- // Message Requests
- conversationType: 'direct',
- acceptConversation: action('acceptConversation'),
- blockConversation: action('blockConversation'),
- blockAndReportSpam: action('blockAndReportSpam'),
- deleteConversation: action('deleteConversation'),
- messageRequestsEnabled: boolean(
- 'messageRequestsEnabled',
- overrideProps.messageRequestsEnabled || false
- ),
- title: '',
- // GroupV1 Disabled Actions
- showGV2MigrationDialog: action('showGV2MigrationDialog'),
- // GroupV2
- announcementsOnly: boolean(
- 'announcementsOnly',
- Boolean(overrideProps.announcementsOnly)
- ),
- areWeAdmin: boolean('areWeAdmin', Boolean(overrideProps.areWeAdmin)),
- areWePendingApproval: boolean(
- 'areWePendingApproval',
- Boolean(overrideProps.areWePendingApproval)
- ),
- groupAdmins: [],
- cancelJoinRequest: action('cancelJoinRequest'),
- showConversation: action('showConversation'),
- // SMS-only
- isSMSOnly: overrideProps.isSMSOnly || false,
- isFetchingUUID: overrideProps.isFetchingUUID || false,
- renderSmartCompositionRecording: _ => RECORDING
,
- renderSmartCompositionRecordingDraft: _ => RECORDING DRAFT
,
- // Select mode
- selectedMessageIds: undefined,
- toggleSelectMode: action('toggleSelectMode'),
- toggleForwardMessagesModal: action('toggleForwardMessagesModal'),
-});
-
-export function Default(): JSX.Element {
- const props = useProps();
-
- return ;
+export function Default(args: Props): JSX.Element {
+ const theme = useContext(StorybookThemeContext);
+ return ;
}
-export function StartingText(): JSX.Element {
- const props = useProps({
- draftText: "here's some starting text",
- });
-
- return ;
-}
-
-export function StickerButton(): JSX.Element {
- const props = useProps({
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- knownPacks: [{} as any],
- });
-
- return ;
-}
-
-export function MessageRequest(): JSX.Element {
- const props = useProps({
- messageRequestsEnabled: true,
- });
-
- return ;
-}
-
-export function SmsOnlyFetchingUuid(): JSX.Element {
- const props = useProps({
- isSMSOnly: true,
- isFetchingUUID: true,
- });
-
- return ;
-}
-
-SmsOnlyFetchingUuid.story = {
- name: 'SMS-only fetching UUID',
-};
-
-export function SmsOnly(): JSX.Element {
- const props = useProps({
- isSMSOnly: true,
- });
-
- return ;
-}
-
-SmsOnly.story = {
- name: 'SMS-only',
-};
-
-export function Attachments(): JSX.Element {
- const props = useProps({
- draftAttachments: [
- fakeDraftAttachment({
- contentType: IMAGE_JPEG,
- url: landscapeGreenUrl,
- }),
- ],
- });
-
- return ;
-}
-
-export function PendingApproval(): JSX.Element {
+export function StartingText(args: Props): JSX.Element {
+ const theme = useContext(StorybookThemeContext);
return (
);
}
-AnnouncementsOnlyGroup.story = {
- name: 'Announcements Only group',
-};
-
-export function AnnouncementsOnlyGroup(): JSX.Element {
+export function StickerButton(args: Props): JSX.Element {
+ const theme = useContext(StorybookThemeContext);
return (
);
}
-AnnouncementsOnlyGroup.story = {
- name: 'Announcements Only group',
-};
+export function MessageRequest(args: Props): JSX.Element {
+ const theme = useContext(StorybookThemeContext);
+ return ;
+}
-export function Quote(): JSX.Element {
+export function SmsOnlyFetchingUuid(args: Props): JSX.Element {
+ const theme = useContext(StorybookThemeContext);
+ return ;
+}
+
+export function SmsOnly(args: Props): JSX.Element {
+ const theme = useContext(StorybookThemeContext);
+ return ;
+}
+
+export function Attachments(args: Props): JSX.Element {
+ const theme = useContext(StorybookThemeContext);
return (
+ );
+}
+
+export function PendingApproval(args: Props): JSX.Element {
+ const theme = useContext(StorybookThemeContext);
+ return ;
+}
+
+export function AnnouncementsOnlyGroup(args: Props): JSX.Element {
+ const theme = useContext(StorybookThemeContext);
+ return (
+
+ );
+}
+
+export function Quote(args: Props): JSX.Element {
+ const theme = useContext(StorybookThemeContext);
+ return (
+
+ );
+}
+
+export function QuoteWithPayment(args: Props): JSX.Element {
+ const theme = useContext(StorybookThemeContext);
+ return (
+
);
}
-export function QuoteWithPayment(): JSX.Element {
+export function NoFormattingMenu(args: Props): JSX.Element {
+ const theme = useContext(StorybookThemeContext);
+ return (
+
+ );
+}
+
+export function NoFormattingFlag(args: Props): JSX.Element {
+ const theme = useContext(StorybookThemeContext);
+ return (
+
+ );
+}
+
+export function NoSpoilerFormattingFlag(args: Props): JSX.Element {
+ const theme = useContext(StorybookThemeContext);
return (
- );
-}
-
-QuoteWithPayment.story = {
- name: 'Quote with payment',
-};
-
-export function NoFormattingMenu(): JSX.Element {
- return ;
-}
-
-export function NoFormattingFlag(): JSX.Element {
- return ;
-}
-
-export function NoSpoilerFormattingFlag(): JSX.Element {
- return (
-
);
}
diff --git a/ts/components/CompositionInput.stories.tsx b/ts/components/CompositionInput.stories.tsx
index e9b57d1dc097..86371085bdc5 100644
--- a/ts/components/CompositionInput.stories.tsx
+++ b/ts/components/CompositionInput.stories.tsx
@@ -2,11 +2,9 @@
// SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react';
-
import 'react-quill/dist/quill.core.css';
-import { boolean, select } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions';
-
+import type { Meta } from '@storybook/react';
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
import type { Props } from './CompositionInput';
import { CompositionInput } from './CompositionInput';
@@ -19,11 +17,13 @@ const i18n = setupI18n('en', enMessages);
export default {
title: 'Components/CompositionInput',
-};
+ argTypes: {},
+ args: {},
+} satisfies Meta;
const useProps = (overrideProps: Partial = {}): Props => ({
i18n,
- disabled: boolean('disabled', overrideProps.disabled || false),
+ disabled: overrideProps.disabled ?? false,
draftText: overrideProps.draftText || undefined,
draftBodyRanges: overrideProps.draftBodyRanges || [],
clearQuotedMessage: action('clearQuotedMessage'),
@@ -41,7 +41,7 @@ const useProps = (overrideProps: Partial = {}): Props => ({
overrideProps.isFormattingEnabled === false
? overrideProps.isFormattingEnabled
: true,
- large: boolean('large', overrideProps.large || false),
+ large: overrideProps.large ?? false,
onCloseLinkPreview: action('onCloseLinkPreview'),
onEditorStateChange: action('onEditorStateChange'),
onPickEmoji: action('onPickEmoji'),
@@ -49,19 +49,8 @@ const useProps = (overrideProps: Partial = {}): Props => ({
onTextTooLong: action('onTextTooLong'),
platform: 'darwin',
sendCounter: 0,
- sortedGroupMembers: overrideProps.sortedGroupMembers || [],
- skinTone: select(
- 'skinTone',
- {
- skinTone0: 0,
- skinTone1: 1,
- skinTone2: 2,
- skinTone3: 3,
- skinTone4: 4,
- skinTone5: 5,
- },
- overrideProps.skinTone || undefined
- ),
+ sortedGroupMembers: overrideProps.sortedGroupMembers ?? [],
+ skinTone: overrideProps.skinTone ?? undefined,
theme: React.useContext(StorybookThemeContext),
});
diff --git a/ts/components/CompositionRecording.stories.tsx b/ts/components/CompositionRecording.stories.tsx
index d537c39447fd..7619ccb93798 100644
--- a/ts/components/CompositionRecording.stories.tsx
+++ b/ts/components/CompositionRecording.stories.tsx
@@ -3,8 +3,9 @@
import React, { useState } from 'react';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
+import type { Props } from './CompositionRecording';
import { CompositionRecording } from './CompositionRecording';
-
import { setupI18n } from '../util/setupI18n';
import enMessages from '../../_locales/en/messages.json';
@@ -13,7 +14,7 @@ const i18n = setupI18n('en', enMessages);
export default {
title: 'components/CompositionRecording',
component: CompositionRecording,
-};
+} satisfies Meta;
export function Default(): JSX.Element {
const [active, setActive] = useState(false);
diff --git a/ts/components/CompositionRecordingDraft.stories.tsx b/ts/components/CompositionRecordingDraft.stories.tsx
index 10d966b5a67e..ac59696708be 100644
--- a/ts/components/CompositionRecordingDraft.stories.tsx
+++ b/ts/components/CompositionRecordingDraft.stories.tsx
@@ -3,8 +3,9 @@
import React, { useState } from 'react';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
+import type { Props } from './CompositionRecordingDraft';
import { CompositionRecordingDraft } from './CompositionRecordingDraft';
-
import { setupI18n } from '../util/setupI18n';
import enMessages from '../../_locales/en/messages.json';
@@ -13,7 +14,7 @@ const i18n = setupI18n('en', enMessages);
export default {
title: 'components/CompositionRecordingDraft',
component: CompositionRecordingDraft,
-};
+} satisfies Meta;
export function Default(): JSX.Element {
const [isPlaying, setIsPlaying] = useState(false);
diff --git a/ts/components/CompositionRecordingDraft.tsx b/ts/components/CompositionRecordingDraft.tsx
index ae26b10502d7..de09f672ecfc 100644
--- a/ts/components/CompositionRecordingDraft.tsx
+++ b/ts/components/CompositionRecordingDraft.tsx
@@ -11,7 +11,7 @@ import * as log from '../logging/log';
import type { Size } from '../hooks/useSizeObserver';
import { SizeObserver } from '../hooks/useSizeObserver';
-type Props = {
+export type Props = {
i18n: LocalizerType;
audioUrl: string | undefined;
active:
diff --git a/ts/components/ConfirmDiscardDialog.stories.tsx b/ts/components/ConfirmDiscardDialog.stories.tsx
index 9f3bb14976fa..04ef5da27572 100644
--- a/ts/components/ConfirmDiscardDialog.stories.tsx
+++ b/ts/components/ConfirmDiscardDialog.stories.tsx
@@ -4,6 +4,7 @@
import React from 'react';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
import { setupI18n } from '../util/setupI18n';
import enMessages from '../../_locales/en/messages.json';
@@ -20,7 +21,7 @@ const createProps = (): PropsType => ({
export default {
title: 'Components/ConfirmDiscardDialog',
-};
+} satisfies Meta;
export function Default(): JSX.Element {
return ;
diff --git a/ts/components/ConfirmationDialog.stories.tsx b/ts/components/ConfirmationDialog.stories.tsx
index 7a3aec6b5a19..629e19e1f443 100644
--- a/ts/components/ConfirmationDialog.stories.tsx
+++ b/ts/components/ConfirmationDialog.stories.tsx
@@ -4,6 +4,8 @@
import * as React from 'react';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
+import type { Props } from './ConfirmationDialog';
import { ConfirmationDialog } from './ConfirmationDialog';
import { setupI18n } from '../util/setupI18n';
import enMessages from '../../_locales/en/messages.json';
@@ -12,9 +14,9 @@ const i18n = setupI18n('en', enMessages);
export default {
title: 'Components/ConfirmationDialog',
-};
+} satisfies Meta;
-export const _ConfirmationDialog = (): JSX.Element => {
+export function Basic(): JSX.Element {
return (
{
asdf blip
);
-};
-
-_ConfirmationDialog.story = {
- name: 'ConfirmationDialog',
-};
+}
export function CustomCancelText(): JSX.Element {
return (
@@ -64,10 +62,6 @@ export function CustomCancelText(): JSX.Element {
);
}
-CustomCancelText.story = {
- name: 'Custom cancel text',
-};
-
export function NoDefaultCancel(): JSX.Element {
return (
;
type ContactType = Omit;
@@ -54,10 +55,6 @@ export function EmptyList(): JSX.Element {
return ;
}
-EmptyList.story = {
- name: 'Empty list',
-};
-
export function OneContact(): JSX.Element {
return (
@@ -66,10 +63,6 @@ export function OneContact(): JSX.Element {
);
}
-OneContact.story = {
- name: 'One contact',
-};
-
export function ThreeContacts(): JSX.Element {
return (
@@ -80,10 +73,6 @@ export function ThreeContacts(): JSX.Element {
);
}
-ThreeContacts.story = {
- name: 'Three contacts',
-};
-
export function FourContactsOneWithALongName(): JSX.Element {
return (
@@ -101,10 +90,6 @@ export function FourContactsOneWithALongName(): JSX.Element {
);
}
-FourContactsOneWithALongName.story = {
- name: 'Four contacts, one with a long name',
-};
-
export function FiftyContacts(): JSX.Element {
return (
@@ -114,7 +99,3 @@ export function FiftyContacts(): JSX.Element {
);
}
-
-FiftyContacts.story = {
- name: 'Fifty contacts',
-};
diff --git a/ts/components/ContextMenu.stories.tsx b/ts/components/ContextMenu.stories.tsx
index 5dc2b038311b..cdb4e70f3396 100644
--- a/ts/components/ContextMenu.stories.tsx
+++ b/ts/components/ContextMenu.stories.tsx
@@ -4,6 +4,7 @@
import React from 'react';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
import type { PropsType } from './ContextMenu';
import { ContextMenu } from './ContextMenu';
import enMessages from '../../_locales/en/messages.json';
@@ -13,7 +14,7 @@ const i18n = setupI18n('en', enMessages);
export default {
title: 'Components/ContextMenu',
-};
+} satisfies Meta>;
const getDefaultProps = (): PropsType => ({
i18n,
diff --git a/ts/components/ConversationList.stories.tsx b/ts/components/ConversationList.stories.tsx
index 8e2db3fe4333..7422077a7157 100644
--- a/ts/components/ConversationList.stories.tsx
+++ b/ts/components/ConversationList.stories.tsx
@@ -4,11 +4,9 @@
import React, { useContext } from 'react';
import { times, omit } from 'lodash';
import { v4 as generateUuid } from 'uuid';
-
import { action } from '@storybook/addon-actions';
-import { boolean, date, select, text } from '@storybook/addon-knobs';
-
-import type { Row } from './ConversationList';
+import type { Meta } from '@storybook/react';
+import type { Row, PropsType } from './ConversationList';
import { ConversationList, RowType } from './ConversationList';
import { MessageSearchResult } from './conversationList/MessageSearchResult';
import type { PropsData as ConversationListItemPropsType } from './conversationList/ConversationListItem';
@@ -25,7 +23,9 @@ const i18n = setupI18n('en', enMessages);
export default {
title: 'Components/ConversationList',
-};
+ argTypes: {},
+ args: {},
+} satisfies Meta;
const defaultConversations: Array = [
getDefaultConversation({
@@ -105,15 +105,13 @@ function Wrapper({
);
}
-export const _ArchiveButton = (): JSX.Element => (
-
-);
-
-_ArchiveButton.story = {
- name: 'Archive button',
-};
+export function ArchiveButton(): JSX.Element {
+ return (
+
+ );
+}
export function ContactNoteToSelf(): JSX.Element {
return (
@@ -132,10 +130,6 @@ export function ContactNoteToSelf(): JSX.Element {
);
}
-ContactNoteToSelf.story = {
- name: 'Contact: note to self',
-};
-
export function ContactDirect(): JSX.Element {
return (
= {}
): ConversationListItemPropsType => ({
...overrideProps,
- acceptedMessageRequest: boolean(
- 'acceptedMessageRequest',
+ acceptedMessageRequest:
overrideProps.acceptedMessageRequest !== undefined
? overrideProps.acceptedMessageRequest
- : true
- ),
+ : true,
badges: [],
- isMe: boolean('isMe', overrideProps.isMe || false),
- avatarPath: text('avatarPath', overrideProps.avatarPath || ''),
+ isMe: overrideProps.isMe ?? false,
+ avatarPath: overrideProps.avatarPath ?? '',
id: overrideProps.id || '',
- isSelected: boolean('isSelected', overrideProps.isSelected || false),
- title: text('title', overrideProps.title || 'Some Person'),
+ isSelected: overrideProps.isSelected ?? false,
+ title: overrideProps.title ?? 'Some Person',
profileName: overrideProps.profileName || 'Some Person',
type: overrideProps.type || 'direct',
- markedUnread: boolean('markedUnread', overrideProps.markedUnread || false),
+ markedUnread: overrideProps.markedUnread ?? false,
lastMessage: overrideProps.lastMessage || {
- text: text('lastMessage.text', 'Hi there!'),
- status: select(
- 'status',
- MessageStatuses.reduce((m, s) => ({ ...m, [s]: s }), {}),
- 'read'
- ),
+ text: 'Hi there!',
+ status: 'read',
deletedForEveryone: false,
},
- lastUpdated: date(
- 'lastUpdated',
- new Date(overrideProps.lastUpdated || Date.now() - 5 * 60 * 1000)
- ),
+ lastUpdated: overrideProps.lastUpdated ?? Date.now() - 5 * 60 * 1000,
sharedGroupNames: [],
});
@@ -333,19 +290,11 @@ const renderConversation = (
export const ConversationName = (): JSX.Element => renderConversation();
-ConversationName.story = {
- name: 'Conversation: name',
-};
-
export const ConversationNameAndAvatar = (): JSX.Element =>
renderConversation({
avatarPath: '/fixtures/kitten-1-64-64.jpg',
});
-ConversationNameAndAvatar.story = {
- name: 'Conversation: name and avatar',
-};
-
export const ConversationWithYourself = (): JSX.Element =>
renderConversation({
lastMessage: {
@@ -358,10 +307,6 @@ export const ConversationWithYourself = (): JSX.Element =>
isMe: true,
});
-ConversationWithYourself.story = {
- name: 'Conversation: with yourself',
-};
-
export function ConversationsMessageStatuses(): JSX.Element {
return (
renderConversation({
typingContactIdTimestamps: {
- [generateUuid()]: date('timestamp', new Date()),
+ [generateUuid()]: Date.now(),
},
});
-ConversationTypingStatus.story = {
- name: 'Conversation: Typing Status',
-};
-
export const ConversationWithDraft = (): JSX.Element =>
renderConversation({
shouldShowDraft: true,
@@ -400,19 +337,11 @@ export const ConversationWithDraft = (): JSX.Element =>
},
});
-ConversationWithDraft.story = {
- name: 'Conversation: With draft',
-};
-
export const ConversationDeletedForEveryone = (): JSX.Element =>
renderConversation({
lastMessage: { deletedForEveryone: true },
});
-ConversationDeletedForEveryone.story = {
- name: 'Conversation: Deleted for everyone',
-};
-
export const ConversationMessageRequest = (): JSX.Element =>
renderConversation({
acceptedMessageRequest: false,
@@ -423,10 +352,6 @@ export const ConversationMessageRequest = (): JSX.Element =>
},
});
-ConversationMessageRequest.story = {
- name: 'Conversation: Message Request',
-};
-
export function ConversationsUnreadCount(): JSX.Element {
return (
renderConversation({ markedUnread: true });
-ConversationMarkedUnread.story = {
- name: 'Conversation: marked unread',
-};
-
export const ConversationSelected = (): JSX.Element =>
renderConversation({
lastMessage: {
@@ -466,10 +383,6 @@ export const ConversationSelected = (): JSX.Element =>
isSelected: true,
});
-ConversationSelected.story = {
- name: 'Conversation: Selected',
-};
-
export const ConversationEmojiInMessage = (): JSX.Element =>
renderConversation({
lastMessage: {
@@ -479,10 +392,6 @@ export const ConversationEmojiInMessage = (): JSX.Element =>
},
});
-ConversationEmojiInMessage.story = {
- name: 'Conversation: Emoji in Message',
-};
-
export const ConversationLinkInMessage = (): JSX.Element =>
renderConversation({
lastMessage: {
@@ -492,10 +401,6 @@ export const ConversationLinkInMessage = (): JSX.Element =>
},
});
-ConversationLinkInMessage.story = {
- name: 'Conversation: Link in Message',
-};
-
export const ConversationLongName = (): JSX.Element => {
const name =
'Long contact name. Esquire. The third. And stuff. And more! And more!';
@@ -505,10 +410,6 @@ export const ConversationLongName = (): JSX.Element => {
});
};
-ConversationLongName.story = {
- name: 'Conversation: long name',
-};
-
export function ConversationLongMessage(): JSX.Element {
const messages = [
"Long line. This is a really really really long line. Really really long. Because that's just how it is",
@@ -534,10 +435,6 @@ Line 4, well.`,
);
}
-ConversationLongMessage.story = {
- name: 'Conversation: Long Message',
-};
-
export function ConversationsVariousTimes(): JSX.Element {
const pairs: Array<[number, string]> = [
[Date.now() - 5 * 60 * 60 * 1000, 'Five hours ago'],
@@ -563,10 +460,6 @@ export function ConversationsVariousTimes(): JSX.Element {
);
}
-ConversationsVariousTimes.story = {
- name: 'Conversations: Various Times',
-};
-
export function ConversationMissingDate(): JSX.Element {
const row = {
type: RowType.Conversation as const,
@@ -576,10 +469,6 @@ export function ConversationMissingDate(): JSX.Element {
return ;
}
-ConversationMissingDate.story = {
- name: 'Conversation: Missing Date',
-};
-
export function ConversationMissingMessage(): JSX.Element {
const row = {
type: RowType.Conversation as const,
@@ -589,10 +478,6 @@ export function ConversationMissingMessage(): JSX.Element {
return ;
}
-ConversationMissingMessage.story = {
- name: 'Conversation: Missing Message',
-};
-
export const ConversationMissingText = (): JSX.Element =>
renderConversation({
lastMessage: {
@@ -602,19 +487,11 @@ export const ConversationMissingText = (): JSX.Element =>
},
});
-ConversationMissingText.story = {
- name: 'Conversation: Missing Text',
-};
-
export const ConversationMutedConversation = (): JSX.Element =>
renderConversation({
muteExpiresAt: Date.now() + 1000 * 60 * 60,
});
-ConversationMutedConversation.story = {
- name: 'Conversation: Muted Conversation',
-};
-
export const ConversationAtMention = (): JSX.Element =>
renderConversation({
title: 'The Rebellion',
@@ -626,10 +503,6 @@ export const ConversationAtMention = (): JSX.Element =>
},
});
-ConversationAtMention.story = {
- name: 'Conversation: At Mention',
-};
-
export function Headers(): JSX.Element {
return (
);
}
-
-KitchenSink.story = {
- name: 'Kitchen sink',
-};
diff --git a/ts/components/CrashReportDialog.stories.tsx b/ts/components/CrashReportDialog.stories.tsx
index 3c5c942b3d31..dc45a2dde1e0 100644
--- a/ts/components/CrashReportDialog.stories.tsx
+++ b/ts/components/CrashReportDialog.stories.tsx
@@ -4,6 +4,8 @@
import React, { useState } from 'react';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
+import type { PropsType } from './CrashReportDialog';
import { CrashReportDialog } from './CrashReportDialog';
import { setupI18n } from '../util/setupI18n';
import { sleep } from '../util/sleep';
@@ -11,11 +13,11 @@ import enMessages from '../../_locales/en/messages.json';
export default {
title: 'Components/CrashReportDialog',
-};
+} satisfies Meta;
const i18n = setupI18n('en', enMessages);
-export const _CrashReportDialog = (): JSX.Element => {
+export function Basic(): JSX.Element {
const [isPending, setIsPending] = useState(false);
return (
@@ -31,8 +33,4 @@ export const _CrashReportDialog = (): JSX.Element => {
eraseCrashReports={action('eraseCrashReports')}
/>
);
-};
-
-_CrashReportDialog.story = {
- name: 'CrashReportDialog',
-};
+}
diff --git a/ts/components/CrashReportDialog.tsx b/ts/components/CrashReportDialog.tsx
index 28e73d56e2e3..4f20b62c3c40 100644
--- a/ts/components/CrashReportDialog.tsx
+++ b/ts/components/CrashReportDialog.tsx
@@ -13,7 +13,7 @@ type PropsActionsType = {
eraseCrashReports: () => void;
};
-type PropsType = {
+export type PropsType = {
i18n: LocalizerType;
isPending: boolean;
} & PropsActionsType;
diff --git a/ts/components/CustomColorEditor.stories.tsx b/ts/components/CustomColorEditor.stories.tsx
index 173e7cc454d6..91beaaee45ca 100644
--- a/ts/components/CustomColorEditor.stories.tsx
+++ b/ts/components/CustomColorEditor.stories.tsx
@@ -5,6 +5,7 @@ import React from 'react';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
import enMessages from '../../_locales/en/messages.json';
import type { PropsType } from './CustomColorEditor';
import { CustomColorEditor } from './CustomColorEditor';
@@ -12,7 +13,7 @@ import { setupI18n } from '../util/setupI18n';
export default {
title: 'Components/CustomColorEditor',
-};
+} satisfies Meta;
const i18n = setupI18n('en', enMessages);
diff --git a/ts/components/CustomizingPreferredReactionsModal.stories.tsx b/ts/components/CustomizingPreferredReactionsModal.stories.tsx
index 62a69bc67771..443b430bd14b 100644
--- a/ts/components/CustomizingPreferredReactionsModal.stories.tsx
+++ b/ts/components/CustomizingPreferredReactionsModal.stories.tsx
@@ -5,16 +5,18 @@ import type { ComponentProps } from 'react';
import React from 'react';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
import { setupI18n } from '../util/setupI18n';
import enMessages from '../../_locales/en/messages.json';
+import type { PropsType } from './CustomizingPreferredReactionsModal';
import { CustomizingPreferredReactionsModal } from './CustomizingPreferredReactionsModal';
const i18n = setupI18n('en', enMessages);
export default {
title: 'Components/CustomizingPreferredReactionsModal',
-};
+} satisfies Meta;
const defaultProps: ComponentProps =
{
@@ -50,10 +52,6 @@ export function DraftEmojiSelected(): JSX.Element {
);
}
-DraftEmojiSelected.story = {
- name: 'Draft emoji selected',
-};
-
export function Saving(): JSX.Element {
return ;
}
@@ -61,7 +59,3 @@ export function Saving(): JSX.Element {
export function HadError(): JSX.Element {
return ;
}
-
-HadError.story = {
- name: 'Had error',
-};
diff --git a/ts/components/CustomizingPreferredReactionsModal.tsx b/ts/components/CustomizingPreferredReactionsModal.tsx
index ae50f9511b46..073cc06ac61a 100644
--- a/ts/components/CustomizingPreferredReactionsModal.tsx
+++ b/ts/components/CustomizingPreferredReactionsModal.tsx
@@ -19,7 +19,7 @@ import { convertShortName } from './emoji/lib';
import { offsetDistanceModifier } from '../util/popperUtil';
import { handleOutsideClick } from '../util/handleOutsideClick';
-type PropsType = {
+export type PropsType = {
draftPreferredReactions: ReadonlyArray;
hadSaveError: boolean;
i18n: LocalizerType;
diff --git a/ts/components/DebugLogWindow.stories.tsx b/ts/components/DebugLogWindow.stories.tsx
index 7118a5bbe81c..2e226a0db0ea 100644
--- a/ts/components/DebugLogWindow.stories.tsx
+++ b/ts/components/DebugLogWindow.stories.tsx
@@ -4,6 +4,7 @@
import React from 'react';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
import enMessages from '../../_locales/en/messages.json';
import type { PropsType } from './DebugLogWindow';
import { DebugLogWindow } from './DebugLogWindow';
@@ -31,12 +32,8 @@ const createProps = (): PropsType => ({
export default {
title: 'Components/DebugLogWindow',
-};
+} satisfies Meta;
-export const _DebugLogWindow = (): JSX.Element => (
-
-);
-
-_DebugLogWindow.story = {
- name: 'DebugLogWindow',
-};
+export function Basic(): JSX.Element {
+ return ;
+}
diff --git a/ts/components/DialogExpiredBuild.stories.tsx b/ts/components/DialogExpiredBuild.stories.tsx
index 11df133f0a31..2d8b732e6333 100644
--- a/ts/components/DialogExpiredBuild.stories.tsx
+++ b/ts/components/DialogExpiredBuild.stories.tsx
@@ -2,8 +2,8 @@
// SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react';
-import { select } from '@storybook/addon-knobs';
-
+import type { Meta } from '@storybook/react';
+import type { PropsType } from './DialogExpiredBuild';
import { DialogExpiredBuild } from './DialogExpiredBuild';
import { setupI18n } from '../util/setupI18n';
import enMessages from '../../_locales/en/messages.json';
@@ -14,14 +14,12 @@ const i18n = setupI18n('en', enMessages);
export default {
title: 'Components/DialogExpiredBuild',
-};
+ argTypes: {},
+ args: {},
+} satisfies Meta;
-export const _DialogExpiredBuild = (): JSX.Element => {
- const containerWidthBreakpoint = select(
- 'containerWidthBreakpoint',
- WidthBreakpoint,
- WidthBreakpoint.Wide
- );
+export function Basic(): JSX.Element {
+ const containerWidthBreakpoint = WidthBreakpoint.Wide;
return (
@@ -31,8 +29,4 @@ export const _DialogExpiredBuild = (): JSX.Element => {
/>
);
-};
-
-_DialogExpiredBuild.story = {
- name: 'DialogExpiredBuild',
-};
+}
diff --git a/ts/components/DialogNetworkStatus.stories.tsx b/ts/components/DialogNetworkStatus.stories.tsx
index 9bcf717e1ac0..cfbec3cc14cb 100644
--- a/ts/components/DialogNetworkStatus.stories.tsx
+++ b/ts/components/DialogNetworkStatus.stories.tsx
@@ -4,6 +4,7 @@
import * as React from 'react';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
import type { PropsType } from './DialogNetworkStatus';
import { DialogNetworkStatus } from './DialogNetworkStatus';
import { SocketStatus } from '../types/SocketStatus';
@@ -27,7 +28,7 @@ const defaultProps = {
export default {
title: 'Components/DialogNetworkStatus',
-};
+} satisfies Meta;
export function KnobsPlayground(args: PropsType): JSX.Element {
/*
@@ -68,10 +69,6 @@ export function ConnectingWide(): JSX.Element {
);
}
-ConnectingWide.story = {
- name: 'Connecting Wide',
-};
-
export function ClosingWide(): JSX.Element {
return (
@@ -84,10 +81,6 @@ export function ClosingWide(): JSX.Element {
);
}
-ClosingWide.story = {
- name: 'Closing Wide',
-};
-
export function ClosedWide(): JSX.Element {
return (
@@ -100,10 +93,6 @@ export function ClosedWide(): JSX.Element {
);
}
-ClosedWide.story = {
- name: 'Closed Wide',
-};
-
export function OfflineWide(): JSX.Element {
return (
@@ -116,10 +105,6 @@ export function OfflineWide(): JSX.Element {
);
}
-OfflineWide.story = {
- name: 'Offline Wide',
-};
-
export function ConnectingNarrow(): JSX.Element {
return (
@@ -132,10 +117,6 @@ export function ConnectingNarrow(): JSX.Element {
);
}
-ConnectingNarrow.story = {
- name: 'Connecting Narrow',
-};
-
export function ClosingNarrow(): JSX.Element {
return (
@@ -148,10 +129,6 @@ export function ClosingNarrow(): JSX.Element {
);
}
-ClosingNarrow.story = {
- name: 'Closing Narrow',
-};
-
export function ClosedNarrow(): JSX.Element {
return (
@@ -164,10 +141,6 @@ export function ClosedNarrow(): JSX.Element {
);
}
-ClosedNarrow.story = {
- name: 'Closed Narrow',
-};
-
export function OfflineNarrow(): JSX.Element {
return (
@@ -179,7 +152,3 @@ export function OfflineNarrow(): JSX.Element {
);
}
-
-OfflineNarrow.story = {
- name: 'Offline Narrow',
-};
diff --git a/ts/components/DialogRelink.stories.tsx b/ts/components/DialogRelink.stories.tsx
index 813da6e4561c..01ab3e7fcbcd 100644
--- a/ts/components/DialogRelink.stories.tsx
+++ b/ts/components/DialogRelink.stories.tsx
@@ -3,7 +3,8 @@
import * as React from 'react';
import { action } from '@storybook/addon-actions';
-
+import type { Meta } from '@storybook/react';
+import type { PropsType } from './DialogRelink';
import { DialogRelink } from './DialogRelink';
import { setupI18n } from '../util/setupI18n';
import enMessages from '../../_locales/en/messages.json';
@@ -35,7 +36,7 @@ const permutations = [
export default {
title: 'Components/DialogRelink',
-};
+} satisfies Meta;
export function Iterations(): JSX.Element {
return (
diff --git a/ts/components/DialogUpdate.stories.tsx b/ts/components/DialogUpdate.stories.tsx
index 4e202cd5f9b3..097206d81259 100644
--- a/ts/components/DialogUpdate.stories.tsx
+++ b/ts/components/DialogUpdate.stories.tsx
@@ -2,8 +2,9 @@
// SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react';
-import { select } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
+import type { PropsType } from './DialogUpdate';
import { DialogUpdate } from './DialogUpdate';
import { DialogType } from '../types/Dialogs';
import { WidthBreakpoint } from './_util';
@@ -29,15 +30,13 @@ const defaultProps = {
export default {
title: 'Components/DialogUpdate',
-};
+ argTypes: {},
+ args: {},
+} satisfies Meta;
export function KnobsPlayground(): JSX.Element {
- const containerWidthBreakpoint = select(
- 'containerWidthBreakpoint',
- WidthBreakpoint,
- WidthBreakpoint.Wide
- );
- const dialogType = select('dialogType', DialogType, DialogType.AutoUpdate);
+ const containerWidthBreakpoint = WidthBreakpoint.Wide;
+ const dialogType = DialogType.AutoUpdate;
return (
@@ -64,10 +63,6 @@ export function UpdateWide(): JSX.Element {
);
}
-UpdateWide.story = {
- name: 'Update (Wide)',
-};
-
export function DownloadedWide(): JSX.Element {
return (
@@ -81,10 +76,6 @@ export function DownloadedWide(): JSX.Element {
);
}
-DownloadedWide.story = {
- name: 'Downloaded (Wide)',
-};
-
export function DownloadReadyWide(): JSX.Element {
return (
@@ -99,10 +90,6 @@ export function DownloadReadyWide(): JSX.Element {
);
}
-DownloadReadyWide.story = {
- name: 'DownloadReady (Wide)',
-};
-
export function FullDownloadReadyWide(): JSX.Element {
return (
@@ -117,10 +104,6 @@ export function FullDownloadReadyWide(): JSX.Element {
);
}
-FullDownloadReadyWide.story = {
- name: 'FullDownloadReady (Wide)',
-};
-
export function DownloadingWide(): JSX.Element {
const [downloadedSize, setDownloadedSize] = React.useState(0);
@@ -153,10 +136,6 @@ export function DownloadingWide(): JSX.Element {
);
}
-DownloadingWide.story = {
- name: 'Downloading (Wide)',
-};
-
export function CannotUpdateWide(): JSX.Element {
return (
@@ -170,10 +149,6 @@ export function CannotUpdateWide(): JSX.Element {
);
}
-CannotUpdateWide.story = {
- name: 'Cannot_Update (Wide)',
-};
-
export function CannotUpdateBetaWide(): JSX.Element {
return (
@@ -187,10 +162,6 @@ export function CannotUpdateBetaWide(): JSX.Element {
);
}
-CannotUpdateBetaWide.story = {
- name: 'Cannot_Update_Beta (Wide)',
-};
-
export function CannotUpdateRequireManualWide(): JSX.Element {
return (
@@ -204,10 +175,6 @@ export function CannotUpdateRequireManualWide(): JSX.Element {
);
}
-CannotUpdateRequireManualWide.story = {
- name: 'Cannot_Update_Require_Manual (Wide)',
-};
-
export function CannotUpdateRequireManualBetaWide(): JSX.Element {
return (
@@ -221,10 +188,6 @@ export function CannotUpdateRequireManualBetaWide(): JSX.Element {
);
}
-CannotUpdateRequireManualBetaWide.story = {
- name: 'Cannot_Update_Require_Manual_Beta (Wide)',
-};
-
export function MacOSReadOnlyWide(): JSX.Element {
return (
@@ -238,10 +201,6 @@ export function MacOSReadOnlyWide(): JSX.Element {
);
}
-MacOSReadOnlyWide.story = {
- name: 'MacOS_Read_Only (Wide)',
-};
-
export function UnsupportedOSWide(): JSX.Element {
return (
@@ -255,10 +214,6 @@ export function UnsupportedOSWide(): JSX.Element {
);
}
-UnsupportedOSWide.story = {
- name: 'UnsupportedOS (Wide)',
-};
-
export function UpdateNarrow(): JSX.Element {
return (
@@ -272,10 +227,6 @@ export function UpdateNarrow(): JSX.Element {
);
}
-UpdateNarrow.story = {
- name: 'Update (Narrow)',
-};
-
export function DownloadedNarrow(): JSX.Element {
return (
@@ -289,10 +240,6 @@ export function DownloadedNarrow(): JSX.Element {
);
}
-DownloadedNarrow.story = {
- name: 'Downloaded (Narrow)',
-};
-
export function DownloadReadyNarrow(): JSX.Element {
return (
@@ -307,10 +254,6 @@ export function DownloadReadyNarrow(): JSX.Element {
);
}
-DownloadReadyNarrow.story = {
- name: 'DownloadReady (Narrow)',
-};
-
export function FullDownloadReadyNarrow(): JSX.Element {
return (
@@ -325,10 +268,6 @@ export function FullDownloadReadyNarrow(): JSX.Element {
);
}
-FullDownloadReadyNarrow.story = {
- name: 'FullDownloadReady (Narrow)',
-};
-
export function DownloadingNarrow(): JSX.Element {
return (
@@ -342,10 +281,6 @@ export function DownloadingNarrow(): JSX.Element {
);
}
-DownloadingNarrow.story = {
- name: 'Downloading (Narrow)',
-};
-
export function CannotUpdateNarrow(): JSX.Element {
return (
@@ -359,10 +294,6 @@ export function CannotUpdateNarrow(): JSX.Element {
);
}
-CannotUpdateNarrow.story = {
- name: 'Cannot Update (Narrow)',
-};
-
export function CannotUpdateBetaNarrow(): JSX.Element {
return (
@@ -376,10 +307,6 @@ export function CannotUpdateBetaNarrow(): JSX.Element {
);
}
-CannotUpdateBetaNarrow.story = {
- name: 'Cannot Update Beta (Narrow)',
-};
-
export function CannotUpdateRequireManualNarrow(): JSX.Element {
return (
@@ -393,10 +320,6 @@ export function CannotUpdateRequireManualNarrow(): JSX.Element {
);
}
-CannotUpdateRequireManualNarrow.story = {
- name: 'Cannot_Update_Require_Manual (Narrow)',
-};
-
export function CannotUpdateRequireManualBetaNarrow(): JSX.Element {
return (
@@ -410,10 +333,6 @@ export function CannotUpdateRequireManualBetaNarrow(): JSX.Element {
);
}
-CannotUpdateRequireManualBetaNarrow.story = {
- name: 'Cannot_Update_Require_Manual_Beta (Narrow)',
-};
-
export function MacOSReadOnlyNarrow(): JSX.Element {
return (
@@ -427,10 +346,6 @@ export function MacOSReadOnlyNarrow(): JSX.Element {
);
}
-MacOSReadOnlyNarrow.story = {
- name: 'MacOS_Read_Only (Narrow)',
-};
-
export function UnsupportedOSNarrow(): JSX.Element {
return (
@@ -443,7 +358,3 @@ export function UnsupportedOSNarrow(): JSX.Element {
);
}
-
-UnsupportedOSNarrow.story = {
- name: 'UnsupportedOS (Narrow)',
-};
diff --git a/ts/components/DisappearingTimeDialog.stories.tsx b/ts/components/DisappearingTimeDialog.stories.tsx
index 3ed55aa89adf..69a99e115716 100644
--- a/ts/components/DisappearingTimeDialog.stories.tsx
+++ b/ts/components/DisappearingTimeDialog.stories.tsx
@@ -3,7 +3,8 @@
import React from 'react';
import { action } from '@storybook/addon-actions';
-
+import type { Meta } from '@storybook/react';
+import type { PropsType } from './DisappearingTimeDialog';
import { DisappearingTimeDialog } from './DisappearingTimeDialog';
import { setupI18n } from '../util/setupI18n';
import enMessages from '../../_locales/en/messages.json';
@@ -12,7 +13,7 @@ import { EXPIRE_TIMERS } from '../test-both/util/expireTimers';
export default {
title: 'Components/DisappearingTimeDialog',
-};
+} satisfies Meta;
const i18n = setupI18n('en', enMessages);
diff --git a/ts/components/DisappearingTimerSelect.stories.tsx b/ts/components/DisappearingTimerSelect.stories.tsx
index 11d8973f0cd4..460abf1d6f03 100644
--- a/ts/components/DisappearingTimerSelect.stories.tsx
+++ b/ts/components/DisappearingTimerSelect.stories.tsx
@@ -2,7 +2,8 @@
// SPDX-License-Identifier: AGPL-3.0-only
import React, { useState } from 'react';
-
+import type { Meta } from '@storybook/react';
+import type { Props } from './DisappearingTimerSelect';
import { DisappearingTimerSelect } from './DisappearingTimerSelect';
import { setupI18n } from '../util/setupI18n';
import { DurationInSeconds } from '../util/durations';
@@ -10,15 +11,15 @@ import enMessages from '../../_locales/en/messages.json';
export default {
title: 'Components/DisappearingTimerSelect',
-};
+} satisfies Meta;
const i18n = setupI18n('en', enMessages);
-type Props = {
+type Args = {
initialValue: number;
};
-function TimerSelectWrap({ initialValue }: Props): JSX.Element {
+function TimerSelectWrap({ initialValue }: Args): JSX.Element {
const [value, setValue] = useState(initialValue);
return (
@@ -34,14 +35,6 @@ export function InitialValue1Day(): JSX.Element {
return ;
}
-InitialValue1Day.story = {
- name: 'Initial value: 1 day',
-};
-
export function InitialValue3DaysCustomTime(): JSX.Element {
return ;
}
-
-InitialValue3DaysCustomTime.story = {
- name: 'Initial value 3 days (Custom time)',
-};
diff --git a/ts/components/EditUsernameModalBody.stories.tsx b/ts/components/EditUsernameModalBody.stories.tsx
index 1e9fed1539a9..92a9db4885b6 100644
--- a/ts/components/EditUsernameModalBody.stories.tsx
+++ b/ts/components/EditUsernameModalBody.stories.tsx
@@ -2,8 +2,9 @@
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
-import type { Meta, Story } from '@storybook/react';
+import type { Meta, StoryFn } from '@storybook/react';
+import { action } from '@storybook/addon-actions';
import enMessages from '../../_locales/en/messages.json';
import { setupI18n } from '../util/setupI18n';
import type { UsernameReservationType } from '../types/Username';
@@ -29,11 +30,9 @@ export default {
argTypes: {
currentUsername: {
type: { name: 'string', required: false },
- defaultValue: undefined,
},
state: {
control: { type: 'radio' },
- defaultValue: State.Open,
options: {
Open: State.Open,
Closed: State.Closed,
@@ -43,7 +42,6 @@ export default {
},
error: {
control: { type: 'radio' },
- defaultValue: undefined,
options: {
None: undefined,
NotEnoughCharacters: UsernameReservationError.NotEnoughCharacters,
@@ -54,26 +52,24 @@ export default {
General: UsernameReservationError.General,
},
},
- maxUsername: {
- defaultValue: 20,
- },
- minUsername: {
- defaultValue: 3,
- },
- discriminator: {
+ reservation: {
type: { name: 'string', required: false },
- defaultValue: undefined,
},
- i18n: {
- defaultValue: i18n,
- },
- onClose: { action: true },
- onError: { action: true },
- setUsernameReservationError: { action: true },
- reserveUsername: { action: true },
- confirmUsername: { action: true },
},
-} as Meta;
+ args: {
+ currentUsername: undefined,
+ state: State.Open,
+ error: undefined,
+ maxNickname: 20,
+ minNickname: 3,
+ reservation: undefined,
+ i18n,
+ onClose: action('onClose'),
+ setUsernameReservationError: action('setUsernameReservationError'),
+ reserveUsername: action('reserveUsername'),
+ confirmUsername: action('confirmUsername'),
+ },
+} satisfies Meta;
type ArgsType = PropsType & {
discriminator?: string;
@@ -81,7 +77,7 @@ type ArgsType = PropsType & {
};
// eslint-disable-next-line react/function-component-definition
-const Template: Story = args => {
+const Template: StoryFn = args => {
let { reservation } = args;
if (!reservation && args.discriminator) {
reservation = {
@@ -95,27 +91,16 @@ const Template: Story = args => {
export const WithoutUsername = Template.bind({});
WithoutUsername.args = {};
-WithoutUsername.story = {
- name: 'without current username',
-};
export const WithUsername = Template.bind({});
-WithUsername.args = {};
-WithUsername.story = {
- name: 'with current username',
- args: {
- currentUsername: 'signaluser.12',
- },
+WithUsername.args = {
+ currentUsername: 'signaluser.12',
};
export const WithReservation = Template.bind({});
-WithReservation.args = {};
-WithReservation.story = {
- name: 'with reservation',
- args: {
- currentUsername: 'reserved',
- reservation: DEFAULT_RESERVATION,
- },
+WithReservation.args = {
+ currentUsername: 'reserved',
+ reservation: DEFAULT_RESERVATION,
};
export const UsernameEditingConfirming = Template.bind({});
@@ -123,9 +108,6 @@ UsernameEditingConfirming.args = {
state: State.Confirming,
currentUsername: 'signaluser.12',
};
-UsernameEditingConfirming.story = {
- name: 'Username editing, Confirming',
-};
export const UsernameEditingUsernameTaken = Template.bind({});
UsernameEditingUsernameTaken.args = {
@@ -133,9 +115,6 @@ UsernameEditingUsernameTaken.args = {
error: UsernameReservationError.UsernameNotAvailable,
currentUsername: 'signaluser.12',
};
-UsernameEditingUsernameTaken.story = {
- name: 'Username editing, username taken',
-};
export const UsernameEditingUsernameWrongCharacters = Template.bind({});
UsernameEditingUsernameWrongCharacters.args = {
@@ -143,9 +122,6 @@ UsernameEditingUsernameWrongCharacters.args = {
error: UsernameReservationError.CheckCharacters,
currentUsername: 'signaluser.12',
};
-UsernameEditingUsernameWrongCharacters.story = {
- name: 'Username editing, Wrong Characters',
-};
export const UsernameEditingUsernameTooShort = Template.bind({});
UsernameEditingUsernameTooShort.args = {
@@ -153,9 +129,6 @@ UsernameEditingUsernameTooShort.args = {
error: UsernameReservationError.NotEnoughCharacters,
currentUsername: 'sig',
};
-UsernameEditingUsernameTooShort.story = {
- name: 'Username editing, username too short',
-};
export const UsernameEditingGeneralError = Template.bind({});
UsernameEditingGeneralError.args = {
@@ -163,6 +136,3 @@ UsernameEditingGeneralError.args = {
error: UsernameReservationError.General,
currentUsername: 'signaluser.12',
};
-UsernameEditingGeneralError.story = {
- name: 'Username editing, general error',
-};
diff --git a/ts/components/ErrorModal.stories.tsx b/ts/components/ErrorModal.stories.tsx
index 51a3d40b7a95..20775c3187c4 100644
--- a/ts/components/ErrorModal.stories.tsx
+++ b/ts/components/ErrorModal.stories.tsx
@@ -2,9 +2,9 @@
// SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react';
-import { text } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
import type { PropsType } from './ErrorModal';
import { ErrorModal } from './ErrorModal';
@@ -14,15 +14,17 @@ import enMessages from '../../_locales/en/messages.json';
const i18n = setupI18n('en', enMessages);
const createProps = (overrideProps: Partial = {}): PropsType => ({
- title: text('title', overrideProps.title || ''),
- description: text('description', overrideProps.description || ''),
+ title: overrideProps.title ?? '',
+ description: overrideProps.description ?? '',
i18n,
onClose: action('onClick'),
});
export default {
title: 'Components/ErrorModal',
-};
+ argTypes: {},
+ args: {},
+} satisfies Meta;
export function Normal(): JSX.Element {
return ;
diff --git a/ts/components/ForwardMessagesModal.stories.tsx b/ts/components/ForwardMessagesModal.stories.tsx
index 0cf043ed2d52..a078f4a4ae47 100644
--- a/ts/components/ForwardMessagesModal.stories.tsx
+++ b/ts/components/ForwardMessagesModal.stories.tsx
@@ -2,10 +2,8 @@
// SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react';
-
import { action } from '@storybook/addon-actions';
-import { text } from '@storybook/addon-knobs';
-
+import type { Meta } from '@storybook/react';
import enMessages from '../../_locales/en/messages.json';
import type { AttachmentType } from '../types/Attachment';
import type { PropsType } from './ForwardMessagesModal';
@@ -15,25 +13,25 @@ import { getDefaultConversation } from '../test-both/helpers/getDefaultConversat
import { setupI18n } from '../util/setupI18n';
import { StorybookThemeContext } from '../../.storybook/StorybookThemeContext';
import { CompositionTextArea } from './CompositionTextArea';
-import type { MessageForwardDraft } from '../util/maybeForwardMessages';
+import type { MessageForwardDraft } from '../types/ForwardDraft';
const createAttachment = (
props: Partial = {}
): AttachmentType => ({
pending: false,
path: 'fileName.jpg',
- contentType: stringToMIMEType(
- text('attachment contentType', props.contentType || '')
- ),
- fileName: text('attachment fileName', props.fileName || ''),
+ contentType: stringToMIMEType(props.contentType ?? ''),
+ fileName: props.fileName ?? '',
screenshotPath: props.pending === false ? props.screenshotPath : undefined,
- url: text('attachment url', props.pending === false ? props.url || '' : ''),
+ url: props.pending === false ? props.url ?? '' : '',
size: 3433,
});
export default {
title: 'Components/ForwardMessageModal',
-};
+ argTypes: {},
+ args: {},
+} satisfies Meta;
const i18n = setupI18n('en', enMessages);
@@ -82,7 +80,7 @@ function getMessageForwardDraft(
attachments: overrideProps.attachments,
hasContact: Boolean(overrideProps.hasContact),
isSticker: Boolean(overrideProps.isSticker),
- messageBody: text('messageBody', overrideProps.messageBody || ''),
+ messageBody: overrideProps.messageBody ?? '',
originalMessageId: '123',
previews: overrideProps.previews ?? [],
};
@@ -102,10 +100,6 @@ export function WithText(): JSX.Element {
);
}
-WithText.story = {
- name: 'with text',
-};
-
export function ASticker(): JSX.Element {
return (
);
}
-
-AnnouncementOnlyGroupsNonAdmin.story = {
- name: 'announcement only groups non-admin',
-};
diff --git a/ts/components/ForwardMessagesModal.tsx b/ts/components/ForwardMessagesModal.tsx
index 2675014b56c2..7ea463566fb7 100644
--- a/ts/components/ForwardMessagesModal.tsx
+++ b/ts/components/ForwardMessagesModal.tsx
@@ -27,11 +27,6 @@ import {
shouldNeverBeCalled,
asyncShouldNeverBeCalled,
} from '../util/shouldNeverBeCalled';
-import type { MessageForwardDraft } from '../util/maybeForwardMessages';
-import {
- isDraftEditable,
- isDraftForwardable,
-} from '../util/maybeForwardMessages';
import type { LinkPreviewType } from '../types/message/LinkPreviews';
import { LinkPreviewSourceType } from '../types/LinkPreview';
import { ToastType } from '../types/Toast';
@@ -41,6 +36,11 @@ import { BodyRange } from '../types/BodyRange';
import { UserText } from './UserText';
import { Modal } from './Modal';
import { SizeObserver } from '../hooks/useSizeObserver';
+import {
+ isDraftEditable,
+ isDraftForwardable,
+ type MessageForwardDraft,
+} from '../types/ForwardDraft';
export type DataPropsType = {
candidateConversations: ReadonlyArray;
diff --git a/ts/components/GroupCallOverflowArea.stories.tsx b/ts/components/GroupCallOverflowArea.stories.tsx
index 1bd1272cd5db..17cf8eb16fd6 100644
--- a/ts/components/GroupCallOverflowArea.stories.tsx
+++ b/ts/components/GroupCallOverflowArea.stories.tsx
@@ -3,9 +3,9 @@
import React from 'react';
import { memoize, times } from 'lodash';
-import { number } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions';
-
+import type { Meta } from '@storybook/react';
+import type { PropsType } from './GroupCallOverflowArea';
import { GroupCallOverflowArea } from './GroupCallOverflowArea';
import { setupI18n } from '../util/setupI18n';
import { getDefaultConversationWithServiceId } from '../test-both/helpers/getDefaultConversation';
@@ -34,7 +34,9 @@ const allRemoteParticipants = times(MAX_PARTICIPANTS).map(index => ({
export default {
title: 'Components/GroupCallOverflowArea',
-};
+ argTypes: {},
+ args: {},
+} satisfies Meta;
const defaultProps = {
getFrameBuffer: memoize(() => Buffer.alloc(FRAME_BUFFER_SIZE)),
@@ -68,10 +70,6 @@ export function NoOverflowedParticipants(): JSX.Element {
);
}
-NoOverflowedParticipants.story = {
- name: 'No overflowed participants',
-};
-
export function OneOverflowedParticipant(): JSX.Element {
return (
@@ -83,10 +81,6 @@ export function OneOverflowedParticipant(): JSX.Element {
);
}
-OneOverflowedParticipant.story = {
- name: 'One overflowed participant',
-};
-
export function ThreeOverflowedParticipants(): JSX.Element {
return (
@@ -98,10 +92,6 @@ export function ThreeOverflowedParticipants(): JSX.Element {
);
}
-ThreeOverflowedParticipants.story = {
- name: 'Three overflowed participants',
-};
-
export function ManyOverflowedParticipants(): JSX.Element {
return (
@@ -109,18 +99,9 @@ export function ManyOverflowedParticipants(): JSX.Element {
{...defaultProps}
overflowedParticipants={allRemoteParticipants.slice(
0,
- number('Participant count', MAX_PARTICIPANTS, {
- range: true,
- min: 0,
- max: MAX_PARTICIPANTS,
- step: 1,
- })
+ MAX_PARTICIPANTS
)}
/>
);
}
-
-ManyOverflowedParticipants.story = {
- name: 'Many overflowed participants',
-};
diff --git a/ts/components/GroupCallOverflowArea.tsx b/ts/components/GroupCallOverflowArea.tsx
index b60a135e0be0..76edcebe6710 100644
--- a/ts/components/GroupCallOverflowArea.tsx
+++ b/ts/components/GroupCallOverflowArea.tsx
@@ -15,7 +15,7 @@ const OVERFLOW_SCROLL_BUTTON_RATIO = 0.75;
// This should be an integer, as sub-pixel widths can cause performance issues.
export const OVERFLOW_PARTICIPANT_WIDTH = 140;
-type PropsType = {
+export type PropsType = {
getFrameBuffer: () => Buffer;
getGroupCallVideoFrameSource: (demuxId: number) => VideoFrameSource;
i18n: LocalizerType;
diff --git a/ts/components/GroupCallRemoteParticipant.stories.tsx b/ts/components/GroupCallRemoteParticipant.stories.tsx
index 5d7cc94ef726..3eb13477a897 100644
--- a/ts/components/GroupCallRemoteParticipant.stories.tsx
+++ b/ts/components/GroupCallRemoteParticipant.stories.tsx
@@ -2,9 +2,8 @@
// SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react';
-import { memoize, noop } from 'lodash';
-import { select } from '@storybook/addon-knobs';
-
+import { memoize } from 'lodash';
+import type { Meta } from '@storybook/react';
import type { PropsType } from './GroupCallRemoteParticipant';
import { GroupCallRemoteParticipant } from './GroupCallRemoteParticipant';
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
@@ -46,8 +45,9 @@ const createProps = (
} = {}
): PropsType => ({
getFrameBuffer,
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- getGroupCallVideoFrameSource: noop as any,
+ getGroupCallVideoFrameSource: () => {
+ return { receiveVideoFrame: () => undefined };
+ },
i18n,
audioLevel: 0,
remoteParticipant: {
@@ -72,7 +72,9 @@ const createProps = (
export default {
title: 'Components/GroupCallRemoteParticipant',
-};
+ argTypes: {},
+ args: {},
+} satisfies Meta;
export function Default(): JSX.Element {
return (
@@ -101,7 +103,7 @@ export function Speaking(): JSX.Element {
left: (120 + 10) * index,
top: 0,
width: 120,
- audioLevel: select('audioLevel', [0, 0.5, 1], 0.5),
+ audioLevel: 0.5,
remoteParticipantsCount,
},
{ hasRemoteAudio: true, presenting }
@@ -126,10 +128,6 @@ export function IsInPip(): JSX.Element {
);
}
-IsInPip.story = {
- name: 'isInPip',
-};
-
export function Blocked(): JSX.Element {
return (
;
function Wrapper({
disabled,
diff --git a/ts/components/GroupDescriptionInput.tsx b/ts/components/GroupDescriptionInput.tsx
index 0534a8d1013b..2a470d819c49 100644
--- a/ts/components/GroupDescriptionInput.tsx
+++ b/ts/components/GroupDescriptionInput.tsx
@@ -6,7 +6,7 @@ import React, { forwardRef } from 'react';
import { Input } from './Input';
import type { LocalizerType } from '../types/Util';
-type PropsType = {
+export type PropsType = {
disabled?: boolean;
i18n: LocalizerType;
onChangeValue: (value: string) => void;
diff --git a/ts/components/GroupTitleInput.stories.tsx b/ts/components/GroupTitleInput.stories.tsx
index af128f35064b..d873de91de5b 100644
--- a/ts/components/GroupTitleInput.stories.tsx
+++ b/ts/components/GroupTitleInput.stories.tsx
@@ -2,17 +2,17 @@
// SPDX-License-Identifier: AGPL-3.0-only
import React, { useState } from 'react';
-
+import type { Meta } from '@storybook/react';
import { setupI18n } from '../util/setupI18n';
import enMessages from '../../_locales/en/messages.json';
-
+import type { PropsType } from './GroupTitleInput';
import { GroupTitleInput } from './GroupTitleInput';
const i18n = setupI18n('en', enMessages);
export default {
title: 'Components/GroupTitleInput',
-};
+} satisfies Meta;
function Wrapper({
disabled,
diff --git a/ts/components/GroupTitleInput.tsx b/ts/components/GroupTitleInput.tsx
index 23def66a206d..ebd75e6c68f0 100644
--- a/ts/components/GroupTitleInput.tsx
+++ b/ts/components/GroupTitleInput.tsx
@@ -6,7 +6,7 @@ import React, { forwardRef } from 'react';
import { Input } from './Input';
import type { LocalizerType } from '../types/Util';
-type PropsType = {
+export type PropsType = {
disabled?: boolean;
i18n: LocalizerType;
onChangeValue: (value: string) => void;
diff --git a/ts/components/GroupV1MigrationDialog.stories.tsx b/ts/components/GroupV1MigrationDialog.stories.tsx
index e86725e4e11d..a6464eb5d97d 100644
--- a/ts/components/GroupV1MigrationDialog.stories.tsx
+++ b/ts/components/GroupV1MigrationDialog.stories.tsx
@@ -5,6 +5,7 @@ import * as React from 'react';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
import type { PropsType } from './GroupV1MigrationDialog';
import { GroupV1MigrationDialog } from './GroupV1MigrationDialog';
import type { ConversationType } from '../state/ducks/conversations';
@@ -48,16 +49,12 @@ const createProps = (overrideProps: Partial = {}): PropsType => ({
export default {
title: 'Components/GroupV1MigrationDialog',
-};
+} satisfies Meta;
export function NotYetMigratedBasic(): JSX.Element {
return ;
}
-NotYetMigratedBasic.story = {
- name: 'Not yet migrated, basic',
-};
-
export function MigratedBasic(): JSX.Element {
return (
);
}
-
-NotYetMigratedJustDroppedMember.story = {
- name: 'Not yet migrated, just dropped member',
-};
diff --git a/ts/components/GroupV2JoinDialog.stories.tsx b/ts/components/GroupV2JoinDialog.stories.tsx
index ab0515616606..6a348fad4f0e 100644
--- a/ts/components/GroupV2JoinDialog.stories.tsx
+++ b/ts/components/GroupV2JoinDialog.stories.tsx
@@ -2,9 +2,8 @@
// SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react';
-import { boolean, number, text } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions';
-
+import type { Meta } from '@storybook/react';
import type { PropsType } from './GroupV2JoinDialog';
import { GroupV2JoinDialog } from './GroupV2JoinDialog';
import { setupI18n } from '../util/setupI18n';
@@ -13,13 +12,10 @@ import enMessages from '../../_locales/en/messages.json';
const i18n = setupI18n('en', enMessages);
const createProps = (overrideProps: Partial = {}): PropsType => ({
- memberCount: number('memberCount', overrideProps.memberCount || 12),
+ memberCount: overrideProps.memberCount ?? 12,
avatar: overrideProps.avatar,
- title: text('title', overrideProps.title || 'Random Group!'),
- approvalRequired: boolean(
- 'approvalRequired',
- overrideProps.approvalRequired || false
- ),
+ title: overrideProps.title ?? 'Random Group!',
+ approvalRequired: overrideProps.approvalRequired ?? false,
groupDescription: overrideProps.groupDescription,
join: action('join'),
onClose: action('onClose'),
@@ -28,7 +24,9 @@ const createProps = (overrideProps: Partial = {}): PropsType => ({
export default {
title: 'Components/GroupV2JoinDialog',
-};
+ argTypes: {},
+ args: {},
+} satisfies Meta;
export function Basic(): JSX.Element {
return ;
@@ -45,10 +43,6 @@ export function ApprovalRequired(): JSX.Element {
);
}
-ApprovalRequired.story = {
- name: 'Approval required',
-};
-
export function WithAvatar(): JSX.Element {
return (
= [];
diff --git a/ts/components/InContactsIcon.stories.tsx b/ts/components/InContactsIcon.stories.tsx
index 5c5acb63234a..42db8da1b25f 100644
--- a/ts/components/InContactsIcon.stories.tsx
+++ b/ts/components/InContactsIcon.stories.tsx
@@ -2,16 +2,17 @@
// SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react';
-
+import type { Meta } from '@storybook/react';
import { setupI18n } from '../util/setupI18n';
import enMessages from '../../_locales/en/messages.json';
+import type { PropsType } from './InContactsIcon';
import { InContactsIcon } from './InContactsIcon';
const i18n = setupI18n('en', enMessages);
export default {
title: 'Components/InContactsIcon',
-};
+} satisfies Meta;
export function Default(): JSX.Element {
return ;
diff --git a/ts/components/InContactsIcon.tsx b/ts/components/InContactsIcon.tsx
index 9ee209a45ca2..e0cfe0d218c0 100644
--- a/ts/components/InContactsIcon.tsx
+++ b/ts/components/InContactsIcon.tsx
@@ -7,7 +7,7 @@ import classNames from 'classnames';
import { Tooltip } from './Tooltip';
import type { LocalizerType } from '../types/Util';
-type PropsType = {
+export type PropsType = {
className?: string;
tooltipContainerRef?: React.RefObject;
i18n: LocalizerType;
diff --git a/ts/components/Inbox.stories.tsx b/ts/components/Inbox.stories.tsx
index 213150438310..b2f93e4dfc79 100644
--- a/ts/components/Inbox.stories.tsx
+++ b/ts/components/Inbox.stories.tsx
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: AGPL-3.0-only
import React, { useState, useEffect, useMemo } from 'react';
-import type { Meta, Story } from '@storybook/react';
+import type { Meta, StoryFn } from '@storybook/react';
import { noop } from 'lodash';
import { Inbox } from './Inbox';
@@ -16,41 +16,15 @@ const i18n = setupI18n('en', enMessages);
export default {
title: 'Components/Inbox',
- argTypes: {
- i18n: {
- defaultValue: i18n,
- },
- hasInitialLoadCompleted: {
- defaultValue: false,
- },
- daysAgo: {
- control: 'select',
- defaultValue: undefined,
- options: [undefined, 1, 2, 3, 7, 14, 21],
- },
- isCustomizingPreferredReactions: {
- defaultValue: false,
- },
- onConversationClosed: {
- action: true,
- },
- onConversationOpened: {
- action: true,
- },
- scrollToMessage: {
- action: true,
- },
- showConversation: {
- action: true,
- },
- showWhatsNewModal: {
- action: true,
- },
+ args: {
+ i18n,
+ hasInitialLoadCompleted: false,
+ isCustomizingPreferredReactions: false,
},
-} as Meta;
+} satisfies Meta;
// eslint-disable-next-line react/function-component-definition
-const Template: Story = ({
+const Template: StoryFn = ({
daysAgo,
...args
}) => {
@@ -90,6 +64,3 @@ const Template: Story = ({
};
export const Default = Template.bind({});
-Default.story = {
- name: 'Default',
-};
diff --git a/ts/components/IncomingCallBar.stories.tsx b/ts/components/IncomingCallBar.stories.tsx
index 0228afebcaac..099e55c19c34 100644
--- a/ts/components/IncomingCallBar.stories.tsx
+++ b/ts/components/IncomingCallBar.stories.tsx
@@ -3,7 +3,8 @@
import * as React from 'react';
import { action } from '@storybook/addon-actions';
-
+import type { Meta } from '@storybook/react';
+import type { PropsType } from './IncomingCallBar';
import { IncomingCallBar } from './IncomingCallBar';
import { CallMode } from '../types/Calling';
import { setupI18n } from '../util/setupI18n';
@@ -53,7 +54,7 @@ const groupConversation = getDefaultConversation({
export default {
title: 'Components/IncomingCallBar',
-};
+} satisfies Meta;
export function IncomingDirectCallVideo(): JSX.Element {
return (
@@ -66,10 +67,6 @@ export function IncomingDirectCallVideo(): JSX.Element {
);
}
-IncomingDirectCallVideo.story = {
- name: 'Incoming direct call (video)',
-};
-
export function IncomingDirectCallAudio(): JSX.Element {
return (
);
}
-
-IncomingGroupCallCallingYouAnd4Others.story = {
- name: 'Incoming group call (calling you and 4 others)',
-};
diff --git a/ts/components/Input.stories.tsx b/ts/components/Input.stories.tsx
index 370358fa57c6..e6b580e9014e 100644
--- a/ts/components/Input.stories.tsx
+++ b/ts/components/Input.stories.tsx
@@ -2,10 +2,8 @@
// SPDX-License-Identifier: AGPL-3.0-only
import React, { useState } from 'react';
-
-import { text } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions';
-
+import type { Meta } from '@storybook/react';
import type { PropsType } from './Input';
import { Input } from './Input';
import { setupI18n } from '../util/setupI18n';
@@ -15,7 +13,9 @@ const i18n = setupI18n('en', enMessages);
export default {
title: 'Components/Input',
-};
+ argTypes: {},
+ args: {},
+} satisfies Meta;
const createProps = (overrideProps: Partial = {}): PropsType => ({
disabled: Boolean(overrideProps.disabled),
@@ -26,11 +26,8 @@ const createProps = (overrideProps: Partial = {}): PropsType => ({
icon: overrideProps.icon,
maxLengthCount: overrideProps.maxLengthCount,
onChange: action('onChange'),
- placeholder: text(
- 'placeholder',
- overrideProps.placeholder || 'Enter some text here'
- ),
- value: text('value', overrideProps.value || ''),
+ placeholder: overrideProps.placeholder ?? 'Enter some text here',
+ value: overrideProps.value ?? '',
whenToShowRemainingCount: overrideProps.whenToShowRemainingCount,
});
@@ -55,10 +52,6 @@ export function HasClearButton(): JSX.Element {
);
}
-HasClearButton.story = {
- name: 'hasClearButton',
-};
-
export function CharacterCount(): JSX.Element {
return (
);
}
-
-SpellcheckDisabled.story = {
- name: 'spellcheck disabled',
-};
diff --git a/ts/components/Intl.stories.tsx b/ts/components/Intl.stories.tsx
index d2dfb2359b90..1460c902ddf1 100644
--- a/ts/components/Intl.stories.tsx
+++ b/ts/components/Intl.stories.tsx
@@ -1,7 +1,7 @@
// Copyright 2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
-import type { Meta, Story } from '@storybook/react';
+import type { Meta, StoryFn } from '@storybook/react';
import * as React from 'react';
import type { Props } from './Intl';
@@ -14,7 +14,7 @@ const i18n = setupI18n('en', enMessages);
export default {
title: 'Components/Intl',
component: Intl,
-} as Meta;
+} satisfies Meta;
const createProps = (overrideProps: Partial = {}): Props => ({
i18n,
@@ -24,7 +24,7 @@ const createProps = (overrideProps: Partial = {}): Props => ({
// eslint-disable-next-line max-len
// eslint-disable-next-line react/function-component-definition, local-rules/valid-i18n-keys
-const Template: Story = args => ;
+const Template: StoryFn = args => ;
export const NoReplacements = Template.bind({});
NoReplacements.args = createProps({
diff --git a/ts/components/LeftPane.stories.tsx b/ts/components/LeftPane.stories.tsx
index 3b95675eef77..4c27e6c69fb6 100644
--- a/ts/components/LeftPane.stories.tsx
+++ b/ts/components/LeftPane.stories.tsx
@@ -2,10 +2,8 @@
// SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react';
-
import { action } from '@storybook/addon-actions';
-import { boolean, select } from '@storybook/addon-knobs';
-
+import type { Meta } from '@storybook/react';
import type { PropsType } from './LeftPane';
import { LeftPane, LeftPaneMode } from './LeftPane';
import { CaptchaDialog } from './CaptchaDialog';
@@ -45,7 +43,9 @@ type OverridePropsType = Partial & {
export default {
title: 'Components/LeftPane',
-};
+ argTypes: {},
+ args: {},
+} satisfies Meta;
const defaultConversations: Array = [
getDefaultConversation({
@@ -126,11 +126,8 @@ const useProps = (overrideProps: OverridePropsType = {}): PropsType => {
};
}
- const isUpdateDownloaded = boolean('isUpdateDownloaded', false);
- const isContactManagementEnabled = boolean(
- 'isContactManagementEnabled',
- true
- );
+ const isUpdateDownloaded = false;
+ const isContactManagementEnabled = true;
return {
otherTabsUnreadStats: {
@@ -151,28 +148,20 @@ const useProps = (overrideProps: OverridePropsType = {}): PropsType => {
hasFailedStorySends: false,
hasPendingUpdate: false,
i18n,
- isMacOS: boolean('isMacOS', false),
+ isMacOS: false,
preferredWidthFromStorage: 320,
regionCode: 'US',
- challengeStatus: select(
- 'challengeStatus',
- ['idle', 'required', 'pending'],
- 'idle'
- ),
- crashReportCount: select('challengeReportCount', [0, 1], 0),
+ challengeStatus: 'idle',
+ crashReportCount: 0,
- hasNetworkDialog: boolean('hasNetworkDialog', false),
- hasExpiredDialog: boolean('hasExpiredDialog', false),
- hasRelinkDialog: boolean('hasRelinkDialog', false),
- hasUpdateDialog: boolean('hasUpdateDialog', false),
- unsupportedOSDialogType: select(
- 'unsupportedOSDialogType',
- ['error', 'warning', undefined],
- undefined
- ),
+ hasNetworkDialog: false,
+ hasExpiredDialog: false,
+ hasRelinkDialog: false,
+ hasUpdateDialog: false,
+ unsupportedOSDialogType: undefined,
isUpdateDownloaded,
isContactManagementEnabled,
- navTabsCollapsed: boolean('navTabsCollapsed', false),
+ navTabsCollapsed: false,
setChallengeStatus: action('setChallengeStatus'),
lookupConversationWithoutServiceId:
@@ -315,10 +304,6 @@ export function InboxNoConversations(): JSX.Element {
);
}
-InboxNoConversations.story = {
- name: 'Inbox: no conversations',
-};
-
export function InboxOnlyPinnedConversations(): JSX.Element {
return (
;
}
-InboxPinnedNonPinnedAndArchivedConversations.story = {
- name: 'Inbox: pinned, non-pinned, and archived conversations',
-};
-
export function SearchNoResultsWhenSearchingEverywhere(): JSX.Element {
return (
(
-
-);
-
-_CrashReportDialog.story = {
- name: 'Crash report dialog',
-};
+export function _CrashReportDialog(): JSX.Element {
+ return (
+
+ );
+}
export function ChooseGroupMembersPartialPhoneNumber(): JSX.Element {
return (
@@ -1055,10 +910,6 @@ export function ChooseGroupMembersPartialPhoneNumber(): JSX.Element {
);
}
-ChooseGroupMembersPartialPhoneNumber.story = {
- name: 'Choose Group Members: Partial phone number',
-};
-
export function ChooseGroupMembersValidPhoneNumber(): JSX.Element {
return (
null,
clickLabel: 'Click me',
containerWidthBreakpoint: WidthBreakpoint.Wide,
},
-};
+} satisfies Meta;
export const Update = {
args: {
diff --git a/ts/components/Lightbox.stories.tsx b/ts/components/Lightbox.stories.tsx
index 5f600473ec16..a6c55eb72c29 100644
--- a/ts/components/Lightbox.stories.tsx
+++ b/ts/components/Lightbox.stories.tsx
@@ -2,11 +2,9 @@
// SPDX-License-Identifier: AGPL-3.0-only
import React, { useState } from 'react';
-
import { action } from '@storybook/addon-actions';
-import { number } from '@storybook/addon-knobs';
import { noop } from 'lodash';
-
+import type { Meta } from '@storybook/react';
import enMessages from '../../_locales/en/messages.json';
import type { PropsType } from './Lightbox';
import { Lightbox } from './Lightbox';
@@ -26,7 +24,9 @@ const i18n = setupI18n('en', enMessages);
export default {
title: 'Components/Lightbox',
-};
+ argTypes: {},
+ args: {},
+} satisfies Meta;
type OverridePropsMediaItemType = Partial & { caption?: string };
@@ -57,9 +57,7 @@ function createMediaItem(
const createProps = (overrideProps: Partial = {}): PropsType => {
// eslint-disable-next-line react-hooks/rules-of-hooks
- const [selectedIndex, setSelectedIndex] = useState(
- number('selectedIndex', overrideProps.selectedIndex || 0)
- );
+ const [selectedIndex, setSelectedIndex] = useState(0);
const media = overrideProps.media || [];
return {
closeLightbox: action('closeLightbox'),
@@ -196,10 +194,6 @@ export function ImageWithCaptionNormalImage(): JSX.Element {
);
}
-ImageWithCaptionNormalImage.story = {
- name: 'Image with Caption (normal image)',
-};
-
export function ImageWithCaptionAllWhiteImage(): JSX.Element {
return (
{
+ log.error('Lightbox: Failed to play video', Errors.toLogFormat(error));
+ });
} else {
videoElement.pause();
}
diff --git a/ts/components/ListTile.stories.tsx b/ts/components/ListTile.stories.tsx
index 279c8cbf1327..b54c376b7b76 100644
--- a/ts/components/ListTile.stories.tsx
+++ b/ts/components/ListTile.stories.tsx
@@ -1,7 +1,7 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
-import type { Story } from '@storybook/react';
+import type { Meta, StoryFn } from '@storybook/react';
import React from 'react';
import { ListTile } from './ListTile';
import type { Props } from './ListTile';
@@ -11,12 +11,12 @@ import { UserText } from './UserText';
export default {
title: 'Components/ListTile',
component: ListTile,
-};
+} satisfies Meta;
const lorem =
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam feugiat quam vitae semper facilisis. Praesent eu efficitur dui. Donec semper mattis nisl non hendrerit.';
-function TemplateList(width: number): Story {
+function TemplateList(width: number): StoryFn {
// eslint-disable-next-line react/display-name
return args => {
return (
diff --git a/ts/components/MediaEditor.stories.tsx b/ts/components/MediaEditor.stories.tsx
index 53ec34c3f030..7ac7928a5213 100644
--- a/ts/components/MediaEditor.stories.tsx
+++ b/ts/components/MediaEditor.stories.tsx
@@ -1,9 +1,10 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
-import type { Meta, Story } from '@storybook/react';
+import type { Meta, StoryFn } from '@storybook/react';
import React from 'react';
+import { action } from '@storybook/addon-actions';
import type { PropsType } from './MediaEditor';
import { MediaEditor } from './MediaEditor';
import enMessages from '../../_locales/en/messages.json';
@@ -19,48 +20,28 @@ const IMAGE_4 = '/fixtures/snow.jpg';
export default {
title: 'Components/MediaEditor',
component: MediaEditor,
- argTypes: {
- getPreferredBadge: { action: true },
- i18n: {
- defaultValue: i18n,
- },
- imageToBlurHash: { action: true },
- imageSrc: {
- defaultValue: IMAGE_2,
- },
- installedPacks: {
- defaultValue: installedPacks,
- },
- isFormattingEnabled: {
- defaultValue: true,
- },
- isFormattingFlagEnabled: {
- defaultValue: true,
- },
- isFormattingSpoilersFlagEnabled: {
- defaultValue: true,
- },
- isSending: {
- defaultValue: false,
- },
- onClose: { action: true },
- onDone: { action: true },
- onPickEmoji: { action: true },
- onTextTooLong: { action: true },
- platform: {
- defaultValue: 'darwin',
- },
- recentStickers: {
- defaultValue: [Stickers.wide, Stickers.tall, Stickers.abe],
- },
- skinTone: {
- defaultValue: 0,
- },
+ args: {
+ getPreferredBadge: () => undefined,
+ i18n,
+ imageToBlurHash: input => Promise.resolve(input.toString()),
+ imageSrc: IMAGE_2,
+ installedPacks,
+ isFormattingEnabled: true,
+ isFormattingFlagEnabled: true,
+ isFormattingSpoilersFlagEnabled: true,
+ isSending: false,
+ onClose: action('onClose'),
+ onDone: action('onDone'),
+ onPickEmoji: action('onPickEmoji'),
+ onTextTooLong: action('onTextTooLong'),
+ platform: 'darwin',
+ recentStickers: [Stickers.wide, Stickers.tall, Stickers.abe],
+ skinTone: 0,
},
-} as Meta;
+} satisfies Meta;
// eslint-disable-next-line react/function-component-definition
-const Template: Story = args => ;
+const Template: StoryFn = args => ;
export const ExtraLarge = Template.bind({});
diff --git a/ts/components/MediaQualitySelector.stories.tsx b/ts/components/MediaQualitySelector.stories.tsx
index a1277f3516a3..61ba742e1efd 100644
--- a/ts/components/MediaQualitySelector.stories.tsx
+++ b/ts/components/MediaQualitySelector.stories.tsx
@@ -2,10 +2,8 @@
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
-
import { action } from '@storybook/addon-actions';
-import { boolean } from '@storybook/addon-knobs';
-
+import type { Meta } from '@storybook/react';
import enMessages from '../../_locales/en/messages.json';
import type { PropsType } from './MediaQualitySelector';
import { MediaQualitySelector } from './MediaQualitySelector';
@@ -13,14 +11,16 @@ import { setupI18n } from '../util/setupI18n';
export default {
title: 'Components/MediaQualitySelector',
-};
+ argTypes: {},
+ args: {},
+} satisfies Meta;
const i18n = setupI18n('en', enMessages);
const createProps = (overrideProps: Partial = {}): PropsType => ({
conversationId: 'abc123',
i18n,
- isHighQuality: boolean('isHighQuality', Boolean(overrideProps.isHighQuality)),
+ isHighQuality: overrideProps.isHighQuality ?? false,
onSelectQuality: action('onSelectQuality'),
});
diff --git a/ts/components/MiniPlayer.stories.tsx b/ts/components/MiniPlayer.stories.tsx
index 7c5e58cc89c0..f1570e3b1d30 100644
--- a/ts/components/MiniPlayer.stories.tsx
+++ b/ts/components/MiniPlayer.stories.tsx
@@ -2,6 +2,8 @@
// SPDX-License-Identifier: AGPL-3.0-only
import React, { useEffect, useState } from 'react';
+import type { Meta } from '@storybook/react';
+import type { Props } from './MiniPlayer';
import { MiniPlayer, PlayerState } from './MiniPlayer';
import { setupI18n } from '../util/setupI18n';
@@ -15,7 +17,7 @@ audio.src = '/fixtures/incompetech-com-Agnus-Dei-X.mp3';
export default {
title: 'components/MiniPlayer',
component: MiniPlayer,
-};
+} satisfies Meta;
export function Default(): JSX.Element {
const [active, setActive] = useState(false);
diff --git a/ts/components/Modal.stories.tsx b/ts/components/Modal.stories.tsx
index 267fdffeb5c1..6a4034febc5b 100644
--- a/ts/components/Modal.stories.tsx
+++ b/ts/components/Modal.stories.tsx
@@ -3,19 +3,19 @@
import React from 'react';
import { noop } from 'lodash';
-
import { action } from '@storybook/addon-actions';
-
+import type { Meta } from '@storybook/react';
import { setupI18n } from '../util/setupI18n';
import enMessages from '../../_locales/en/messages.json';
import { Button } from './Button';
+import type { ModalPropsType } from './Modal';
import { Modal } from './Modal';
const i18n = setupI18n('en', enMessages);
export default {
title: 'Components/Modal',
-};
+} satisfies Meta;
const onClose = action('onClose');
@@ -30,10 +30,6 @@ export function BareBonesShort(): JSX.Element {
);
}
-BareBonesShort.story = {
- name: 'Bare bones, short',
-};
-
export function BareBonesLong(): JSX.Element {
return (
@@ -45,10 +41,6 @@ export function BareBonesLong(): JSX.Element {
);
}
-BareBonesLong.story = {
- name: 'Bare bones, long',
-};
-
export function BareBonesLongWithButton(): JSX.Element {
return (
);
}
-
-WithBackButton.story = {
- name: 'Back Button',
-};
diff --git a/ts/components/MyStories.stories.tsx b/ts/components/MyStories.stories.tsx
index 8d916eff8617..915fae063149 100644
--- a/ts/components/MyStories.stories.tsx
+++ b/ts/components/MyStories.stories.tsx
@@ -1,13 +1,14 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
-import type { Meta, ReactFramework, Story } from '@storybook/react';
+import type { Meta, ReactRenderer, StoryFn } from '@storybook/react';
import type { PlayFunction } from '@storybook/csf';
import React from 'react';
-import { expect } from '@storybook/jest';
+import { expect, jest } from '@storybook/jest';
import { v4 as uuid } from 'uuid';
import { within, userEvent } from '@storybook/testing-library';
+import { action } from '@storybook/addon-actions';
import type { PropsType } from './MyStories';
import enMessages from '../../_locales/en/messages.json';
import { MY_STORY_ID } from '../types/Stories';
@@ -24,50 +25,32 @@ export default {
title: 'Components/MyStories',
component: MyStories,
argTypes: {
- i18n: {
- defaultValue: i18n,
- },
- onBack: {
- action: true,
- },
- onDelete: {
- action: true,
- },
- onForward: {
- action: true,
- },
- onSave: {
- action: true,
- },
- ourConversationId: {
- defaultValue: getDefaultConversation().id,
- },
hasViewReceiptSetting: {
control: 'boolean',
- defaultValue: false,
},
- queueStoryDownload: {
- action: true,
- },
- retryMessageSend: {
- action: true,
- },
- viewStory: { action: true },
},
-} as Meta;
+ args: {
+ i18n,
+ onBack: jest.fn(action('onBack')),
+ onDelete: action('onDelete'),
+ onForward: jest.fn(action('onForward')),
+ onSave: jest.fn(action('onSave')),
+ hasViewReceiptSetting: false,
+ queueStoryDownload: action('queueStoryDownload'),
+ retryMessageSend: action('retryMessageSend'),
+ viewStory: action('viewStory'),
+ },
+} satisfies Meta;
// eslint-disable-next-line react/function-component-definition
-const Template: Story = args => ;
+const Template: StoryFn = args => ;
export const NoStories = Template.bind({});
NoStories.args = {
myStories: [],
};
-NoStories.story = {
- name: 'No Stories',
-};
-const interactionTest: PlayFunction = async ({
+const interactionTest: PlayFunction = async ({
args,
canvasElement,
}) => {
@@ -76,7 +59,7 @@ const interactionTest: PlayFunction = async ({
await userEvent.click(btnDownload);
await expect(args.onSave).toHaveBeenCalled();
- const [btnBack] = canvas.getAllByLabelText('Back');
+ const btnBack = canvas.getByText('Back');
await userEvent.click(btnBack);
await expect(args.onBack).toHaveBeenCalled();
@@ -94,9 +77,6 @@ SingleListStories.args = {
myStories: [getFakeMyStory(MY_STORY_ID)],
};
SingleListStories.play = interactionTest;
-SingleListStories.story = {
- name: 'One distribution list',
-};
export const MultiListStories = Template.bind({});
MultiListStories.args = {
@@ -107,9 +87,6 @@ MultiListStories.args = {
],
};
MultiListStories.play = interactionTest;
-MultiListStories.story = {
- name: 'Multiple distribution lists',
-};
export const FailedSentStory = Template.bind({});
{
diff --git a/ts/components/MyStoryButton.stories.tsx b/ts/components/MyStoryButton.stories.tsx
index b49b3b057741..c4589f0e24ed 100644
--- a/ts/components/MyStoryButton.stories.tsx
+++ b/ts/components/MyStoryButton.stories.tsx
@@ -1,12 +1,13 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
-import type { Meta, ReactFramework, Story } from '@storybook/react';
+import type { Meta, ReactRenderer, StoryFn } from '@storybook/react';
import type { PlayFunction } from '@storybook/csf';
import React from 'react';
-import { expect } from '@storybook/jest';
+import { expect, jest } from '@storybook/jest';
import { within, userEvent } from '@storybook/testing-library';
+import { action } from '@storybook/addon-actions';
import type { PropsType } from './MyStoryButton';
import enMessages from '../../_locales/en/messages.json';
import { MyStoryButton } from './MyStoryButton';
@@ -21,27 +22,21 @@ const i18n = setupI18n('en', enMessages);
export default {
title: 'Components/MyStoriesButton',
component: MyStoryButton,
- argTypes: {
- i18n: {
- defaultValue: i18n,
- },
- me: {
- defaultValue: getDefaultConversation(),
- },
- myStories: {
- defaultValue: [getFakeMyStory()],
- },
- onAddStory: { action: true },
- onClick: { action: true },
- queueStoryDownload: { action: true },
- showToast: { action: true },
+ args: {
+ i18n,
+ me: getDefaultConversation(),
+ myStories: [getFakeMyStory()],
+ onAddStory: jest.fn(action('onAddStory')),
+ onClick: jest.fn(action('onClick')),
+ queueStoryDownload: action('queueStoryDownload'),
+ showToast: action('showToast'),
},
-} as Meta;
+} satisfies Meta;
// eslint-disable-next-line react/function-component-definition
-const Template: Story = args => ;
+const Template: StoryFn = args => ;
-const interactionTest: PlayFunction = async ({
+const interactionTest: PlayFunction = async ({
args,
canvasElement,
}) => {
@@ -51,40 +46,34 @@ const interactionTest: PlayFunction = async ({
const textStory = canvas.getByText('Text story');
await userEvent.click(textStory);
await expect(args.onAddStory).toHaveBeenCalled();
- const btnStory = canvas.getByText('My Stories');
- await userEvent.click(btnStory);
- await expect(args.onClick).toHaveBeenCalled();
+ if (args.myStories.length > 0) {
+ const btnStory = canvas.getByText('My Stories');
+ await userEvent.click(btnStory);
+ await expect(args.onClick).toHaveBeenCalled();
+ }
};
export const NoStory = Template.bind({});
NoStory.args = {
myStories: [],
};
-NoStory.story = {
- name: 'No Story',
-};
+
NoStory.play = interactionTest;
export const OneStory = Template.bind({});
OneStory.args = {};
-OneStory.story = {
- name: 'One Story',
-};
+
OneStory.play = interactionTest;
export const ManyStories = Template.bind({});
ManyStories.args = {
myStories: [getFakeMyStory(), getFakeMyStory()],
};
-ManyStories.story = {
- name: 'Many Stories',
-};
+
ManyStories.play = interactionTest;
export const SendingStory = Template.bind({});
-SendingStory.story = {
- name: 'Sending Story',
-};
+
{
const myStory = getFakeMyStory();
SendingStory.args = {
@@ -115,9 +104,7 @@ SendingStory.story = {
SendingStory.play = interactionTest;
export const FailedSendStory = Template.bind({});
-FailedSendStory.story = {
- name: 'Failed Send Story',
-};
+
{
const myStory = getFakeMyStory();
FailedSendStory.args = {
diff --git a/ts/components/NewlyCreatedGroupInvitedContactsDialog.stories.tsx b/ts/components/NewlyCreatedGroupInvitedContactsDialog.stories.tsx
index a5034790240d..c4c458e93239 100644
--- a/ts/components/NewlyCreatedGroupInvitedContactsDialog.stories.tsx
+++ b/ts/components/NewlyCreatedGroupInvitedContactsDialog.stories.tsx
@@ -5,6 +5,8 @@ import React from 'react';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
+import type { PropsType } from './NewlyCreatedGroupInvitedContactsDialog';
import { NewlyCreatedGroupInvitedContactsDialog } from './NewlyCreatedGroupInvitedContactsDialog';
import { setupI18n } from '../util/setupI18n';
import enMessages from '../../_locales/en/messages.json';
@@ -21,7 +23,7 @@ const conversations: Array = [
export default {
title: 'Components/NewlyCreatedGroupInvitedContactsDialog',
-};
+} satisfies Meta;
export function OneContact(): JSX.Element {
return (
@@ -35,10 +37,6 @@ export function OneContact(): JSX.Element {
);
}
-OneContact.story = {
- name: 'One contact',
-};
-
export function TwoContacts(): JSX.Element {
return (
);
}
-
-TwoContacts.story = {
- name: 'Two contacts',
-};
diff --git a/ts/components/NewlyCreatedGroupInvitedContactsDialog.tsx b/ts/components/NewlyCreatedGroupInvitedContactsDialog.tsx
index e0c17032d7eb..51887d427ae3 100644
--- a/ts/components/NewlyCreatedGroupInvitedContactsDialog.tsx
+++ b/ts/components/NewlyCreatedGroupInvitedContactsDialog.tsx
@@ -12,7 +12,7 @@ import { ContactName } from './conversation/ContactName';
import { GroupDialog } from './GroupDialog';
import { openLinkInWebBrowser } from '../util/openLinkInWebBrowser';
-type PropsType = {
+export type PropsType = {
contacts: Array;
getPreferredBadge: PreferredBadgeSelectorType;
i18n: LocalizerType;
diff --git a/ts/components/OutgoingGiftBadgeModal.stories.tsx b/ts/components/OutgoingGiftBadgeModal.stories.tsx
index 8c9e22d44a3a..d5a85f5eab44 100644
--- a/ts/components/OutgoingGiftBadgeModal.stories.tsx
+++ b/ts/components/OutgoingGiftBadgeModal.stories.tsx
@@ -2,12 +2,10 @@
// SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react';
-import { text } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions';
-
+import type { Meta } from '@storybook/react';
import type { PropsType } from './OutgoingGiftBadgeModal';
import { OutgoingGiftBadgeModal } from './OutgoingGiftBadgeModal';
-
import { setupI18n } from '../util/setupI18n';
import enMessages from '../../_locales/en/messages.json';
import { BadgeCategory } from '../badges/BadgeCategory';
@@ -30,11 +28,8 @@ const getPreferredBadge = () => ({
});
const createProps = (overrideProps: Partial = {}): PropsType => ({
- recipientTitle: text(
- 'recipientTitle',
- overrideProps.recipientTitle || 'Default Name'
- ),
- badgeId: text('badgeId', overrideProps.badgeId || 'heart'),
+ recipientTitle: overrideProps.recipientTitle ?? 'Default Name',
+ badgeId: overrideProps.badgeId ?? 'heart',
getPreferredBadge,
hideOutgoingGiftBadgeModal: action('hideOutgoingGiftBadgeModal'),
i18n,
@@ -42,7 +37,9 @@ const createProps = (overrideProps: Partial = {}): PropsType => ({
export default {
title: 'Components/OutgoingGiftBadgeModal',
-};
+ argTypes: {},
+ args: {},
+} satisfies Meta;
export function Normal(): JSX.Element {
return ;
@@ -56,7 +53,3 @@ export function MissingBadge(): JSX.Element {
return ;
}
-
-MissingBadge.story = {
- name: 'Missing badge',
-};
diff --git a/ts/components/PlaybackButton.stories.tsx b/ts/components/PlaybackButton.stories.tsx
index 8080e83822fb..2ae8bffea444 100644
--- a/ts/components/PlaybackButton.stories.tsx
+++ b/ts/components/PlaybackButton.stories.tsx
@@ -4,12 +4,14 @@
import React from 'react';
import type { CSSProperties } from 'react';
import { action } from '@storybook/addon-actions';
+import type { Meta } from '@storybook/react';
+import type { ButtonProps } from './PlaybackButton';
import { PlaybackButton } from './PlaybackButton';
export default {
title: 'components/PlaybackButton',
component: PlaybackButton,
-};
+} satisfies Meta;
const rowStyles: CSSProperties = {
display: 'flex',
diff --git a/ts/components/PlaybackButton.tsx b/ts/components/PlaybackButton.tsx
index 0f9794408833..c66ac08aa86c 100644
--- a/ts/components/PlaybackButton.tsx
+++ b/ts/components/PlaybackButton.tsx
@@ -12,7 +12,7 @@ const SPRING_CONFIG = {
velocity: 0.01,
};
-type ButtonProps = {
+export type ButtonProps = {
context?: 'incoming' | 'outgoing';
variant: 'message' | 'mini' | 'draft';
mod: 'play' | 'pause' | 'download' | 'pending';
diff --git a/ts/components/Preferences.stories.tsx b/ts/components/Preferences.stories.tsx
index 88dcb62e5c33..2d6f975d24df 100644
--- a/ts/components/Preferences.stories.tsx
+++ b/ts/components/Preferences.stories.tsx
@@ -1,17 +1,17 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
-import type { Meta, Story } from '@storybook/react';
+import type { Meta, StoryFn } from '@storybook/react';
import React from 'react';
+import { action } from '@storybook/addon-actions';
import enMessages from '../../_locales/en/messages.json';
-import type { PropsDataType, PropsType } from './Preferences';
+import type { PropsType } from './Preferences';
import { Preferences } from './Preferences';
import { setupI18n } from '../util/setupI18n';
import { DEFAULT_CONVERSATION_COLOR } from '../types/Colors';
import { PhoneNumberSharingMode } from '../util/phoneNumberSharingMode';
import { PhoneNumberDiscoverability } from '../util/phoneNumberDiscoverability';
-import { objectMap } from '../util/objectMap';
import { DurationInSeconds } from '../util/durations';
const i18n = setupI18n('en', enMessages);
@@ -44,145 +44,144 @@ const availableSpeakers = [
},
];
-const getDefaultArgs = (): PropsDataType => ({
- availableCameras: [
- {
- deviceId:
- 'dfbe6effe70b0611ba0fdc2a9ea3f39f6cb110e6687948f7e5f016c111b7329c',
- groupId:
- '63ee218d2446869e40adfc958ff98263e51f74382b0143328ee4826f20a76f47',
- kind: 'videoinput' as MediaDeviceKind,
- label: 'FaceTime HD Camera (Built-in) (9fba:bced)',
- },
- {
- deviceId:
- 'e2db196a31d50ff9b135299dc0beea67f65b1a25a06d8a4ce76976751bb7a08d',
- groupId:
- '218ba7f00d7b1239cca15b9116769e5e7d30cc01104ebf84d667643661e0ecf9',
- kind: 'videoinput' as MediaDeviceKind,
- label: 'Logitech Webcam (4e72:9058)',
- },
- ],
- availableMicrophones,
- availableSpeakers,
- blockedCount: 0,
- customColors: {},
- defaultConversationColor: DEFAULT_CONVERSATION_COLOR,
- deviceName: 'Work Windows ME',
- hasAudioNotifications: true,
- hasAutoDownloadUpdate: true,
- hasAutoLaunch: true,
- hasCallNotifications: true,
- hasCallRingtoneNotification: false,
- hasCountMutedConversations: false,
- hasCustomTitleBar: true,
- hasHideMenuBar: false,
- hasIncomingCallNotifications: true,
- hasLinkPreviews: true,
- hasMediaCameraPermissions: true,
- hasMediaPermissions: true,
- hasMessageAudio: true,
- hasMinimizeToAndStartInSystemTray: true,
- hasMinimizeToSystemTray: true,
- hasNotificationAttention: false,
- hasNotifications: true,
- hasReadReceipts: true,
- hasRelayCalls: false,
- hasSpellCheck: true,
- hasStoriesDisabled: false,
- hasTextFormatting: true,
- hasTypingIndicators: true,
- initialSpellCheckSetting: true,
- isAutoDownloadUpdatesSupported: true,
- isAutoLaunchSupported: true,
- isFormattingFlagEnabled: true,
- isHideMenuBarSupported: true,
- isNotificationAttentionSupported: true,
- isPhoneNumberSharingSupported: true,
- isSyncSupported: true,
- isSystemTraySupported: true,
- isMinimizeToAndStartInSystemTraySupported: true,
- lastSyncTime: Date.now(),
- notificationContent: 'name',
- selectedCamera:
- 'dfbe6effe70b0611ba0fdc2a9ea3f39f6cb110e6687948f7e5f016c111b7329c',
- selectedMicrophone: availableMicrophones[0],
- selectedSpeaker: availableSpeakers[1],
- shouldShowStoriesSettings: true,
- sentMediaQualitySetting: 'standard',
- themeSetting: 'system',
- universalExpireTimer: DurationInSeconds.HOUR,
- whoCanFindMe: PhoneNumberDiscoverability.Discoverable,
- whoCanSeeMe: PhoneNumberSharingMode.Everybody,
- zoomFactor: 1,
-});
-
-const defaultArgTypes: Record = {};
-objectMap(getDefaultArgs(), (key, defaultValue) => {
- defaultArgTypes[key] = { defaultValue };
-});
-
export default {
title: 'Components/Preferences',
component: Preferences,
- argTypes: {
- // ...defaultArgTypes,
+ args: {
+ i18n,
- i18n: {
- defaultValue: i18n,
- },
+ availableCameras: [
+ {
+ deviceId:
+ 'dfbe6effe70b0611ba0fdc2a9ea3f39f6cb110e6687948f7e5f016c111b7329c',
+ groupId:
+ '63ee218d2446869e40adfc958ff98263e51f74382b0143328ee4826f20a76f47',
+ kind: 'videoinput' as MediaDeviceKind,
+ label: 'FaceTime HD Camera (Built-in) (9fba:bced)',
+ },
+ {
+ deviceId:
+ 'e2db196a31d50ff9b135299dc0beea67f65b1a25a06d8a4ce76976751bb7a08d',
+ groupId:
+ '218ba7f00d7b1239cca15b9116769e5e7d30cc01104ebf84d667643661e0ecf9',
+ kind: 'videoinput' as MediaDeviceKind,
+ label: 'Logitech Webcam (4e72:9058)',
+ },
+ ],
+ availableMicrophones,
+ availableSpeakers,
+ blockedCount: 0,
+ customColors: {},
+ defaultConversationColor: DEFAULT_CONVERSATION_COLOR,
+ deviceName: 'Work Windows ME',
+ hasAudioNotifications: true,
+ hasAutoDownloadUpdate: true,
+ hasAutoLaunch: true,
+ hasCallNotifications: true,
+ hasCallRingtoneNotification: false,
+ hasCountMutedConversations: false,
+ hasCustomTitleBar: true,
+ hasHideMenuBar: false,
+ hasIncomingCallNotifications: true,
+ hasLinkPreviews: true,
+ hasMediaCameraPermissions: true,
+ hasMediaPermissions: true,
+ hasMessageAudio: true,
+ hasMinimizeToAndStartInSystemTray: true,
+ hasMinimizeToSystemTray: true,
+ hasNotificationAttention: false,
+ hasNotifications: true,
+ hasReadReceipts: true,
+ hasRelayCalls: false,
+ hasSpellCheck: true,
+ hasStoriesDisabled: false,
+ hasTextFormatting: true,
+ hasTypingIndicators: true,
+ initialSpellCheckSetting: true,
+ isAutoDownloadUpdatesSupported: true,
+ isAutoLaunchSupported: true,
+ isFormattingFlagEnabled: true,
+ isHideMenuBarSupported: true,
+ isNotificationAttentionSupported: true,
+ isPhoneNumberSharingSupported: true,
+ isSyncSupported: true,
+ isSystemTraySupported: true,
+ isMinimizeToAndStartInSystemTraySupported: true,
+ lastSyncTime: Date.now(),
+ notificationContent: 'name',
+ selectedCamera:
+ 'dfbe6effe70b0611ba0fdc2a9ea3f39f6cb110e6687948f7e5f016c111b7329c',
+ selectedMicrophone: availableMicrophones[0],
+ selectedSpeaker: availableSpeakers[1],
+ shouldShowStoriesSettings: true,
+ sentMediaQualitySetting: 'standard',
+ themeSetting: 'system',
+ universalExpireTimer: DurationInSeconds.HOUR,
+ whoCanFindMe: PhoneNumberDiscoverability.Discoverable,
+ whoCanSeeMe: PhoneNumberSharingMode.Everybody,
+ zoomFactor: 1,
- addCustomColor: { action: true },
- closeSettings: { action: true },
- doDeleteAllData: { action: true },
- doneRendering: { action: true },
- editCustomColor: { action: true },
- executeMenuRole: { action: true },
- getConversationsWithCustomColor: { action: true },
- makeSyncRequest: { action: true },
- onAudioNotificationsChange: { action: true },
- onAutoDownloadUpdateChange: { action: true },
- onAutoLaunchChange: { action: true },
- onCallNotificationsChange: { action: true },
- onCallRingtoneNotificationChange: { action: true },
- onCountMutedConversationsChange: { action: true },
- onHasStoriesDisabledChanged: { action: true },
- onHideMenuBarChange: { action: true },
- onIncomingCallNotificationsChange: { action: true },
- onLastSyncTimeChange: { action: true },
- onMediaCameraPermissionsChange: { action: true },
- onMediaPermissionsChange: { action: true },
- onMessageAudioChange: { action: true },
- onMinimizeToAndStartInSystemTrayChange: { action: true },
- onMinimizeToSystemTrayChange: { action: true },
- onNotificationAttentionChange: { action: true },
- onNotificationContentChange: { action: true },
- onNotificationsChange: { action: true },
- onRelayCallsChange: { action: true },
- onSelectedCameraChange: { action: true },
- onSelectedMicrophoneChange: { action: true },
- onSelectedSpeakerChange: { action: true },
- onSentMediaQualityChange: { action: true },
- onSpellCheckChange: { action: true },
- onTextFormattingChange: { action: true },
- onThemeChange: { action: true },
- onUniversalExpireTimerChange: { action: true },
- onWhoCanSeeMeChange: { action: true },
- onWhoCanFindMeChange: { action: true },
- onZoomFactorChange: { action: true },
- removeCustomColor: { action: true },
- removeCustomColorOnConversations: { action: true },
- resetAllChatColors: { action: true },
- resetDefaultChatColor: { action: true },
- setGlobalDefaultConversationColor: { action: true },
- },
-} as Meta;
+ getConversationsWithCustomColor: () => Promise.resolve([]),
+
+ addCustomColor: action('addCustomColor'),
+ closeSettings: action('closeSettings'),
+ doDeleteAllData: action('doDeleteAllData'),
+ doneRendering: action('doneRendering'),
+ editCustomColor: action('editCustomColor'),
+ executeMenuRole: action('executeMenuRole'),
+ makeSyncRequest: action('makeSyncRequest'),
+ onAudioNotificationsChange: action('onAudioNotificationsChange'),
+ onAutoDownloadUpdateChange: action('onAutoDownloadUpdateChange'),
+ onAutoLaunchChange: action('onAutoLaunchChange'),
+ onCallNotificationsChange: action('onCallNotificationsChange'),
+ onCallRingtoneNotificationChange: action(
+ 'onCallRingtoneNotificationChange'
+ ),
+ onCountMutedConversationsChange: action('onCountMutedConversationsChange'),
+ onHasStoriesDisabledChanged: action('onHasStoriesDisabledChanged'),
+ onHideMenuBarChange: action('onHideMenuBarChange'),
+ onIncomingCallNotificationsChange: action(
+ 'onIncomingCallNotificationsChange'
+ ),
+ onLastSyncTimeChange: action('onLastSyncTimeChange'),
+ onMediaCameraPermissionsChange: action('onMediaCameraPermissionsChange'),
+ onMediaPermissionsChange: action('onMediaPermissionsChange'),
+ onMessageAudioChange: action('onMessageAudioChange'),
+ onMinimizeToAndStartInSystemTrayChange: action(
+ 'onMinimizeToAndStartInSystemTrayChange'
+ ),
+ onMinimizeToSystemTrayChange: action('onMinimizeToSystemTrayChange'),
+ onNotificationAttentionChange: action('onNotificationAttentionChange'),
+ onNotificationContentChange: action('onNotificationContentChange'),
+ onNotificationsChange: action('onNotificationsChange'),
+ onRelayCallsChange: action('onRelayCallsChange'),
+ onSelectedCameraChange: action('onSelectedCameraChange'),
+ onSelectedMicrophoneChange: action('onSelectedMicrophoneChange'),
+ onSelectedSpeakerChange: action('onSelectedSpeakerChange'),
+ onSentMediaQualityChange: action('onSentMediaQualityChange'),
+ onSpellCheckChange: action('onSpellCheckChange'),
+ onTextFormattingChange: action('onTextFormattingChange'),
+ onThemeChange: action('onThemeChange'),
+ onUniversalExpireTimerChange: action('onUniversalExpireTimerChange'),
+ onWhoCanSeeMeChange: action('onWhoCanSeeMeChange'),
+ onWhoCanFindMeChange: action('onWhoCanFindMeChange'),
+ onZoomFactorChange: action('onZoomFactorChange'),
+ removeCustomColor: action('removeCustomColor'),
+ removeCustomColorOnConversations: action(
+ 'removeCustomColorOnConversations'
+ ),
+ resetAllChatColors: action('resetAllChatColors'),
+ resetDefaultChatColor: action('resetDefaultChatColor'),
+ setGlobalDefaultConversationColor: action(
+ 'setGlobalDefaultConversationColor'
+ ),
+ } satisfies PropsType,
+} satisfies Meta;
// eslint-disable-next-line react/function-component-definition
-const Template: Story = args => ;
+const Template: StoryFn = args => ;
export const _Preferences = Template.bind({});
-_Preferences.args = getDefaultArgs();
export const Blocked1 = Template.bind({});
Blocked1.args = {
@@ -198,9 +197,6 @@ export const CustomUniversalExpireTimer = Template.bind({});
CustomUniversalExpireTimer.args = {
universalExpireTimer: DurationInSeconds.fromSeconds(9000),
};
-CustomUniversalExpireTimer.story = {
- name: 'Custom universalExpireTimer',
-};
export const PNPSharingDisabled = Template.bind({});
PNPSharingDisabled.args = {
@@ -208,9 +204,6 @@ PNPSharingDisabled.args = {
whoCanFindMe: PhoneNumberDiscoverability.Discoverable,
isPhoneNumberSharingSupported: true,
};
-PNPSharingDisabled.story = {
- name: 'PNP Sharing Disabled',
-};
export const PNPDiscoverabilityDisabled = Template.bind({});
PNPDiscoverabilityDisabled.args = {
@@ -218,9 +211,6 @@ PNPDiscoverabilityDisabled.args = {
whoCanFindMe: PhoneNumberDiscoverability.NotDiscoverable,
isPhoneNumberSharingSupported: true,
};
-PNPDiscoverabilityDisabled.story = {
- name: 'PNP Discoverability Disabled',
-};
export const FormattingDisabled = Template.bind({});
FormattingDisabled.args = {
diff --git a/ts/components/ProfileEditor.stories.tsx b/ts/components/ProfileEditor.stories.tsx
index 32c388e2dcf1..9fe216309f80 100644
--- a/ts/components/ProfileEditor.stories.tsx
+++ b/ts/components/ProfileEditor.stories.tsx
@@ -1,7 +1,7 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
-import type { Meta, Story } from '@storybook/react';
+import type { Meta, StoryFn } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import React, { useState } from 'react';
import casual from 'casual';
@@ -18,6 +18,7 @@ import {
} from '../state/ducks/usernameEnums';
import { getRandomColor } from '../test-both/helpers/getRandomColor';
import { setupI18n } from '../util/setupI18n';
+import { SignalService as Proto } from '../protobuf';
const i18n = setupI18n('en', enMessages);
@@ -25,44 +26,11 @@ export default {
component: ProfileEditor,
title: 'Components/ProfileEditor',
argTypes: {
- aboutEmoji: {
- defaultValue: '',
- },
- aboutText: {
- defaultValue: casual.sentence,
- },
- profileAvatarPath: {
- defaultValue: undefined,
- },
- conversationId: {
- defaultValue: generateUuid(),
- },
- color: {
- defaultValue: getRandomColor(),
- },
- deleteAvatarFromDisk: { action: true },
- familyName: {
- defaultValue: casual.last_name,
- },
- firstName: {
- defaultValue: casual.first_name,
- },
- i18n: {
- defaultValue: i18n,
- },
- usernameLink: {
- defaultValue: 'https://signal.me/#eu/testtest',
- },
- usernameLinkFgColor: {
- defaultValue: '',
- },
isUsernameFlagEnabled: {
control: { type: 'checkbox' },
- defaultValue: false,
},
usernameEditState: {
control: { type: 'radio' },
- defaultValue: UsernameEditState.Editing,
options: {
Editing: UsernameEditState.Editing,
ConfirmingDelete: UsernameEditState.ConfirmingDelete,
@@ -71,37 +39,49 @@ export default {
},
usernameLinkState: {
control: { type: 'select' },
- defaultValue: UsernameLinkState.Ready,
options: [UsernameLinkState.Ready, UsernameLinkState.Updating],
},
- onEditStateChanged: { action: true },
- onProfileChanged: { action: true },
- onSetSkinTone: { action: true },
- saveAttachment: { action: true },
- setUsernameLinkColor: { action: true },
- showToast: { action: true },
- recentEmojis: {
- defaultValue: [],
- },
- replaceAvatar: { action: true },
- resetUsernameLink: { action: true },
- saveAvatarToDisk: { action: true },
- markCompletedUsernameOnboarding: { action: true },
- markCompletedUsernameLinkOnboarding: { action: true },
- openUsernameReservationModal: { action: true },
- setUsernameEditState: { action: true },
- deleteUsername: { action: true },
- skinTone: {
- defaultValue: 0,
- },
- userAvatarData: {
- defaultValue: [],
- },
- username: {
- defaultValue: undefined,
- },
},
-} as Meta;
+ args: {
+ aboutEmoji: '',
+ aboutText: casual.sentence,
+ profileAvatarPath: undefined,
+ conversationId: generateUuid(),
+ color: getRandomColor(),
+ deleteAvatarFromDisk: action('deleteAvatarFromDisk'),
+ familyName: casual.last_name,
+ firstName: casual.first_name,
+ i18n,
+
+ usernameLink: 'https://signal.me/#eu/testtest',
+ usernameLinkColor: Proto.AccountRecord.UsernameLink.Color.PURPLE,
+ isUsernameFlagEnabled: false,
+ usernameEditState: UsernameEditState.Editing,
+ usernameLinkState: UsernameLinkState.Ready,
+
+ recentEmojis: [],
+ skinTone: 0,
+ userAvatarData: [],
+ username: undefined,
+
+ onEditStateChanged: action('onEditStateChanged'),
+ onProfileChanged: action('onProfileChanged'),
+ onSetSkinTone: action('onSetSkinTone'),
+ saveAttachment: action('saveAttachment'),
+ setUsernameLinkColor: action('setUsernameLinkColor'),
+ showToast: action('showToast'),
+ replaceAvatar: action('replaceAvatar'),
+ resetUsernameLink: action('resetUsernameLink'),
+ saveAvatarToDisk: action('saveAvatarToDisk'),
+ markCompletedUsernameOnboarding: action('markCompletedUsernameOnboarding'),
+ markCompletedUsernameLinkOnboarding: action(
+ 'markCompletedUsernameLinkOnboarding'
+ ),
+ openUsernameReservationModal: action('openUsernameReservationModal'),
+ setUsernameEditState: action('setUsernameEditState'),
+ deleteUsername: action('deleteUsername'),
+ },
+} satisfies Meta;
function renderEditUsernameModalBody(props: {
onClose: () => void;
@@ -122,7 +102,7 @@ function renderEditUsernameModalBody(props: {
}
// eslint-disable-next-line react/function-component-definition
-const Template: Story = args => {
+const Template: StoryFn = args => {
const [skinTone, setSkinTone] = useState(0);
return (
@@ -148,35 +128,22 @@ export const WithFullName = Template.bind({});
WithFullName.args = {
familyName: casual.last_name,
};
-WithFullName.story = {
- name: 'with Full Name',
-};
-
export const WithCustomAbout = Template.bind({});
WithCustomAbout.args = {
aboutEmoji: '🙏',
aboutText: 'Live. Laugh. Love',
};
-WithCustomAbout.story = {
- name: 'with Custom About',
-};
export const WithUsernameFlagEnabled = Template.bind({});
WithUsernameFlagEnabled.args = {
isUsernameFlagEnabled: true,
};
-WithUsernameFlagEnabled.story = {
- name: 'with Username flag enabled',
-};
export const WithUsernameFlagEnabledAndUsername = Template.bind({});
WithUsernameFlagEnabledAndUsername.args = {
isUsernameFlagEnabled: true,
username: 'signaluser.123',
};
-WithUsernameFlagEnabledAndUsername.story = {
- name: 'with Username flag enabled and username',
-};
export const DeletingUsername = Template.bind({});
DeletingUsername.args = {
diff --git a/ts/components/ProgressDialog.stories.tsx b/ts/components/ProgressDialog.stories.tsx
index 88b5ced0a89a..a4ebc518474b 100644
--- a/ts/components/ProgressDialog.stories.tsx
+++ b/ts/components/ProgressDialog.stories.tsx
@@ -3,6 +3,7 @@
import * as React from 'react';
+import type { Meta } from '@storybook/react';
import type { PropsType } from './ProgressDialog';
import { ProgressDialog } from './ProgressDialog';
import { setupI18n } from '../util/setupI18n';
@@ -11,7 +12,7 @@ import enMessages from '../../_locales/en/messages.json';
export default {
title: 'Components/ProgressDialog',
-};
+} satisfies Meta