this repo has no description
10
fork

Configure Feed

Select the types of activity you want to include in your feed.

ux: compact banner field in manage form — add button when empty, thumbnail when set

Made-with: Cursor

+113 -67
+52 -23
assets/styles.css
··· 2857 2857 } 2858 2858 } 2859 2859 .profile-form-banner { 2860 + margin-bottom: 1.25rem; 2861 + } 2862 + .profile-form-banner-empty { 2860 2863 display: flex; 2861 - flex-direction: column; 2862 - gap: 0.65rem; 2863 - margin-bottom: 1.25rem; 2864 + flex-wrap: wrap; 2865 + align-items: center; 2866 + gap: 0.75rem; 2867 + } 2868 + .profile-form-banner-empty .profile-form-hint { 2869 + margin: 0; 2870 + flex: 1 1 220px; 2864 2871 } 2865 - .profile-form-banner-preview { 2872 + /* Compact row when a banner exists */ 2873 + .profile-form-banner-row { 2874 + display: flex; 2875 + align-items: center; 2876 + gap: 1rem; 2877 + flex-wrap: wrap; 2878 + } 2879 + /* Clickable thumbnail */ 2880 + .profile-form-banner-thumb-label { 2866 2881 position: relative; 2867 - width: 100%; 2882 + display: block; 2883 + cursor: pointer; 2884 + border-radius: 10px; 2885 + overflow: hidden; 2886 + flex: 0 0 auto; 2887 + width: 160px; 2868 2888 aspect-ratio: 1200 / 630; 2869 - border-radius: 18px; 2870 - overflow: hidden; 2871 - background: rgba(255, 255, 255, 0.4); 2872 2889 border: 1px solid rgba(255, 255, 255, 0.5); 2873 - display: flex; 2874 - align-items: center; 2875 - justify-content: center; 2890 + background: rgba(255, 255, 255, 0.3); 2876 2891 } 2877 - .profile-form-banner-preview--empty { 2878 - border-style: dashed; 2879 - background: rgba(255, 255, 255, 0.25); 2880 - } 2881 - .profile-form-banner-img { 2892 + .profile-form-banner-thumb { 2882 2893 width: 100%; 2883 2894 height: 100%; 2884 2895 object-fit: cover; 2885 2896 display: block; 2886 2897 } 2887 - .profile-form-banner-placeholder { 2888 - font-size: 0.95rem; 2889 - color: rgba(0, 0, 0, 0.5); 2898 + .profile-form-banner-thumb-overlay { 2899 + position: absolute; 2900 + inset: 0; 2901 + display: flex; 2902 + align-items: center; 2903 + justify-content: center; 2904 + background: rgba(0, 0, 0, 0.35); 2905 + color: #fff; 2906 + font-size: 0.8rem; 2907 + font-weight: 500; 2908 + opacity: 0; 2909 + transition: opacity 0.15s ease; 2910 + } 2911 + .profile-form-banner-thumb-label:hover .profile-form-banner-thumb-overlay { 2912 + opacity: 1; 2890 2913 } 2891 - .profile-form-banner-controls { 2914 + .profile-form-banner-thumb-actions { 2892 2915 display: flex; 2893 - flex-wrap: wrap; 2894 - gap: 0.6rem; 2895 - align-items: center; 2916 + flex-direction: column; 2917 + gap: 0.5rem; 2918 + align-items: flex-start; 2919 + } 2920 + /* The visible "Replace banner" button next to thumbnail is redundant 2921 + with the clickable thumbnail but improves discoverability */ 2922 + .profile-form-banner-thumb-replace { 2923 + font-size: 0.85rem; 2924 + padding: 0.4rem 0.8rem; 2896 2925 } 2897 2926 .profile-form-avatar { 2898 2927 display: flex;
+1 -1
i18n/messages/en.tsx
··· 590 590 avatarHint: "PNG, JPEG, or WebP. 1MB max. Square works best.", 591 591 avatarReplace: "Replace icon", 592 592 avatarRemove: "Remove icon", 593 - bannerLabel: "Project banner", 593 + bannerLabel: "Add banner image", 594 594 bannerHint: 595 595 "Shown at the top of your project page and used as the share preview when your link is posted (Bluesky, Twitter, etc.). Recommended 1200×630, PNG/JPEG/WebP, 3MB max.", 596 596 bannerReplace: "Replace banner",
+60 -43
islands/CreateProfileForm.tsx
··· 928 928 </div> 929 929 930 930 <div class="profile-form-banner"> 931 - <div 932 - class={`profile-form-banner-preview${ 933 - bannerPreview.value ? "" : " profile-form-banner-preview--empty" 934 - }`} 935 - aria-hidden={bannerPreview.value ? undefined : "true"} 936 - > 937 - {bannerPreview.value 938 - ? ( 939 - <img 940 - src={bannerPreview.value} 941 - alt="" 942 - class="profile-form-banner-img" 943 - onError={() => { 944 - bannerPreview.value = null; 945 - }} 946 - /> 947 - ) 948 - : ( 949 - <span class="profile-form-banner-placeholder"> 950 - {tForm.bannerLabel} 951 - </span> 952 - )} 953 - </div> 954 - <div class="profile-form-banner-controls"> 955 - <label class="profile-form-button-secondary"> 956 - {bannerPreview.value ? tForm.bannerReplace : tForm.bannerLabel} 957 - <input 958 - type="file" 959 - accept="image/png,image/jpeg,image/webp" 960 - hidden 961 - onChange={onBannerChange} 962 - /> 963 - </label> 964 - {bannerPreview.value && ( 965 - <button 966 - type="button" 967 - class="profile-form-button-link" 968 - onClick={removeBanner} 969 - > 970 - {tForm.bannerRemove} 971 - </button> 931 + {bannerPreview.value 932 + ? ( 933 + /* Banner exists — compact thumbnail row */ 934 + <div class="profile-form-banner-row"> 935 + <label class="profile-form-banner-thumb-label"> 936 + <img 937 + src={bannerPreview.value} 938 + alt="Project banner" 939 + class="profile-form-banner-thumb" 940 + onError={() => { 941 + bannerPreview.value = null; 942 + }} 943 + /> 944 + <span 945 + class="profile-form-banner-thumb-overlay" 946 + aria-hidden="true" 947 + > 948 + {tForm.bannerReplace} 949 + </span> 950 + <input 951 + type="file" 952 + accept="image/png,image/jpeg,image/webp" 953 + hidden 954 + onChange={onBannerChange} 955 + /> 956 + </label> 957 + <div class="profile-form-banner-thumb-actions"> 958 + <label class="profile-form-button-secondary profile-form-banner-thumb-replace"> 959 + {tForm.bannerReplace} 960 + <input 961 + type="file" 962 + accept="image/png,image/jpeg,image/webp" 963 + hidden 964 + onChange={onBannerChange} 965 + /> 966 + </label> 967 + <button 968 + type="button" 969 + class="profile-form-button-link" 970 + onClick={removeBanner} 971 + > 972 + {tForm.bannerRemove} 973 + </button> 974 + </div> 975 + </div> 976 + ) 977 + : ( 978 + /* No banner — just a small add button + hint */ 979 + <div class="profile-form-banner-empty"> 980 + <label class="profile-form-button-secondary"> 981 + + {tForm.bannerLabel} 982 + <input 983 + type="file" 984 + accept="image/png,image/jpeg,image/webp" 985 + hidden 986 + onChange={onBannerChange} 987 + /> 988 + </label> 989 + <p class="profile-form-hint">{tForm.bannerHint}</p> 990 + </div> 972 991 )} 973 - </div> 974 - <p class="profile-form-hint">{tForm.bannerHint}</p> 975 992 </div> 976 993 977 994 <div class="profile-form-row">