adjust colors to movie-web

This commit is contained in:
Jorrin
2024-03-08 21:53:03 +01:00
parent 7e035e823a
commit ad2c84950a
29 changed files with 1537 additions and 167 deletions

View File

@@ -4,7 +4,7 @@ import * as Haptics from "expo-haptics";
import { Tabs } from "expo-router";
import * as ScreenOrientation from "expo-screen-orientation";
import Colors from "@movie-web/tailwind-config/colors";
import { defaultTheme } from "@movie-web/tailwind-config/themes";
import { MovieWebSvg } from "~/components/Icon";
import SvgTabBarIcon from "~/components/SvgTabBarIcon";
@@ -19,7 +19,7 @@ export default function TabLayout() {
<SearchTabContext.Provider value={{ focusSearchInputRef }}>
<Tabs
sceneContainerStyle={{
backgroundColor: Colors.background,
backgroundColor: defaultTheme.extend.colors.background.main,
}}
screenListeners={({ route }) => ({
tabPress: () => {
@@ -38,9 +38,9 @@ export default function TabLayout() {
})}
screenOptions={{
headerShown: false,
tabBarActiveTintColor: Colors.primary[100],
tabBarActiveTintColor: defaultTheme.extend.colors.tabBar.active,
tabBarStyle: {
backgroundColor: Colors.secondary[700],
backgroundColor: defaultTheme.extend.colors.tabBar.background,
borderTopColor: "transparent",
borderTopRightRadius: 20,
borderTopLeftRadius: 20,

View File

@@ -12,10 +12,10 @@ import {
} from "@react-navigation/native";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import Colors from "@movie-web/tailwind-config/colors";
import "../styles/global.css";
import { defaultTheme } from "@movie-web/tailwind-config/themes";
export {
// Catch any errors thrown by the Layout component.
ErrorBoundary,
@@ -83,7 +83,7 @@ function RootLayoutNav() {
presentation: "card",
headerShown: false,
contentStyle: {
backgroundColor: Colors.background,
backgroundColor: defaultTheme.extend.colors.background.main,
},
}}
>

View File

@@ -2,7 +2,7 @@ import React from "react";
import { Text, View } from "react-native";
import { Bar as ProgressBar } from "react-native-progress";
import colors from "@movie-web/tailwind-config/colors";
import { defaultTheme } from "@movie-web/tailwind-config/themes";
export interface DownloadItemProps {
filename: string;
@@ -38,8 +38,8 @@ export const DownloadItem: React.FC<DownloadItemProps> = ({
<ProgressBar
progress={progress}
width={null}
color={colors.primary[400]}
unfilledColor={colors.gray[200]}
color={defaultTheme.extend.colors.download.progressFilled}
unfilledColor={defaultTheme.extend.colors.download.progress}
borderWidth={0}
height={10}
borderRadius={5}

View File

@@ -1,6 +1,6 @@
import React from "react";
import Colors from "@movie-web/tailwind-config/colors";
import { defaultTheme } from "@movie-web/tailwind-config/themes";
interface SvgTabBarIconProps {
focused?: boolean;
@@ -11,7 +11,9 @@ export default function SvgTabBarIcon({
focused,
children,
}: SvgTabBarIconProps) {
const fillColor = focused ? Colors.primary[300] : Colors.secondary[300];
const fillColor = focused
? defaultTheme.extend.colors.tabBar.active
: defaultTheme.extend.colors.tabBar.inactive;
if (React.isValidElement(children)) {
return React.cloneElement(children, { fillColor } as React.Attributes);

View File

@@ -1,17 +1,14 @@
import { FontAwesome } from "@expo/vector-icons";
import Colors from "@movie-web/tailwind-config/colors";
import { defaultTheme } from "@movie-web/tailwind-config/themes";
type Props = {
focused?: boolean;
} & React.ComponentProps<typeof FontAwesome>;
export default function TabBarIcon({ focused, ...rest }: Props) {
return (
<FontAwesome
color={focused ? Colors.primary[300] : Colors.secondary[300]}
size={24}
{...rest}
/>
);
const color = focused
? defaultTheme.extend.colors.tabBar.active
: defaultTheme.extend.colors.tabBar.inactive;
return <FontAwesome color={color} size={24} {...rest} />;
}

View File

@@ -3,7 +3,7 @@ import { Pressable, ScrollView, View } from "react-native";
import Modal from "react-native-modal";
import { MaterialCommunityIcons } from "@expo/vector-icons";
import colors from "@movie-web/tailwind-config/colors";
import { defaultTheme } from "@movie-web/tailwind-config/themes";
import { useAudioTrack } from "~/hooks/player/useAudioTrack";
import { useBoolean } from "~/hooks/useBoolean";
@@ -62,7 +62,7 @@ export const AudioTrackSelector = () => {
<MaterialCommunityIcons
name="volume-high"
size={24}
color={colors.primary[300]}
color={defaultTheme.extend.colors.buttons.primary}
/>
}
/>
@@ -97,7 +97,7 @@ export const AudioTrackSelector = () => {
<MaterialCommunityIcons
name="check-circle"
size={24}
color={colors.primary[300]}
color={defaultTheme.extend.colors.buttons.primary}
/>
)}
</Pressable>

View File

@@ -6,7 +6,7 @@ import { MaterialCommunityIcons } from "@expo/vector-icons";
import { parse } from "subsrt-ts";
import type { Stream } from "@movie-web/provider-utils";
import colors from "@movie-web/tailwind-config/colors";
import { defaultTheme } from "@movie-web/tailwind-config/themes";
import { useBoolean } from "~/hooks/useBoolean";
import { useCaptionsStore } from "~/stores/captions";
@@ -59,7 +59,7 @@ export const CaptionsSelector = () => {
<MaterialCommunityIcons
name="subtitles"
size={24}
color={colors.primary[300]}
color={defaultTheme.extend.colors.buttons.primary}
/>
}
/>
@@ -90,7 +90,7 @@ export const CaptionsSelector = () => {
<MaterialCommunityIcons
name="download"
size={24}
color={colors.primary[300]}
color={defaultTheme.extend.colors.buttons.primary}
/>
</Pressable>
))}

View File

@@ -2,7 +2,7 @@ import { Pressable, ScrollView, View } from "react-native";
import Modal from "react-native-modal";
import { MaterialCommunityIcons } from "@expo/vector-icons";
import colors from "@movie-web/tailwind-config/colors";
import { defaultTheme } from "@movie-web/tailwind-config/themes";
import { usePlaybackSpeed } from "~/hooks/player/usePlaybackSpeed";
import { useBoolean } from "~/hooks/useBoolean";
@@ -27,7 +27,7 @@ export const PlaybackSpeedSelector = () => {
<MaterialCommunityIcons
name="speedometer"
size={24}
color={colors.primary[300]}
color={defaultTheme.extend.colors.buttons.primary}
/>
}
/>
@@ -59,7 +59,7 @@ export const PlaybackSpeedSelector = () => {
<MaterialCommunityIcons
name="check-circle"
size={24}
color={colors.primary[300]}
color={defaultTheme.extend.colors.buttons.primary}
/>
)}
</Pressable>

View File

@@ -18,6 +18,7 @@ import { fetchMediaDetails, fetchSeasonDetails } from "@movie-web/tmdb";
import type { ItemData } from "../item/item";
import type { AudioTrack } from "./AudioTrackSelector";
import { constructFullUrl } from "~/lib/url";
import { PlayerStatus } from "~/stores/player/slices/interface";
import { usePlayerStore } from "~/stores/player/store";
import { Text } from "../ui/Text";
@@ -64,14 +65,16 @@ export const ScraperProcess = ({ data }: ScraperProcessProps) => {
setCheckedSource(event);
setScrapeStatus({ status: ScrapeStatus.LOADING, progress: 10 });
} else if (isUpdateEvent(event)) {
console.log(event.status);
switch (event.status) {
case ScrapeStatus.SUCCESS:
case "success":
setScrapeStatus({ status: ScrapeStatus.SUCCESS, progress: 100 });
break;
case ScrapeStatus.ERROR as string:
case "failure":
setScrapeStatus({ status: ScrapeStatus.ERROR, progress: 0 });
break;
case ScrapeStatus.LOADING as string:
case "pending":
case "notfound":
}
setCheckedSource(event.id);
} else if (isInitEvent(event) || isDiscoverEmbedsEvent(event)) {
@@ -131,7 +134,7 @@ export const ScraperProcess = ({ data }: ScraperProcessProps) => {
const streamResult = await getVideoStream({
media: scrapeMedia,
events: {
// init: handleEvent,
init: handleEvent,
update: handleEvent,
discoverEmbeds: handleEvent,
start: handleEvent,
@@ -151,27 +154,16 @@ export const ScraperProcess = ({ data }: ScraperProcessProps) => {
if (tracks) setHlsTracks(tracks);
const constructFullUrl = (playlistUrl: string, uri: string) => {
const baseUrl = playlistUrl.substring(
0,
playlistUrl.lastIndexOf("/") + 1,
);
return uri.startsWith("http://") || uri.startsWith("https://")
? uri
: baseUrl + uri;
};
if (tracks?.audio.length) {
const audioTracks: AudioTrack[] = tracks.audio.map((track) => ({
uri: constructFullUrl(
(streamResult.stream as HlsBasedStream).playlist,
track.uri,
),
name: (track.properties[0]?.attributes.name as string) ?? "Unknown",
name: track.properties[0]?.attributes.name?.toString() ?? "Unknown",
language:
(track.properties[0]?.attributes.language as string) ?? "Unknown",
active:
(track.properties[0]?.attributes.default as boolean) ?? false,
track.properties[0]?.attributes.language?.toString() ?? "Unknown",
active: Boolean(track.properties[0]?.attributes.default) ?? false,
}));
const uniqueTracks = new Set(audioTracks.map((t) => t.language));

View File

@@ -9,7 +9,7 @@ import Modal from "react-native-modal";
import { Ionicons, MaterialCommunityIcons } from "@expo/vector-icons";
import { useQuery } from "@tanstack/react-query";
import colors from "@movie-web/tailwind-config/colors";
import { defaultTheme } from "@movie-web/tailwind-config/themes";
import { fetchMediaDetails, fetchSeasonDetails } from "@movie-web/tmdb";
import { useBoolean } from "~/hooks/useBoolean";
@@ -45,7 +45,10 @@ const EpisodeSelector = ({
<>
{isLoading && (
<View className="flex-1 items-center justify-center">
<ActivityIndicator size="large" color={colors.primary[300]} />
<ActivityIndicator
size="large"
color={defaultTheme.extend.colors.buttons.primary}
/>
</View>
)}
{data && (
@@ -120,7 +123,7 @@ export const SeasonSelector = () => {
<MaterialCommunityIcons
name="audio-video"
size={24}
color={colors.primary[300]}
color={defaultTheme.extend.colors.buttons.primary}
/>
}
/>
@@ -140,7 +143,10 @@ export const SeasonSelector = () => {
<>
{isLoading && (
<View className="flex-1 items-center justify-center">
<ActivityIndicator size="large" color={colors.primary[300]} />
<ActivityIndicator
size="large"
color={defaultTheme.extend.colors.buttons.primary}
/>
</View>
)}
{data && (

View File

@@ -4,7 +4,7 @@ import Modal from "react-native-modal";
import { Ionicons, MaterialCommunityIcons } from "@expo/vector-icons";
import { getBuiltinSources, providers } from "@movie-web/provider-utils";
import colors from "@movie-web/tailwind-config/colors";
import { defaultTheme } from "@movie-web/tailwind-config/themes";
import {
useEmbedScrape,
@@ -55,14 +55,14 @@ const SourceItem = ({
<MaterialCommunityIcons
name="check-circle"
size={24}
color={colors.primary[300]}
color={defaultTheme.extend.colors.buttons.primary}
/>
)}
{isError && (
<MaterialCommunityIcons
name="alert-circle"
size={24}
color={colors.red[500]}
color={defaultTheme.extend.colors.video.context.error}
/>
)}
{isPending && <ActivityIndicator size="small" color="#0000ff" />}
@@ -141,7 +141,7 @@ export const SourceSelector = () => {
<MaterialCommunityIcons
name="video"
size={24}
color={colors.primary[300]}
color={defaultTheme.extend.colors.buttons.primary}
/>
}
/>

View File

@@ -17,7 +17,7 @@ import Animated, {
useSharedValue,
} from "react-native-reanimated";
import colors from "@movie-web/tailwind-config/colors";
import { defaultTheme } from "@movie-web/tailwind-config/themes";
import { usePlayerStore } from "~/stores/player/store";
@@ -132,7 +132,7 @@ const VideoSlider = ({ onSlidingComplete }: VideoSliderProps) => {
{
height: trackSize_,
borderRadius: trackSize_,
backgroundColor: colors.secondary[700],
backgroundColor: defaultTheme.extend.colors.video.context.slider,
width,
},
]}
@@ -142,7 +142,8 @@ const VideoSlider = ({ onSlidingComplete }: VideoSliderProps) => {
{
position: "absolute",
height: trackSize_,
backgroundColor: colors.primary[300],
backgroundColor:
defaultTheme.extend.colors.video.context.sliderFilled,
borderRadius: trackSize_ / 2,
},
progressStyle,
@@ -160,7 +161,8 @@ const VideoSlider = ({ onSlidingComplete }: VideoSliderProps) => {
height: knobSize_,
width: knobSize_,
borderRadius: knobSize_ / 2,
backgroundColor: colors.primary[300],
backgroundColor:
defaultTheme.extend.colors.video.context.sliderFilled,
},
scrollTranslationStyle,
]}

View File

@@ -2,7 +2,7 @@ import { useContext, useEffect, useRef, useState } from "react";
import { TextInput, View } from "react-native";
import { FontAwesome5 } from "@expo/vector-icons";
import Colors from "@movie-web/tailwind-config/colors";
import { defaultTheme } from "@movie-web/tailwind-config/themes";
import SearchTabContext from "./SearchTabContext";
@@ -30,14 +30,18 @@ export function SearchBar({
return (
<View className="mb-6 mt-4 flex-row items-center rounded-full border border-primary-400 bg-black focus-within:border-primary-300">
<View className="ml-1 w-12 items-center justify-center">
<FontAwesome5 name="search" size={18} color={Colors.secondary[200]} />
<FontAwesome5
name="search"
size={18}
color={defaultTheme.extend.colors.search.icon}
/>
</View>
<TextInput
value={keyword}
onChangeText={handleChange}
ref={inputRef}
placeholder="What are you looking for?"
placeholderTextColor={Colors.secondary[200]}
placeholderTextColor={defaultTheme.extend.colors.search.placeholder}
className="w-full rounded-3xl py-3 pr-5 text-white"
/>
</View>

6
apps/expo/src/lib/url.ts Normal file
View File

@@ -0,0 +1,6 @@
export const constructFullUrl = (playlistUrl: string, uri: string) => {
const baseUrl = playlistUrl.substring(0, playlistUrl.lastIndexOf("/") + 1);
return uri.startsWith("http://") || uri.startsWith("https://")
? uri
: baseUrl + uri;
};

View File

@@ -7,8 +7,8 @@ import baseConfig from "@movie-web/tailwind-config/native";
export default {
content: ["./src/**/*.{ts,tsx}"],
presets: [
baseConfig,
nativewind,
baseConfig,
{
theme: {
extend: {

19
pnpm-lock.yaml generated
View File

@@ -345,6 +345,9 @@ importers:
tailwindcss-animate:
specifier: ^1.0.7
version: 1.0.7(tailwindcss@3.4.1)
tailwindcss-themer:
specifier: ^4.0.0
version: 4.0.0(tailwindcss@3.4.1)
devDependencies:
'@movie-web/eslint-config':
specifier: workspace:^0.2.0
@@ -7387,6 +7390,10 @@ packages:
object.values: 1.1.7
dev: false
/just-unique@4.2.0:
resolution: {integrity: sha512-cxQGGUiit6CGUpuuiezY8N4m1wgF4o7127rXEXDFcxeDUFfdV7gSkwA26Fe2wWBiNQq2SZOgN4gSmMxB/StA8Q==}
dev: false
/keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
dependencies:
@@ -10422,6 +10429,18 @@ packages:
tailwindcss: 3.4.1
dev: false
/tailwindcss-themer@4.0.0(tailwindcss@3.4.1):
resolution: {integrity: sha512-kngKDW+z36JtjvaNziX0aesO95r8f5+3FFdANVFDt1uzNHZsL6XLla1YDK6EBAYFqPichoPDbO4lrrTyB+UAbA==}
peerDependencies:
tailwindcss: ^3.1.0
dependencies:
color: 4.2.3
just-unique: 4.2.0
lodash.merge: 4.6.2
lodash.mergewith: 4.6.2
tailwindcss: 3.4.1
dev: false
/tailwindcss@3.4.1:
resolution: {integrity: sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==}
engines: {node: '>=14.0.0'}

View File

@@ -1,12 +0,0 @@
import type { Config } from "tailwindcss";
import colors from "./colors";
export default {
content: ["src/**/*.{ts,tsx}"],
theme: {
extend: {
colors,
},
},
} satisfies Config;

View File

@@ -1,40 +0,0 @@
import {
black,
blue,
gray,
green,
indigo,
pink,
purple,
red,
white,
yellow,
} from "tailwindcss/colors";
export default {
black: black,
white: white,
gray: gray,
red: red,
yellow: yellow,
green: green,
blue: blue,
indigo: indigo,
purple: purple,
pink: pink,
primary: {
100: "#C082FF",
300: "#8D44D6",
400: "#7831BF",
},
secondary: {
50: "#676790",
200: "#3F3F60",
300: "#32324F",
700: "#131322",
},
playerSettings: {
captionBackground: "#161b23",
},
background: "#0a0a12",
};

View File

@@ -1,14 +1,22 @@
import type { Config } from "tailwindcss";
import themer from "tailwindcss-themer";
import base from "./base";
import colors from "./colors";
import { allThemes, defaultTheme, safeThemeList } from "./themes";
export default {
content: base.content,
presets: [base],
theme: {
extend: {
colors,
},
},
content: ["src/**/*.{ts,tsx}"],
safelist: safeThemeList,
plugins: [
themer({
defaultTheme,
themes: [
{
name: "default",
selectors: [".theme-default"],
...defaultTheme,
},
...allThemes,
],
}),
],
} satisfies Config;

View File

@@ -5,8 +5,7 @@
"type": "module",
"exports": {
"./native": "./native.ts",
"./web": "./web.ts",
"./colors": "./colors.ts"
"./themes": "./themes/index.ts"
},
"license": "MIT",
"scripts": {
@@ -19,7 +18,8 @@
"autoprefixer": "^10.4.17",
"postcss": "^8.4.32",
"tailwindcss": "^3.4.0",
"tailwindcss-animate": "^1.0.7"
"tailwindcss-animate": "^1.0.7",
"tailwindcss-themer": "^4.0.0"
},
"devDependencies": {
"@movie-web/eslint-config": "workspace:^0.2.0",

View File

@@ -0,0 +1,11 @@
import teal from "./list/teal";
import blue from "./list/blue";
import red from "./list/red";
import gray from "./list/gray";
export const allThemes = [
teal,
blue,
gray,
red
]

View File

@@ -0,0 +1,352 @@
const tokens = {
black: "#000000",
white: "#FFFFFF",
semantic: {
red: {
c100: "#F46E6E",
c200: "#E44F4F",
c300: "#D74747",
c400: "#B43434",
},
green: {
c100: "#60D26A",
c200: "#40B44B",
c300: "#31A33C",
c400: "#237A2B",
},
silver: {
c100: "#DEDEDE",
c200: "#B6CAD7",
c300: "#8EA3B0",
c400: "#617A8A",
},
yellow: {
c100: "#FFF599",
c200: "#FCEC61",
c300: "#D8C947",
c400: "#AFA349",
},
rose: {
c100: "#DB3D61",
c200: "#8A293B",
c300: "#812435",
c400: "#701B2B",
},
},
blue: {
c50: "#ADADF5",
c100: "#7979CC",
c200: "#5D5DAE",
c300: "#3B3B8C",
c400: "#2A2A71",
c500: "#1F1F50",
c600: "#1B1B41",
c700: "#171736",
c800: "#101020",
c900: "#0B0B13",
},
purple: {
c50: "#D5AAFF",
c100: "#C082FF",
c200: "#A359EC",
c300: "#8D44D6",
c400: "#7831BF",
c500: "#572887",
c600: "#411F64",
c700: "#31184A",
c800: "#221134",
c900: "#160B22",
},
ash: {
c50: "#7F8D9B",
c100: "#5B6B7B",
c200: "#445464",
c300: "#2B3D4E",
c400: "#203242",
c500: "#1C2C3C",
c600: "#172532",
c700: "#131E29",
c800: "#101820",
c900: "#0C1216",
},
shade: {
c50: "#676790",
c100: "#52527A",
c200: "#3F3F60",
c300: "#32324F",
c400: "#272741",
c500: "#1E1E32",
c600: "#171728",
c700: "#131322",
c800: "#0F0F1B",
c900: "#0A0A12",
},
};
export const defaultTheme = {
extend: {
colors: {
themePreview: {
primary: tokens.blue.c200,
secondary: tokens.shade.c50,
ghost: tokens.white,
},
// Branding
pill: {
background: tokens.shade.c300,
backgroundHover: tokens.shade.c200,
highlight: tokens.blue.c200,
activeBackground: tokens.shade.c300,
},
// meta data for the theme itself
global: {
accentA: tokens.blue.c200,
accentB: tokens.blue.c300,
},
// light bar
lightBar: {
light: tokens.blue.c400,
},
// Buttons
buttons: {
toggle: tokens.purple.c300,
toggleDisabled: tokens.ash.c500,
danger: tokens.semantic.rose.c300,
dangerHover: tokens.semantic.rose.c200,
secondary: tokens.ash.c700,
secondaryText: tokens.semantic.silver.c300,
secondaryHover: tokens.ash.c700,
primary: tokens.white,
primaryText: tokens.black,
primaryHover: tokens.semantic.silver.c100,
purple: tokens.purple.c500,
purpleHover: tokens.purple.c400,
cancel: tokens.ash.c500,
cancelHover: tokens.ash.c300,
},
// only used for body colors/textures
background: {
main: tokens.shade.c900,
secondary: tokens.shade.c600,
secondaryHover: tokens.shade.c400,
accentA: tokens.purple.c500,
accentB: tokens.blue.c500,
},
// Modals
modal: {
background: tokens.shade.c800,
},
// typography
type: {
logo: tokens.purple.c100,
emphasis: tokens.white,
text: tokens.shade.c50,
dimmed: tokens.shade.c50,
divider: tokens.ash.c500,
secondary: tokens.ash.c100,
danger: tokens.semantic.red.c100,
success: tokens.semantic.green.c100,
link: tokens.purple.c100,
linkHover: tokens.purple.c50,
},
// search bar
search: {
background: tokens.shade.c500,
hoverBackground: tokens.shade.c600,
focused: tokens.shade.c400,
placeholder: tokens.shade.c100,
icon: tokens.shade.c100,
text: tokens.white,
},
// media cards
mediaCard: {
hoverBackground: tokens.shade.c600,
hoverAccent: tokens.shade.c50,
hoverShadow: tokens.shade.c900,
shadow: tokens.shade.c700,
barColor: tokens.ash.c200,
barFillColor: tokens.purple.c100,
badge: tokens.shade.c700,
badgeText: tokens.ash.c100,
},
// Large card
largeCard: {
background: tokens.shade.c600,
icon: tokens.purple.c400,
},
// Dropdown
dropdown: {
background: tokens.shade.c600,
altBackground: tokens.shade.c700,
hoverBackground: tokens.shade.c500,
highlight: tokens.semantic.yellow.c400,
highlightHover: tokens.semantic.yellow.c200,
text: tokens.shade.c50,
secondary: tokens.shade.c100,
border: tokens.shade.c400,
contentBackground: tokens.shade.c500,
},
// Passphrase
authentication: {
border: tokens.shade.c300,
inputBg: tokens.shade.c600,
inputBgHover: tokens.shade.c500,
wordBackground: tokens.shade.c500,
copyText: tokens.shade.c100,
copyTextHover: tokens.ash.c50,
errorText: tokens.semantic.rose.c100,
},
// Settings page
settings: {
sidebar: {
activeLink: tokens.shade.c600,
badge: tokens.shade.c900,
type: {
secondary: tokens.shade.c200,
inactive: tokens.shade.c50,
icon: tokens.shade.c50,
iconActivated: tokens.purple.c200,
activated: tokens.purple.c50,
},
},
card: {
border: tokens.shade.c400,
background: tokens.shade.c400,
altBackground: tokens.shade.c400,
},
saveBar: {
background: tokens.shade.c800,
},
},
// Utilities
utils: {
divider: tokens.ash.c300,
},
// Onboarding
onboarding: {
bar: tokens.shade.c400,
barFilled: tokens.purple.c300,
divider: tokens.shade.c200,
card: tokens.shade.c800,
cardHover: tokens.shade.c700,
border: tokens.shade.c600,
good: tokens.purple.c100,
best: tokens.semantic.yellow.c100,
link: tokens.purple.c100,
},
// Error page
errors: {
card: tokens.shade.c800,
border: tokens.ash.c500,
type: {
secondary: tokens.ash.c100,
},
},
// About page
about: {
circle: tokens.ash.c500,
circleText: tokens.ash.c50,
},
// About page
editBadge: {
bg: tokens.ash.c500,
bgHover: tokens.ash.c400,
text: tokens.ash.c50,
},
progress: {
background: tokens.ash.c50,
preloaded: tokens.ash.c50,
filled: tokens.purple.c200,
},
// video player
video: {
buttonBackground: tokens.ash.c200,
autoPlay: {
background: tokens.ash.c700,
hover: tokens.ash.c500,
},
scraping: {
card: tokens.shade.c700,
error: tokens.semantic.red.c200,
success: tokens.semantic.green.c200,
loading: tokens.purple.c200,
noresult: tokens.ash.c100,
},
audio: {
set: tokens.purple.c200,
},
context: {
background: tokens.ash.c900,
light: tokens.shade.c50,
border: tokens.ash.c600,
hoverColor: tokens.ash.c600,
buttonFocus: tokens.ash.c500,
flagBg: tokens.ash.c500,
inputBg: tokens.ash.c600,
buttonOverInputHover: tokens.ash.c500,
inputPlaceholder: tokens.ash.c200,
cardBorder: tokens.ash.c700,
slider: tokens.ash.c50,
sliderFilled: tokens.purple.c200,
error: tokens.semantic.red.c200,
buttons: {
list: tokens.ash.c700,
active: tokens.ash.c900,
},
closeHover: tokens.ash.c800,
type: {
main: tokens.semantic.silver.c400,
secondary: tokens.ash.c200,
accent: tokens.purple.c200,
},
},
},
// tabBar
tabBar: {
background: tokens.shade.c700,
active: tokens.purple.c200,
inactive: tokens.shade.c300,
},
// download
download: {
progress: tokens.ash.c50,
progressFilled: tokens.purple.c200,
},
},
},
};

View File

@@ -0,0 +1,9 @@
import { allThemes } from "./all";
export { defaultTheme } from "./default";
export { allThemes } from "./all";
export const safeThemeList = allThemes
.flatMap(v=>v.selectors)
.filter(v=>v.startsWith("."))
.map(v=>v.slice(1)); // remove dot from selector

View File

@@ -0,0 +1,259 @@
import { createTheme } from "../types";
const tokens = {
purple: {
c50: "#aac5ff",
c100: "#82a9ff",
c200: "#4681ff",
c300: "#1a63ff",
c400: "#054eec",
c500: "#083aa7",
c600: "#072c7c",
c700: "#06215d",
c800: "#041741",
c900: "#03102a"
},
shade: {
c50: "#756790",
c100: "#60527a",
c200: "#4a3f60",
c300: "#3c324f",
c400: "#302741",
c500: "#251e32",
c600: "#1d1728",
c700: "#181322",
c800: "#130f1b",
c900: "#0d0a12"
},
ash: {
c50: "#7f859b",
c100: "#5b627b",
c200: "#444b64",
c300: "#2b344e",
c400: "#202842",
c500: "#1c243c",
c600: "#171d32",
c700: "#131829",
c800: "#101420",
c900: "#0c0f16"
},
blue: {
c50: "#adb4f5",
c100: "#7981cc",
c200: "#5d65ae",
c300: "#3b438c",
c400: "#2a3171",
c500: "#1f2450",
c600: "#1b1f41",
c700: "#171b36",
c800: "#101120",
c900: "#0b0c13"
}
};
export default createTheme({
name: "blue",
extend: {
colors: {
themePreview: {
primary: tokens.blue.c200,
secondary: tokens.shade.c50
},
pill: {
background: tokens.shade.c300,
backgroundHover: tokens.shade.c200,
highlight: tokens.blue.c200,
activeBackground: tokens.shade.c300,
},
global: {
accentA: tokens.blue.c200,
accentB: tokens.blue.c300
},
lightBar: {
light: tokens.blue.c400
},
buttons: {
toggle: tokens.purple.c300,
toggleDisabled: tokens.ash.c500,
secondary: tokens.ash.c700,
secondaryHover: tokens.ash.c700,
purple: tokens.purple.c500,
purpleHover: tokens.purple.c400,
cancel: tokens.ash.c500,
cancelHover: tokens.ash.c300
},
background: {
main: tokens.shade.c900,
secondary: tokens.shade.c600,
secondaryHover: tokens.shade.c400,
accentA: tokens.purple.c500,
accentB: tokens.blue.c500
},
modal: {
background: tokens.shade.c800,
},
type: {
logo: tokens.purple.c100,
text: tokens.shade.c50,
dimmed: tokens.shade.c50,
divider: tokens.ash.c500,
secondary: tokens.ash.c100,
link: tokens.purple.c100,
linkHover: tokens.purple.c50
},
search: {
background: tokens.shade.c500,
hoverBackground: tokens.shade.c600,
focused: tokens.shade.c400,
placeholder: tokens.shade.c100,
icon: tokens.shade.c100
},
mediaCard: {
hoverBackground: tokens.shade.c600,
hoverAccent: tokens.shade.c50,
hoverShadow: tokens.shade.c900,
shadow: tokens.shade.c700,
barColor: tokens.ash.c200,
barFillColor: tokens.purple.c100,
badge: tokens.shade.c700,
badgeText: tokens.ash.c100
},
largeCard: {
background: tokens.shade.c600,
icon: tokens.purple.c400
},
dropdown: {
background: tokens.shade.c600,
altBackground: tokens.shade.c700,
hoverBackground: tokens.shade.c500,
text: tokens.shade.c50,
secondary: tokens.shade.c100,
border: tokens.shade.c400,
contentBackground: tokens.shade.c500
},
authentication: {
border: tokens.shade.c300,
inputBg: tokens.shade.c600,
inputBgHover: tokens.shade.c500,
wordBackground: tokens.shade.c500,
copyText: tokens.shade.c100,
copyTextHover: tokens.ash.c50
},
settings: {
sidebar: {
activeLink: tokens.shade.c600,
badge: tokens.shade.c900,
type: {
secondary: tokens.shade.c200,
inactive: tokens.shade.c50,
icon: tokens.shade.c50,
iconActivated: tokens.purple.c200,
activated: tokens.purple.c50
}
},
card: {
border: tokens.shade.c400,
background: tokens.shade.c400,
altBackground: tokens.shade.c400
},
saveBar: {
background: tokens.shade.c800
}
},
utils: {
divider: tokens.ash.c300
},
errors: {
card: tokens.shade.c800,
border: tokens.ash.c500,
type: {
secondary: tokens.ash.c100
}
},
about: {
circle: tokens.ash.c500,
circleText: tokens.ash.c50
},
editBadge: {
bg: tokens.ash.c500,
bgHover: tokens.ash.c400,
text: tokens.ash.c50
},
progress: {
background: tokens.ash.c50,
preloaded: tokens.ash.c50,
filled: tokens.purple.c200
},
video: {
buttonBackground: tokens.ash.c200,
autoPlay: {
background: tokens.ash.c700,
hover: tokens.ash.c500
},
scraping: {
card: tokens.shade.c700,
loading: tokens.purple.c200,
noresult: tokens.ash.c100
},
audio: {
set: tokens.purple.c200
},
context: {
background: tokens.ash.c900,
light: tokens.shade.c50,
border: tokens.ash.c600,
hoverColor: tokens.ash.c600,
buttonFocus: tokens.ash.c500,
flagBg: tokens.ash.c500,
inputBg: tokens.ash.c600,
buttonOverInputHover: tokens.ash.c500,
inputPlaceholder: tokens.ash.c200,
cardBorder: tokens.ash.c700,
slider: tokens.ash.c50,
sliderFilled: tokens.purple.c200,
buttons: {
list: tokens.ash.c700,
active: tokens.ash.c900
},
closeHover: tokens.ash.c800,
type: {
secondary: tokens.ash.c200,
accent: tokens.purple.c200
}
}
}
}
}
});

View File

@@ -0,0 +1,259 @@
import { createTheme } from "../types";
const tokens = {
purple: {
c50: "#aaafff",
c100: "#8288fe",
c200: "#5a62eb",
c300: "#454cd4",
c400: "#333abe",
c500: "#292d86",
c600: "#1f2363",
c700: "#191b4a",
c800: "#111334",
c900: "#0b0d22"
},
shade: {
c50: "#7c7c7c",
c100: "#666666",
c200: "#4f4f4f",
c300: "#404040",
c400: "#343434",
c500: "#282828",
c600: "#202020",
c700: "#1a1a1a",
c800: "#151515",
c900: "#0e0e0e"
},
ash: {
c50: "#8d8d8d",
c100: "#6b6b6b",
c200: "#545454",
c300: "#3c3c3c",
c400: "#313131",
c500: "#2c2c2c",
c600: "#252525",
c700: "#1e1e1e",
c800: "#181818",
c900: "#111111"
},
blue: {
c50: "#ccccd6",
c100: "#a2a2a2",
c200: "#868686",
c300: "#646464",
c400: "#4e4e4e",
c500: "#383838",
c600: "#2e2e2e",
c700: "#272727",
c800: "#181818",
c900: "#0f0f0f"
}
};
export default createTheme({
name: "gray",
extend: {
colors: {
themePreview: {
primary: tokens.blue.c200,
secondary: tokens.shade.c50
},
pill: {
background: tokens.shade.c300,
backgroundHover: tokens.shade.c200,
highlight: tokens.blue.c200,
activeBackground: tokens.shade.c300,
},
global: {
accentA: tokens.blue.c200,
accentB: tokens.blue.c300
},
lightBar: {
light: tokens.blue.c400
},
buttons: {
toggle: tokens.purple.c300,
toggleDisabled: tokens.ash.c500,
secondary: tokens.ash.c700,
secondaryHover: tokens.ash.c700,
purple: tokens.purple.c500,
purpleHover: tokens.purple.c400,
cancel: tokens.ash.c500,
cancelHover: tokens.ash.c300
},
background: {
main: tokens.shade.c900,
secondary: tokens.shade.c600,
secondaryHover: tokens.shade.c400,
accentA: tokens.purple.c500,
accentB: tokens.blue.c500
},
modal: {
background: tokens.shade.c800,
},
type: {
logo: tokens.purple.c100,
text: tokens.shade.c50,
dimmed: tokens.shade.c50,
divider: tokens.ash.c500,
secondary: tokens.ash.c100,
link: tokens.purple.c100,
linkHover: tokens.purple.c50
},
search: {
background: tokens.shade.c500,
hoverBackground: tokens.shade.c600,
focused: tokens.shade.c400,
placeholder: tokens.shade.c100,
icon: tokens.shade.c100
},
mediaCard: {
hoverBackground: tokens.shade.c600,
hoverAccent: tokens.shade.c50,
hoverShadow: tokens.shade.c900,
shadow: tokens.shade.c700,
barColor: tokens.ash.c200,
barFillColor: tokens.purple.c100,
badge: tokens.shade.c700,
badgeText: tokens.ash.c100
},
largeCard: {
background: tokens.shade.c600,
icon: tokens.purple.c400
},
dropdown: {
background: tokens.shade.c600,
altBackground: tokens.shade.c700,
hoverBackground: tokens.shade.c500,
text: tokens.shade.c50,
secondary: tokens.shade.c100,
border: tokens.shade.c400,
contentBackground: tokens.shade.c500
},
authentication: {
border: tokens.shade.c300,
inputBg: tokens.shade.c600,
inputBgHover: tokens.shade.c500,
wordBackground: tokens.shade.c500,
copyText: tokens.shade.c100,
copyTextHover: tokens.ash.c50
},
settings: {
sidebar: {
activeLink: tokens.shade.c600,
badge: tokens.shade.c900,
type: {
secondary: tokens.shade.c200,
inactive: tokens.shade.c50,
icon: tokens.shade.c50,
iconActivated: tokens.purple.c200,
activated: tokens.purple.c50
}
},
card: {
border: tokens.shade.c400,
background: tokens.shade.c400,
altBackground: tokens.shade.c400
},
saveBar: {
background: tokens.shade.c800
}
},
utils: {
divider: tokens.ash.c300
},
errors: {
card: tokens.shade.c800,
border: tokens.ash.c500,
type: {
secondary: tokens.ash.c100
}
},
about: {
circle: tokens.ash.c500,
circleText: tokens.ash.c50
},
editBadge: {
bg: tokens.ash.c500,
bgHover: tokens.ash.c400,
text: tokens.ash.c50
},
progress: {
background: tokens.ash.c50,
preloaded: tokens.ash.c50,
filled: tokens.purple.c200
},
video: {
buttonBackground: tokens.ash.c200,
autoPlay: {
background: tokens.ash.c700,
hover: tokens.ash.c500
},
scraping: {
card: tokens.shade.c700,
loading: tokens.purple.c200,
noresult: tokens.ash.c100
},
audio: {
set: tokens.purple.c200
},
context: {
background: tokens.ash.c900,
light: tokens.shade.c50,
border: tokens.ash.c600,
hoverColor: tokens.ash.c600,
buttonFocus: tokens.ash.c500,
flagBg: tokens.ash.c500,
inputBg: tokens.ash.c600,
buttonOverInputHover: tokens.ash.c500,
inputPlaceholder: tokens.ash.c200,
cardBorder: tokens.ash.c700,
slider: tokens.ash.c50,
sliderFilled: tokens.purple.c200,
buttons: {
list: tokens.ash.c700,
active: tokens.ash.c900
},
closeHover: tokens.ash.c800,
type: {
secondary: tokens.ash.c200,
accent: tokens.purple.c200
}
}
}
}
}
});

View File

@@ -0,0 +1,259 @@
import { createTheme } from "../types";
const tokens = {
purple: {
c50: "#feabac",
c100: "#fe8385",
c200: "#ea5b5e",
c300: "#d34648",
c400: "#bd3436",
c500: "#852a2b",
c600: "#632021",
c700: "#49191a",
c800: "#331112",
c900: "#220c0c"
},
shade: {
c50: "#9c605c",
c100: "#834d49",
c200: "#673b38",
c300: "#542f2c",
c400: "#452422",
c500: "#361c1a",
c600: "#2b1614",
c700: "#241210",
c800: "#1c0e0d",
c900: "#130909"
},
ash: {
c50: "#ac6e6f",
c100: "#8b4b4c",
c200: "#703739",
c300: "#572225",
c400: "#49191a",
c500: "#421617",
c600: "#371212",
c700: "#2e0e0f",
c800: "#230c0d",
c900: "#19090b"
},
blue: {
c50: "#f5adb4",
c100: "#cc7981",
c200: "#ae5d65",
c300: "#8c3b43",
c400: "#712a31",
c500: "#501f24",
c600: "#411b1f",
c700: "#36171b",
c800: "#201011",
c900: "#130b0c"
}
};
export default createTheme({
name: "red",
extend: {
colors: {
themePreview: {
primary: tokens.blue.c200,
secondary: tokens.shade.c50
},
pill: {
background: tokens.shade.c300,
backgroundHover: tokens.shade.c200,
highlight: tokens.blue.c200,
activeBackground: tokens.shade.c300,
},
global: {
accentA: tokens.blue.c200,
accentB: tokens.blue.c300
},
lightBar: {
light: tokens.blue.c400
},
buttons: {
toggle: tokens.purple.c300,
toggleDisabled: tokens.ash.c500,
secondary: tokens.ash.c700,
secondaryHover: tokens.ash.c700,
purple: tokens.purple.c500,
purpleHover: tokens.purple.c400,
cancel: tokens.ash.c500,
cancelHover: tokens.ash.c300
},
background: {
main: tokens.shade.c900,
secondary: tokens.shade.c600,
secondaryHover: tokens.shade.c400,
accentA: tokens.purple.c500,
accentB: tokens.blue.c500
},
modal: {
background: tokens.shade.c800,
},
type: {
logo: tokens.purple.c100,
text: tokens.shade.c50,
dimmed: tokens.shade.c50,
divider: tokens.ash.c500,
secondary: tokens.ash.c100,
link: tokens.purple.c100,
linkHover: tokens.purple.c50
},
search: {
background: tokens.shade.c500,
hoverBackground: tokens.shade.c600,
focused: tokens.shade.c400,
placeholder: tokens.shade.c100,
icon: tokens.shade.c100
},
mediaCard: {
hoverBackground: tokens.shade.c600,
hoverAccent: tokens.shade.c50,
hoverShadow: tokens.shade.c900,
shadow: tokens.shade.c700,
barColor: tokens.ash.c200,
barFillColor: tokens.purple.c100,
badge: tokens.shade.c700,
badgeText: tokens.ash.c100
},
largeCard: {
background: tokens.shade.c600,
icon: tokens.purple.c400
},
dropdown: {
background: tokens.shade.c600,
altBackground: tokens.shade.c700,
hoverBackground: tokens.shade.c500,
text: tokens.shade.c50,
secondary: tokens.shade.c100,
border: tokens.shade.c400,
contentBackground: tokens.shade.c500
},
authentication: {
border: tokens.shade.c300,
inputBg: tokens.shade.c600,
inputBgHover: tokens.shade.c500,
wordBackground: tokens.shade.c500,
copyText: tokens.shade.c100,
copyTextHover: tokens.ash.c50
},
settings: {
sidebar: {
activeLink: tokens.shade.c600,
badge: tokens.shade.c900,
type: {
secondary: tokens.shade.c200,
inactive: tokens.shade.c50,
icon: tokens.shade.c50,
iconActivated: tokens.purple.c200,
activated: tokens.purple.c50
}
},
card: {
border: tokens.shade.c400,
background: tokens.shade.c400,
altBackground: tokens.shade.c400
},
saveBar: {
background: tokens.shade.c800
}
},
utils: {
divider: tokens.ash.c300
},
errors: {
card: tokens.shade.c800,
border: tokens.ash.c500,
type: {
secondary: tokens.ash.c100
}
},
about: {
circle: tokens.ash.c500,
circleText: tokens.ash.c50
},
editBadge: {
bg: tokens.ash.c500,
bgHover: tokens.ash.c400,
text: tokens.ash.c50
},
progress: {
background: tokens.ash.c50,
preloaded: tokens.ash.c50,
filled: tokens.purple.c200
},
video: {
buttonBackground: tokens.ash.c200,
autoPlay: {
background: tokens.ash.c700,
hover: tokens.ash.c500
},
scraping: {
card: tokens.shade.c700,
loading: tokens.purple.c200,
noresult: tokens.ash.c100
},
audio: {
set: tokens.purple.c200
},
context: {
background: tokens.ash.c900,
light: tokens.shade.c50,
border: tokens.ash.c600,
hoverColor: tokens.ash.c600,
buttonFocus: tokens.ash.c500,
flagBg: tokens.ash.c500,
inputBg: tokens.ash.c600,
buttonOverInputHover: tokens.ash.c500,
inputPlaceholder: tokens.ash.c200,
cardBorder: tokens.ash.c700,
slider: tokens.ash.c50,
sliderFilled: tokens.purple.c200,
buttons: {
list: tokens.ash.c700,
active: tokens.ash.c900
},
closeHover: tokens.ash.c800,
type: {
secondary: tokens.ash.c200,
accent: tokens.purple.c200
}
}
}
}
}
});

View File

@@ -0,0 +1,259 @@
import { createTheme } from "../types";
const tokens = {
purple: {
c50: "#aad7ff",
c100: "#82c4ff",
c200: "#59a8ec",
c300: "#4491d6",
c400: "#317dbf",
c500: "#285b87",
c600: "#1f4464",
c700: "#18334a",
c800: "#112434",
c900: "#0b1822"
},
shade: {
c50: "#677c90",
c100: "#52667a",
c200: "#3f4f60",
c300: "#32404f",
c400: "#273441",
c500: "#1e2832",
c600: "#172028",
c700: "#131a22",
c800: "#0f151b",
c900: "#0a0e12"
},
ash: {
c50: "#7f9b9b",
c100: "#5b7b7b",
c200: "#446463",
c300: "#2b4e4d",
c400: "#204241",
c500: "#1c3c3b",
c600: "#173232",
c700: "#132929",
c800: "#102020",
c900: "#0c1615"
},
blue: {
c50: "#adf5d6",
c100: "#79cca8",
c200: "#5dae8b",
c300: "#3b8c69",
c400: "#2a7152",
c500: "#1f503b",
c600: "#1b4130",
c700: "#173629",
c800: "#102019",
c900: "#0b1310"
}
};
export default createTheme({
name: "teal",
extend: {
colors: {
themePreview: {
primary: tokens.blue.c200,
secondary: tokens.shade.c50
},
pill: {
background: tokens.shade.c300,
backgroundHover: tokens.shade.c200,
highlight: tokens.blue.c200,
activeBackground: tokens.shade.c300,
},
global: {
accentA: tokens.blue.c200,
accentB: tokens.blue.c300
},
lightBar: {
light: tokens.blue.c400
},
buttons: {
toggle: tokens.purple.c300,
toggleDisabled: tokens.ash.c500,
secondary: tokens.ash.c700,
secondaryHover: tokens.ash.c700,
purple: tokens.purple.c500,
purpleHover: tokens.purple.c400,
cancel: tokens.ash.c500,
cancelHover: tokens.ash.c300
},
background: {
main: tokens.shade.c900,
secondary: tokens.shade.c600,
secondaryHover: tokens.shade.c400,
accentA: tokens.purple.c500,
accentB: tokens.blue.c500
},
modal: {
background: tokens.shade.c800,
},
type: {
logo: tokens.purple.c100,
text: tokens.shade.c50,
dimmed: tokens.shade.c50,
divider: tokens.ash.c500,
secondary: tokens.ash.c100,
link: tokens.purple.c100,
linkHover: tokens.purple.c50
},
search: {
background: tokens.shade.c500,
hoverBackground: tokens.shade.c600,
focused: tokens.shade.c400,
placeholder: tokens.shade.c100,
icon: tokens.shade.c100
},
mediaCard: {
hoverBackground: tokens.shade.c600,
hoverAccent: tokens.shade.c50,
hoverShadow: tokens.shade.c900,
shadow: tokens.shade.c700,
barColor: tokens.ash.c200,
barFillColor: tokens.purple.c100,
badge: tokens.shade.c700,
badgeText: tokens.ash.c100
},
largeCard: {
background: tokens.shade.c600,
icon: tokens.purple.c400
},
dropdown: {
background: tokens.shade.c600,
altBackground: tokens.shade.c700,
hoverBackground: tokens.shade.c500,
text: tokens.shade.c50,
secondary: tokens.shade.c100,
border: tokens.shade.c400,
contentBackground: tokens.shade.c500
},
authentication: {
border: tokens.shade.c300,
inputBg: tokens.shade.c600,
inputBgHover: tokens.shade.c500,
wordBackground: tokens.shade.c500,
copyText: tokens.shade.c100,
copyTextHover: tokens.ash.c50
},
settings: {
sidebar: {
activeLink: tokens.shade.c600,
badge: tokens.shade.c900,
type: {
secondary: tokens.shade.c200,
inactive: tokens.shade.c50,
icon: tokens.shade.c50,
iconActivated: tokens.purple.c200,
activated: tokens.purple.c50
}
},
card: {
border: tokens.shade.c400,
background: tokens.shade.c400,
altBackground: tokens.shade.c400
},
saveBar: {
background: tokens.shade.c800
}
},
utils: {
divider: tokens.ash.c300
},
errors: {
card: tokens.shade.c800,
border: tokens.ash.c500,
type: {
secondary: tokens.ash.c100
}
},
about: {
circle: tokens.ash.c500,
circleText: tokens.ash.c50
},
editBadge: {
bg: tokens.ash.c500,
bgHover: tokens.ash.c400,
text: tokens.ash.c50
},
progress: {
background: tokens.ash.c50,
preloaded: tokens.ash.c50,
filled: tokens.purple.c200
},
video: {
buttonBackground: tokens.ash.c200,
autoPlay: {
background: tokens.ash.c700,
hover: tokens.ash.c500
},
scraping: {
card: tokens.shade.c700,
loading: tokens.purple.c200,
noresult: tokens.ash.c100
},
audio: {
set: tokens.purple.c200
},
context: {
background: tokens.ash.c900,
light: tokens.shade.c50,
border: tokens.ash.c600,
hoverColor: tokens.ash.c600,
buttonFocus: tokens.ash.c500,
flagBg: tokens.ash.c500,
inputBg: tokens.ash.c600,
buttonOverInputHover: tokens.ash.c500,
inputPlaceholder: tokens.ash.c200,
cardBorder: tokens.ash.c700,
slider: tokens.ash.c50,
sliderFilled: tokens.purple.c200,
buttons: {
list: tokens.ash.c700,
active: tokens.ash.c900
},
closeHover: tokens.ash.c800,
type: {
secondary: tokens.ash.c200,
accent: tokens.purple.c200
}
}
}
}
}
});

View File

@@ -0,0 +1,18 @@
import type { defaultTheme } from "./default";
type DeepPartial<T> = {
[P in keyof T]?: DeepPartial<T[P]>;
};
export interface Theme {
name: string;
extend: DeepPartial<(typeof defaultTheme)["extend"]>;
}
export function createTheme(theme: Theme) {
return {
name: theme.name,
selectors: [`.theme-${theme.name}`],
extend: theme.extend,
};
}

View File

@@ -1,40 +0,0 @@
import type { Config } from "tailwindcss";
import animate from "tailwindcss-animate";
import base from "./base";
export default {
content: base.content,
presets: [base],
theme: {
container: {
center: true,
padding: "2rem",
screens: {
"2xl": "1400px",
},
},
extend: {
borderRadius: {
lg: "var(--radius)",
md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)",
},
keyframes: {
"accordion-down": {
from: { height: "0" },
to: { height: "var(--radix-accordion-content-height)" },
},
"accordion-up": {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: "0" },
},
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
},
},
},
plugins: [animate],
} satisfies Config;