summaryrefslogtreecommitdiffstats
path: root/browser/components/storybook/.storybook/addon-fluent
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/storybook/.storybook/addon-fluent')
-rw-r--r--browser/components/storybook/.storybook/addon-fluent/FluentPanel.jsx110
-rw-r--r--browser/components/storybook/.storybook/addon-fluent/FluentPanel.mjs121
-rw-r--r--browser/components/storybook/.storybook/addon-fluent/PseudoLocalizationButton.jsx (renamed from browser/components/storybook/.storybook/addon-fluent/PseudoLocalizationButton.mjs)2
-rw-r--r--browser/components/storybook/.storybook/addon-fluent/fluent-panel.css64
-rw-r--r--browser/components/storybook/.storybook/addon-fluent/preset/manager.mjs13
-rw-r--r--browser/components/storybook/.storybook/addon-fluent/withPseudoLocalization.mjs11
6 files changed, 147 insertions, 174 deletions
diff --git a/browser/components/storybook/.storybook/addon-fluent/FluentPanel.jsx b/browser/components/storybook/.storybook/addon-fluent/FluentPanel.jsx
new file mode 100644
index 0000000000..71714d8d25
--- /dev/null
+++ b/browser/components/storybook/.storybook/addon-fluent/FluentPanel.jsx
@@ -0,0 +1,110 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// eslint-disable-next-line no-unused-vars
+import React, { useEffect, useState } from "react";
+import { addons, useGlobals, useStorybookApi } from "@storybook/manager-api";
+// eslint-disable-next-line no-unused-vars
+import { AddonPanel, Table, Form } from "@storybook/components";
+import { FLUENT_CHANGED, FLUENT_SET_STRINGS } from "./constants.mjs";
+// eslint-disable-next-line import/no-unassigned-import
+import "./fluent-panel.css";
+
+export const FluentPanel = ({ active }) => {
+ const [fileName, setFileName] = useState(null);
+ const [strings, setStrings] = useState([]);
+ const [{ fluentStrings }, updateGlobals] = useGlobals();
+ const channel = addons.getChannel();
+ const api = useStorybookApi();
+
+ useEffect(() => {
+ channel.on(FLUENT_CHANGED, handleFluentChanged);
+ return () => {
+ channel.off(FLUENT_CHANGED, handleFluentChanged);
+ };
+ }, [channel]);
+
+ const handleFluentChanged = (nextStrings, fluentFile) => {
+ setFileName(fluentFile);
+ setStrings(nextStrings);
+ };
+
+ const onInput = e => {
+ let nextStrings = [];
+ for (let [key, value] of strings) {
+ if (key == e.target.name) {
+ let stringValue = e.target.value;
+ if (stringValue.startsWith(".")) {
+ stringValue = "\n" + stringValue;
+ }
+ nextStrings.push([key, stringValue]);
+ } else {
+ nextStrings.push([key, value]);
+ }
+ }
+ let stringified = nextStrings
+ .map(([key, value]) => `${key} = ${value}`)
+ .join("\n");
+ channel.emit(FLUENT_SET_STRINGS, stringified);
+ updateGlobals({
+ fluentStrings: { ...fluentStrings, [fileName]: nextStrings },
+ });
+ return { fileName, strings };
+ };
+
+ const addonTemplate = () => {
+ if (strings.length === 0) {
+ return (
+ <AddonPanel active={!!active} api={api}>
+ <div className="addon-panel-body">
+ <div className="addon-panel-message">
+ This story is not configured to use Fluent.
+ </div>
+ </div>
+ </AddonPanel>
+ );
+ }
+
+ return (
+ <AddonPanel active={!!active} api={api}>
+ <div className="addon-panel-body">
+ <Table aria-hidden="false" className="addon-panel-table">
+ <thead className="addon-panel-table-head">
+ <tr>
+ <th>
+ <span>Identifier</span>
+ </th>
+ <th>
+ <span>String</span>
+ </th>
+ </tr>
+ </thead>
+ <tbody className="addon-panel-table-body">
+ {strings.map(([identifier, value]) => (
+ <tr key={identifier}>
+ <td>
+ <span>{identifier}</span>
+ </td>
+ <td>
+ <Form.Textarea
+ name={identifier}
+ onInput={onInput}
+ defaultValue={value
+ .trim()
+ .split("\n")
+ .map(s => s.trim())
+ .join("\n")}
+ ></Form.Textarea>
+ </td>
+ </tr>
+ ))}
+ </tbody>
+ </Table>
+ </div>
+ </AddonPanel>
+ );
+ };
+
+ return addonTemplate();
+};
diff --git a/browser/components/storybook/.storybook/addon-fluent/FluentPanel.mjs b/browser/components/storybook/.storybook/addon-fluent/FluentPanel.mjs
deleted file mode 100644
index 692ff73737..0000000000
--- a/browser/components/storybook/.storybook/addon-fluent/FluentPanel.mjs
+++ /dev/null
@@ -1,121 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-import React from "react";
-import { addons } from "@storybook/addons";
-// eslint-disable-next-line no-unused-vars
-import { AddonPanel } from "@storybook/components";
-import { FLUENT_CHANGED, FLUENT_SET_STRINGS } from "./constants.mjs";
-// eslint-disable-next-line import/no-unassigned-import
-import "./fluent-panel.css";
-
-export class FluentPanel extends React.Component {
- constructor(props) {
- super(props);
- this.channel = addons.getChannel();
- this.state = {
- name: null,
- strings: [],
- };
- }
-
- componentDidMount() {
- const { api } = this.props;
- api.on(FLUENT_CHANGED, this.handleFluentChanged);
- }
-
- componentWillUnmount() {
- const { api } = this.props;
- api.off(FLUENT_CHANGED, this.handleFluentChanged);
- }
-
- handleFluentChanged = strings => {
- let storyData = this.props.api.getCurrentStoryData();
- let fileName = `${storyData.component}.ftl`;
- this.setState(state => ({ ...state, strings, fileName }));
- };
-
- onInput = e => {
- this.setState(state => {
- let strings = [];
- for (let [key, value] of state.strings) {
- if (key == e.target.name) {
- let stringValue = e.target.value;
- if (stringValue.startsWith(".")) {
- stringValue = "\n" + stringValue;
- }
- strings.push([key, stringValue]);
- } else {
- strings.push([key, value]);
- }
- }
- let stringified = strings
- .map(([key, value]) => `${key} = ${value}`)
- .join("\n");
- this.channel.emit(FLUENT_SET_STRINGS, stringified);
- const { fluentStrings } = this.props.api.getGlobals();
- this.props.api.updateGlobals({
- fluentStrings: { ...fluentStrings, [state.fileName]: strings },
- });
- return { ...state, strings };
- });
- };
-
- render() {
- const { api, active } = this.props;
- const { strings } = this.state;
- if (strings.length === 0) {
- return (
- <AddonPanel active={!!active} api={api}>
- <div className="addon-panel-body">
- <div className="addon-panel-message">
- This story is not configured to use Fluent.
- </div>
- </div>
- </AddonPanel>
- );
- }
-
- return (
- <AddonPanel active={!!active} api={api}>
- <div className="addon-panel-body">
- <table aria-hidden="false" className="addon-panel-table">
- <thead className="addon-panel-table-head">
- <tr>
- <th>
- <span>Identifier</span>
- </th>
- <th>
- <span>String</span>
- </th>
- </tr>
- </thead>
- <tbody className="addon-panel-table-body">
- {strings.map(([identifier, value]) => (
- <tr key={identifier}>
- <td>
- <span>{identifier}</span>
- </td>
- <td>
- <label>
- <textarea
- name={identifier}
- onInput={this.onInput}
- defaultValue={value
- .trim()
- .split("\n")
- .map(s => s.trim())
- .join("\n")}
- ></textarea>
- </label>
- </td>
- </tr>
- ))}
- </tbody>
- </table>
- </div>
- </AddonPanel>
- );
- }
-}
diff --git a/browser/components/storybook/.storybook/addon-fluent/PseudoLocalizationButton.mjs b/browser/components/storybook/.storybook/addon-fluent/PseudoLocalizationButton.jsx
index d60112d224..9af7e5ad2b 100644
--- a/browser/components/storybook/.storybook/addon-fluent/PseudoLocalizationButton.mjs
+++ b/browser/components/storybook/.storybook/addon-fluent/PseudoLocalizationButton.jsx
@@ -4,7 +4,7 @@
// eslint-disable-next-line no-unused-vars
import React from "react";
-import { useGlobals } from "@storybook/api";
+import { useGlobals } from "@storybook/manager-api";
import {
// eslint-disable-next-line no-unused-vars
Icons,
diff --git a/browser/components/storybook/.storybook/addon-fluent/fluent-panel.css b/browser/components/storybook/.storybook/addon-fluent/fluent-panel.css
index 75f4562820..cb6dd9b6f2 100644
--- a/browser/components/storybook/.storybook/addon-fluent/fluent-panel.css
+++ b/browser/components/storybook/.storybook/addon-fluent/fluent-panel.css
@@ -15,69 +15,59 @@
font-size: 13px;
}
-.addon-panel-table {
- border-collapse: collapse;
+table.addon-panel-table {
border-spacing: 0;
- color: #333333;
- font-size: 13px;
- line-height: 20px;
text-align: left;
width: 100%;
margin: 0;
}
-.addon-panel-table-head {
- color: rgba(51,51,51,0.75);
+table.addon-panel-table thead.addon-panel-table-head th {
+ border: none;
+ color: rgba(46, 52, 56, 0.75);
}
-.addon-panel-table-head th {
- padding: 10px 15px;
- border: none;
- vertical-align: top;
+@media (prefers-color-scheme: dark) {
+ table.addon-panel-table thead.addon-panel-table-head th {
+ color: rgba(201, 205, 207, 0.55)
+ }
+}
+
+table.addon-panel-table thead.addon-panel-table-head tr {
+ border-top: none;
}
-.addon-panel-table-head th:first-of-type, .addon-panel-table-body td:first-of-type {
+.addon-panel-table-head th:first-of-type,
+.addon-panel-table-body td:first-of-type {
width: 25%;
padding-left: 20px;
+ border-inline: none;
}
-.addon-panel-table-head th:last-of-type, .addon-panel-table-body td:last-of-type {
+.addon-panel-table-head th:last-of-type,
+.addon-panel-table-body td:last-of-type {
padding-right: 20px;
+ border-inline-start: none;
}
-.addon-panel-table-body {
- border-radius: 4px;
-}
-
-.addon-panel-table-body tr {
+.addon-panel-body {
overflow: hidden;
- border-top: 1px solid #e6e6e6;
}
.addon-panel-table-body td {
- padding: 10px 15px;
font-weight: bold;
+ vertical-align: top;
}
-.addon-panel-table-body label {
- display: flex;
+table.addon-panel-table .addon-panel-table-body tr:nth-of-type(2n) {
+ background-color: unset;
+}
+
+.addon-panel-table-body tr:last-of-type td {
+ border-bottom: none;
}
.addon-panel-table-body textarea {
height: fit-content;
- appearance: none;
- border: none;
- box-sizing: inherit;
- display: block;
- margin: 0;
- background-color: rgb(255, 255, 255);
- padding: 6px 10px;
- color: #333333;
- box-shadow: rgba(0,0,0,.1) 0 0 0 1px inset;
- border-radius: 4px;
- line-height: 20px;
- flex: 1;
- text-align: left;
- overflow: visible;
- max-height: 400px;
+ width: 100%;
}
diff --git a/browser/components/storybook/.storybook/addon-fluent/preset/manager.mjs b/browser/components/storybook/.storybook/addon-fluent/preset/manager.mjs
index 0f7ff9299b..29b57812bd 100644
--- a/browser/components/storybook/.storybook/addon-fluent/preset/manager.mjs
+++ b/browser/components/storybook/.storybook/addon-fluent/preset/manager.mjs
@@ -4,13 +4,10 @@
/** This file handles registering the Storybook addon */
-// eslint-disable-next-line no-unused-vars
-import React from "react";
-import { addons, types } from "@storybook/addons";
+import { addons, types } from "@storybook/manager-api";
import { ADDON_ID, PANEL_ID, TOOL_ID } from "../constants.mjs";
-import { PseudoLocalizationButton } from "../PseudoLocalizationButton.mjs";
-// eslint-disable-next-line no-unused-vars
-import { FluentPanel } from "../FluentPanel.mjs";
+import { PseudoLocalizationButton } from "../PseudoLocalizationButton.jsx";
+import { FluentPanel } from "../FluentPanel.jsx";
// Register the addon.
addons.register(ADDON_ID, api => {
@@ -27,8 +24,6 @@ addons.register(ADDON_ID, api => {
title: "Fluent",
//👇 Sets the type of UI element in Storybook
type: types.PANEL,
- render: ({ active, key }) => (
- <FluentPanel active={active} api={api} key={key}></FluentPanel>
- ),
+ render: ({ active }) => FluentPanel({ active }),
});
});
diff --git a/browser/components/storybook/.storybook/addon-fluent/withPseudoLocalization.mjs b/browser/components/storybook/.storybook/addon-fluent/withPseudoLocalization.mjs
index 9d6c62af38..74fd67a6cd 100644
--- a/browser/components/storybook/.storybook/addon-fluent/withPseudoLocalization.mjs
+++ b/browser/components/storybook/.storybook/addon-fluent/withPseudoLocalization.mjs
@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-import { useEffect, useGlobals, addons } from "@storybook/addons";
+import { useEffect, useGlobals, useChannel } from "@storybook/preview-api";
import {
DIRECTIONS,
DIRECTION_BY_STRATEGY,
@@ -25,11 +25,11 @@ export const withPseudoLocalization = (StoryFn, context) => {
const [{ pseudoStrategy }] = useGlobals();
const direction = DIRECTION_BY_STRATEGY[pseudoStrategy] || DIRECTIONS.ltr;
const isInDocs = context.viewMode === "docs";
- const channel = addons.getChannel();
+ const emit = useChannel({});
useEffect(() => {
if (pseudoStrategy) {
- channel.emit(UPDATE_STRATEGY_EVENT, pseudoStrategy);
+ emit(UPDATE_STRATEGY_EVENT, pseudoStrategy);
}
}, [pseudoStrategy]);
@@ -56,8 +56,7 @@ export const withPseudoLocalization = (StoryFn, context) => {
*/
export const withFluentStrings = (StoryFn, context) => {
const [{ fluentStrings }, updateGlobals] = useGlobals();
- const channel = addons.getChannel();
-
+ const emit = useChannel({});
const fileName = context.component + ".ftl";
let strings = [];
@@ -83,7 +82,7 @@ export const withFluentStrings = (StoryFn, context) => {
}
}
- channel.emit(FLUENT_CHANGED, strings);
+ emit(FLUENT_CHANGED, strings, fileName);
return StoryFn();
};