Skip to content

Commit

Permalink
feat(flat-components): add appearance picker component (#1373)
Browse files Browse the repository at this point in the history
* feat(flat-components): add theme picker component

* feat(flat-components): add appearance picker component
  • Loading branch information
Cheerego7 authored Feb 18, 2022
1 parent f5626d4 commit 91c4827
Show file tree
Hide file tree
Showing 13 changed files with 183 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import "./style.less";

import { Checkbox, Radio } from "antd";
import type { CheckboxChangeEvent } from "antd/lib/checkbox";
import React, { useEffect, useState } from "react";
import { Checkbox, Radio, RadioChangeEvent } from "antd";
import React, { useContext, useEffect, useState } from "react";
import { UserSettingLayoutContainer } from "../UserSettingLayoutContainer";
import { ipcSyncByApp, ipcAsyncByApp } from "../../../utils/ipc";
import { useTranslation } from "react-i18next";
import { AppearancePicker, FlatPrefersColorScheme } from "flat-components";
import { ConfigStoreContext } from "../../../components/StoreProvider";

enum SelectLanguage {
Chinese,
Expand All @@ -15,6 +16,7 @@ enum SelectLanguage {
export const GeneralSettingPage = (): React.ReactElement => {
const { t, i18n } = useTranslation();
const [openAtLogin, setOpenAtLogin] = useState(false);
const configStore = useContext(ConfigStoreContext);

useEffect(() => {
ipcSyncByApp("get-open-at-login")
Expand All @@ -33,11 +35,16 @@ export const GeneralSettingPage = (): React.ReactElement => {
});
};

async function changeLanguage(event: CheckboxChangeEvent): Promise<void> {
async function changeLanguage(event: RadioChangeEvent): Promise<void> {
const language: SelectLanguage = event.target.value;
await i18n.changeLanguage(language === SelectLanguage.Chinese ? "zh-CN" : "en");
}

const changeAppearance = (event: RadioChangeEvent): void => {
const prefersColorScheme: FlatPrefersColorScheme = event.target.value;
configStore.updatePrefersColorScheme(prefersColorScheme);
};

return (
<UserSettingLayoutContainer>
<div className="general-setting-container">
Expand All @@ -60,6 +67,13 @@ export const GeneralSettingPage = (): React.ReactElement => {
<Radio value={SelectLanguage.English}>English</Radio>
</Radio.Group>
</div>
<div className="general-setting-appearance-picker-container">
<span>{t("flat-appearance-setting")}</span>
<AppearancePicker
changeAppearance={changeAppearance}
defaultValue={configStore.prefersColorScheme}
/>
</div>
</div>
</UserSettingLayoutContainer>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,11 @@
}
}
}

.general-setting-appearance-picker-container{
> span {
display: block;
padding-top: 8px;
padding-bottom: 3px;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from "react";
import { Meta, Story } from "@storybook/react";
import { BrowserRouter as Router } from "react-router-dom";
import { AppearancePicker, AppearancePickerProps } from ".";

const storyMeta: Meta = {
title: "SettingPage/AppearancePicker",
component: AppearancePicker,
};

export default storyMeta;

export const Overview: Story<AppearancePickerProps> = args => (
<Router>
<div className="vh-75 mw8-ns">
<AppearancePicker {...args} />
</div>
</Router>
);
Overview.args = {
defaultValue: "light",
};
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import lightSVG from "./icons/light.svg";
import darkSVG from "./icons/dark.svg";
import autoSVG from "./icons/auto.svg";
import "./style.less";

import React from "react";
import { useTranslation } from "react-i18next";
import { Radio, RadioChangeEvent } from "antd";
import { FlatPrefersColorScheme } from "../../FlatThemeProvider";

export interface AppearancePickerProps {
defaultValue: FlatPrefersColorScheme;
changeAppearance: (event: RadioChangeEvent) => void;
}

export const AppearancePicker: React.FC<AppearancePickerProps> = ({
defaultValue,
changeAppearance,
}) => {
const { t } = useTranslation();
return (
<div className="appearance-picker-container">
<Radio.Group defaultValue={defaultValue} onChange={changeAppearance}>
<Radio value={"light"}>
<div className="appearance-picker-option">
<img src={lightSVG} />
<span>{t("flat-appearance-light")}</span>
</div>
</Radio>
<Radio value={"dark"}>
<div className="appearance-picker-option">
<img src={darkSVG} />
<span>{t("flat-appearance-dark")}</span>
</div>
</Radio>
<Radio value={"auto"}>
<div className="appearance-picker-option">
<img src={autoSVG} />
<span>{t("flat-appearance-auto")}</span>
</div>
</Radio>
</Radio.Group>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
.appearance-picker-container {
> .ant-radio-group {
> .ant-radio-wrapper {
border-radius: 4px;
padding: 4px;

> span {
padding: 0;
}

.ant-radio {
margin-top: 9px;
}

&::after {
content: "";
top: 0;
left: 0;
width: 100%;
height: 75%;
position: absolute;
border-radius: 4px;
transition: border-color 0.4s;
}

&.ant-radio-wrapper-checked,
&:hover,
&:active {
&::after {
border: 2px solid var(--primary);
}
}
}

.ant-radio {
display: none;
}
}
}

.appearance-picker-option {
display: flex;
flex-direction: column;
align-items: center;

> span {
padding-top: 8px;
}
}
1 change: 1 addition & 0 deletions packages/flat-components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ export * from "./components/DeviceTestPage";
export * from "./components/ClassroomPage/CloudRecordBtn";
export * from "./components/ClassroomPage/Timer";
export * from "./components/FlatIcons";
export * from "./components/SettingPage/AppearancePicker";
10 changes: 7 additions & 3 deletions packages/flat-i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@
"repeat-frequency": "Every {{week}}",
"schedule-room-detail": "Ends at {{time}} with {{length}} rooms",
"schedule-room-type": "Room type: {{type}}",
"view-all-rooms-in-periodic-rooms": "View all {{count}} rooms",
"view-all-rooms-in-periodic-rooms": "View all ({{count}}) rooms",
"ending": "Ending...",
"follow-your-perspective-tips": "Other users will follow your perspective",
"interactive-mode": "Currently in interactive mode",
Expand Down Expand Up @@ -398,6 +398,10 @@
"exit": "Exit",
"side-panel": {
"hide": "Hide",
"show": "Show"
}
"show": "Show"
},
"flat-appearance-light": "Light",
"flat-appearance-dark": "Dark",
"flat-appearance-auto": "Auto",
"flat-appearance-setting": "Appearance"
}
10 changes: 7 additions & 3 deletions packages/flat-i18n/locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@
"schedule-room-default-title": "{{name}} 预定的房间",
"delete-room-records": "删除房间记录",
"delete-room-records-tips": "确定删除当前房间记录?",
"view-all-rooms-in-periodic-rooms": "查看全部 {{count}} 场房间",
"view-all-rooms-in-periodic-rooms": "查看全部 ({{count}}) 场房间",
"repeat-frequency": "每{{week}}",
"schedule-room-type": "房间类型:{{type}}",
"schedule-room-detail": "结束于 {{time}} ,共 {{length}} 个房间",
Expand Down Expand Up @@ -398,6 +398,10 @@
"exit": "退出",
"side-panel": {
"hide": "折叠",
"show": "展开"
}
"show": "展开"
},
"flat-appearance-light": "浅色",
"flat-appearance-dark": "深色",
"flat-appearance-auto": "自动",
"flat-appearance-setting": "外观"
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@
}
}

.general-setting-appearance-picker-container{
> span {
display: block;
padding-top: 8px;
padding-bottom: 3px;
}
}

.general-setting-device-test-box {
padding-top: 12px;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import "./index.less";

import { FlatPrefersColorScheme, AppearancePicker } from "flat-components";
import { Checkbox, Radio } from "antd";
import React, { useContext } from "react";
import { UserSettingLayoutContainer } from "../UserSettingLayoutContainer";
import { useTranslation } from "react-i18next";
import type { CheckboxChangeEvent } from "antd/lib/checkbox";
import { GlobalStoreContext } from "../../../components/StoreProvider";
import { ConfigStoreContext, GlobalStoreContext } from "../../../components/StoreProvider";

enum SelectLanguage {
Chinese,
Expand All @@ -14,6 +15,7 @@ enum SelectLanguage {

export const GeneralSettingPage = (): React.ReactElement => {
const globalStore = useContext(GlobalStoreContext);
const configStore = useContext(ConfigStoreContext);

const { t, i18n } = useTranslation();

Expand All @@ -22,6 +24,11 @@ export const GeneralSettingPage = (): React.ReactElement => {
void i18n.changeLanguage(language === SelectLanguage.Chinese ? "zh-CN" : "en");
}

const changeAppearance = (event: CheckboxChangeEvent): void => {
const prefersColorScheme: FlatPrefersColorScheme = event.target.value;
configStore.updatePrefersColorScheme(prefersColorScheme);
};

return (
<UserSettingLayoutContainer>
<div className="general-setting-container">
Expand All @@ -39,6 +46,13 @@ export const GeneralSettingPage = (): React.ReactElement => {
<Radio value={SelectLanguage.English}>English</Radio>
</Radio.Group>
</div>
<div className="general-setting-appearance-picker-container">
<span>{t("flat-appearance-setting")}</span>
<AppearancePicker
changeAppearance={changeAppearance}
defaultValue={configStore.prefersColorScheme}
/>
</div>
<div className="general-setting-device-test-box">
<div className="general-setting-checkbox-title">{t("device-test-option")}</div>
<Checkbox
Expand Down

0 comments on commit 91c4827

Please sign in to comment.