Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: load space's custom colors #1090

Merged
merged 8 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion apps/ui/src/components/App/Topnav.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const { modalAccountOpen, modalAccountWithoutDismissOpen, resetAccountModal } =
useModal();
const { login, web3 } = useWeb3();
const { toggleSkin, currentMode } = useUserSkin();
const { isWhiteLabel } = useWhiteLabel();

const SEARCH_CONFIG = {
space: {
Expand Down Expand Up @@ -149,7 +150,11 @@ onUnmounted(() => {
</template>
</UiButton>
<IndicatorPendingTransactions />
<UiButton class="!px-0 w-[46px]" @click="toggleSkin">
<UiButton
v-if="!isWhiteLabel"
class="!px-0 w-[46px]"
@click="toggleSkin()"
>
<IH-light-bulb v-if="currentMode === 'dark'" class="inline-block" />
<IH-moon v-else class="inline-block" />
</UiButton>
Expand Down
33 changes: 33 additions & 0 deletions apps/ui/src/components/Layout/App.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
<script lang="ts" setup>
import resolveConfig from 'tailwindcss/resolveConfig';
import { Skin } from '@/composables/useUserSkin';
import { APP_NAME } from '@/helpers/constants';
import {
clone,
getCacheHash,
getStampUrl,
hexToRgb,
whiteLabelAwareParams
} from '@/helpers/utils';
import { Transaction } from '@/types';
Expand All @@ -21,6 +24,7 @@ const router = useRouter();
const uiStore = useUiStore();
const { modalOpen } = useModal();
const { init, setAppName, app } = useApp();
const { DEFAULT_SKIN, setSkin } = useUserSkin();
const { isWhiteLabel, space: whiteLabelSpace } = useWhiteLabel();
const { setFavicon } = useFavicon();
const { web3 } = useWeb3();
Expand All @@ -42,6 +46,7 @@ const {
transaction,
reset
} = useWalletConnectTransaction();
const { css } = useStyleTag('', { id: 'skin' });

provide('web3', web3);

Expand All @@ -67,6 +72,25 @@ const hasTopNav = computed(() => {
return 'space-editor' !== String(route.matched[1]?.name);
});

const skinVariables = computed(() => {
if (!whiteLabelSpace.value?.additionalRawData?.skinSettings) return {};

const colors = clone(whiteLabelSpace.value?.additionalRawData?.skinSettings);

const result = Object.entries(colors).reduce((acc, [colorName, hex]) => {
if (!hex || !colorName.includes('_color')) return acc;

const rgb = hexToRgb(hex.slice(1));
wa0x6e marked this conversation as resolved.
Show resolved Hide resolved
acc[`--${colorName.replace('_color', '')}`] = `${rgb.r},${rgb.g},${rgb.b}`;
return acc;
}, {});

if (result['--content']) {
result['--content'] = `rgb(${result['--content']})`;
}
return result;
});

async function handleTransactionAccept() {
if (
!walletConnectSpaceKey.value ||
Expand Down Expand Up @@ -145,6 +169,15 @@ watch(
setFavicon(faviconUrl);

setAppName(whiteLabelSpace.value.name);

css.value = `:root { ${Object.entries(skinVariables.value)
.map(([key, val]) => `${key}:${val}`)
.join(';')}; }`;

setSkin(
(whiteLabelSpace.value.additionalRawData?.skinSettings?.theme as Skin) ||
DEFAULT_SKIN
);
},
{ immediate: true }
);
Expand Down
8 changes: 1 addition & 7 deletions apps/ui/src/components/Ui/ProposalLabel.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script setup lang="ts">
import { RouteLocationNamedRaw } from 'vue-router';
import { hexToRgb } from '@/helpers/utils';

const props = defineProps<{
label: string;
Expand All @@ -11,13 +12,6 @@ const { currentMode } = useUserSkin();

const colorProperties = computed(() => checkColorProximity(props.color));

function hexToRgb(hex: string): { r: number; g: number; b: number } {
const r = parseInt(hex.substring(0, 2), 16);
const g = parseInt(hex.substring(2, 4), 16);
const b = parseInt(hex.substring(4, 6), 16);
return { r, g, b };
}

function checkColorProximity(color: string): {
backgroundColor?: string;
showBorder: boolean;
Expand Down
16 changes: 12 additions & 4 deletions apps/ui/src/composables/useUserSkin.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,33 @@
type Skin = 'dark' | 'light' | 'none';
export type Skin = 'dark' | 'light' | 'none';

const DEFAULT_SKIN = 'light';

export function useUserSkin() {
const store = useStorage<Skin>('skin', 'none');
const currentMode = computed(() =>
['light', 'none'].includes(store.value) ? 'light' : 'dark'
[DEFAULT_SKIN, 'none'].includes(store.value) ? DEFAULT_SKIN : 'dark'
);

function toggleSkin() {
store.value = ['light', 'none'].includes(store.value) ? 'dark' : 'light';
}

function setSkin(skin: Skin) {
store.value = skin;
}

watchEffect(() => {
if (currentMode.value === 'light') {
if (currentMode.value === DEFAULT_SKIN) {
document.documentElement.classList.remove('dark');
} else {
document.documentElement.classList.add('dark');
}
});

return {
DEFAULT_SKIN,
currentMode,
toggleSkin
toggleSkin,
setSkin
};
}
7 changes: 7 additions & 0 deletions apps/ui/src/helpers/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -637,3 +637,10 @@ export function whiteLabelAwareParams(

return params;
}

export function hexToRgb(hex: string): { r: number; g: number; b: number } {
const r = parseInt(hex.substring(0, 2), 16);
const g = parseInt(hex.substring(2, 4), 16);
const b = parseInt(hex.substring(4, 6), 16);
return { r, g, b };
}
1 change: 1 addition & 0 deletions apps/ui/src/networks/offchain/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ function formatSpace(
private: space.private,
domain: space.domain,
skin: space.skin,
skinSettings: space.skinSettings,
strategies: space.strategies,
categories: space.categories,
admins: space.admins,
Expand Down
10 changes: 10 additions & 0 deletions apps/ui/src/networks/offchain/api/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,16 @@ const SPACE_FRAGMENT = gql`
private
domain
skin
skinSettings {
bg_color
link_color
text_color
content_color
border_color
heading_color
primary_color
theme
}
guidelines
template
categories
Expand Down
2 changes: 2 additions & 0 deletions apps/ui/src/networks/offchain/api/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
DelegationType,
NetworkID,
SkinSettings,
SpaceMetadataLabel,
VoteType
} from '@/types';
Expand Down Expand Up @@ -77,6 +78,7 @@ export type ApiSpace = {
private: boolean;
domain: string | null;
skin: string | null;
skinSettings: SkinSettings | null;
template: string | null;
guidelines: string | null;
categories: string[];
Expand Down
12 changes: 12 additions & 0 deletions apps/ui/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ export type OffchainAdditionalRawData = {
| 'private'
| 'domain'
| 'skin'
| 'skinSettings'
| 'strategies'
| 'categories'
| 'admins'
Expand Down Expand Up @@ -393,6 +394,17 @@ export type Metadata = {
execution: Transaction[];
};

export type SkinSettings = {
bg_color?: string;
link_color?: string;
text_color?: string;
content_color?: string;
border_color?: string;
heading_color?: string;
primary_color?: string;
theme?: string;
};

export type Drafts = Record<string, Draft>;

export type BaseTransaction = {
Expand Down