Skip to content

Instantly share code, notes, and snippets.

@JuanRdBO
Created April 23, 2025 17:06
Show Gist options
  • Save JuanRdBO/1f678801713c8cfc353494852d3e3459 to your computer and use it in GitHub Desktop.
Save JuanRdBO/1f678801713c8cfc353494852d3e3459 to your computer and use it in GitHub Desktop.
const { withAndroidManifest, withDangerousMod } = require("@expo/config-plugins");
const { mergeContents } = require("@expo/config-plugins/build/utils/generateCode");
const fs = require("node:fs");
const path = require("node:path");
/**
* Config plugin to add border radius to Android popup menus
* @param {import('@expo/config-types').ExpoConfig} config - Expo config
* @param {Object} options - Plugin options
* @param {number} [options.radius=14] - Border radius in dp
* @param {string} [options.lightBackgroundColor='#F7F7F7'] - Background color for light theme
* @param {string} [options.darkBackgroundColor='#090909'] - Background color for dark theme
* @param {number} [options.padding=14] - Padding in dp
* @returns {import('@expo/config-types').ExpoConfig} - Modified Expo config
*/
const withRoundedPopupMenu = (config, options = {}) => {
const radius = options.radius || 14;
const lightBackgroundColor = options.lightBackgroundColor || "#F7F7F7";
const darkBackgroundColor = options.darkBackgroundColor || "#090909";
const padding = options.padding || 14;
// Create the drawable resources for the rounded popup menu
let modifiedConfig = withDangerousMod(config, [
"android",
async (config) => {
const androidDir = path.join(config.modRequest.platformProjectRoot, "app", "src", "main");
const resDir = path.join(androidDir, "res");
const drawableDir = path.join(resDir, "drawable");
const drawableNightDir = path.join(resDir, "drawable-night");
// Ensure the drawable directories exist
if (!fs.existsSync(drawableDir)) {
fs.mkdirSync(drawableDir, { recursive: true });
}
if (!fs.existsSync(drawableNightDir)) {
fs.mkdirSync(drawableNightDir, { recursive: true });
}
// Create the rounded popup drawable XML for light theme
const roundedPopupLightXml = `<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="${lightBackgroundColor}" />
<corners android:radius="${radius}dp" />
<padding
android:bottom="${padding}dp"
android:top="${padding}dp" />
</shape>`;
// Create the rounded popup drawable XML for dark theme
const roundedPopupDarkXml = `<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="${darkBackgroundColor}" />
<corners android:radius="${radius}dp" />
<padding
android:bottom="${padding}dp"
android:top="${padding}dp" />
</shape>`;
// Write the drawable XML files
fs.writeFileSync(path.join(drawableDir, "rounded_popup.xml"), roundedPopupLightXml);
fs.writeFileSync(path.join(drawableNightDir, "rounded_popup.xml"), roundedPopupDarkXml);
return config;
},
]);
// Modify the styles.xml to use the rounded popup drawable
modifiedConfig = withDangerousMod(modifiedConfig, [
"android",
async (config) => {
const androidDir = path.join(config.modRequest.platformProjectRoot, "app", "src", "main");
const resDir = path.join(androidDir, "res");
const valuesDir = path.join(resDir, "values");
// Ensure the values directory exists
if (!fs.existsSync(valuesDir)) {
fs.mkdirSync(valuesDir, { recursive: true });
}
const stylesPath = path.join(valuesDir, "styles.xml");
// Create a new styles.xml file with proper XML formatting
const stylesXml = `<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Base application theme -->
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<!-- Customize your theme here -->
<item name="android:popupMenuStyle">@style/RoundedPopupMenuStyle</item>
</style>
<!-- Rounded Popup Menu Style -->
<style name="RoundedPopupMenuStyle" parent="Widget.AppCompat.PopupMenu">
<item name="android:popupBackground">@drawable/rounded_popup</item>
</style>
</resources>`;
// Write the styles.xml file
fs.writeFileSync(stylesPath, stylesXml);
return config;
},
]);
return modifiedConfig;
};
module.exports = withRoundedPopupMenu;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment