(UI/STYLE): Created a simple UI for the profile page. #2

Merged
azpect merged 2 commits from feature/UI into master 2025-06-25 18:04:28 -07:00
9 changed files with 326 additions and 127 deletions

View File

@ -46,7 +46,12 @@ func GoogleCallback(ctx *gin.Context) {
false, // TODO: True in prod
true,
)
ctx.JSON(http.StatusOK, gin.H{"jwt": jwt, "googleUserInfo": googleUserInfo, "dbUser": dbUser})
// ctx.JSON(http.StatusOK, gin.H{"jwt": jwt, "googleUserInfo": googleUserInfo, "dbUser": dbUser})
_ = dbUser
_ = googleUserInfo
ctx.Redirect(http.StatusSeeOther, "/")
}
}

View File

@ -1,7 +1,10 @@
package handlers
import (
"net/http"
"github.com/gin-gonic/gin"
domain "github.com/haydenhargreaves/Potion/internal/domain/server"
layouts "github.com/haydenhargreaves/Potion/internal/templates/layouts"
pages "github.com/haydenhargreaves/Potion/internal/templates/pages"
)
@ -35,8 +38,18 @@ func CreatePage(ctx *gin.Context) {
}
func ProfilePage(ctx *gin.Context) {
// If not logged in, direct to the login page
if !domain.IsLoggedIn(ctx) {
ctx.Redirect(http.StatusSeeOther, "/v1/web/login")
return
}
// Else, get the user data
deps := ctx.MustGet("deps").(*domain.InjectedDependencies)
user := deps.UserService.GetAuthenicatedUser(ctx)
title := "Potion - Profile"
page := pages.ProfilePage()
page := pages.ProfilePage(user)
ctx.HTML(200, "", layouts.AppLayout(title, page))
}

View File

@ -1,6 +1,9 @@
package service
import domain "github.com/haydenhargreaves/Potion/internal/domain/user"
import (
"github.com/gin-gonic/gin"
domain "github.com/haydenhargreaves/Potion/internal/domain/user"
)
// UserService implements the domain.UserService defined in the domain module.
type UserService struct {
@ -15,3 +18,18 @@ var _ domain.UserService = (*UserService)(nil)
func NewUserService(userRepository domain.UserRepository) domain.UserService {
return &UserService{userRepository: userRepository}
}
func (s *UserService) GetAuthenicatedUser(ctx *gin.Context) domain.User {
val, ok := ctx.Get("userId")
if !ok {
return domain.User{}
}
id := val.(int)
user, err := s.userRepository.GetUserById(id)
if err != nil {
return domain.User{}
}
return *user
}

View File

@ -3,4 +3,5 @@ package domain
type UserRepository interface {
CreateGoogleUser(googleUserInfo *GoogleUserInfo, googleRefreshToken string) (User, error)
GetGoogleUser(googleId string) (*User, error)
GetUserById(id int) (*User, error)
}

View File

@ -1,4 +1,7 @@
package domain
import "github.com/gin-gonic/gin"
type UserService interface {
GetAuthenicatedUser(ctx *gin.Context) User
}

View File

@ -105,3 +105,39 @@ func (r *UserRepository) GetGoogleUser(googleId string) (*domain.User, error) {
return &user, nil
}
func (r *UserRepository) GetUserById(id int) (*domain.User, error) {
tx, err := r.db.Begin()
if err != nil {
tx.Rollback()
return nil, err
}
var user domain.User
query := `SELECT * FROM users WHERE id = $1`
if err := tx.QueryRow(query, id).Scan(
&user.Id,
&user.GoogleId,
&user.Name,
&user.Email,
&user.ImageUrl,
&user.GoogleRefreshToken,
&user.Created,
); err != nil {
// If no user was found, don't error, just return
if err == sql.ErrNoRows {
return nil, nil
}
tx.Rollback()
return nil, err
}
if err := tx.Commit(); err != nil {
tx.Rollback()
return nil, err
}
return &user, nil
}

View File

@ -1,9 +1,37 @@
package templates
import "github.com/haydenhargreaves/Potion/internal/templates/components"
import "github.com/haydenhargreaves/Potion/internal/domain/user"
templ ProfilePage() {
@components.Navbar("profile")
templ userDetailsSection(user domain.User) {
<section class="w-full flex flex-col justify-center my-8 py-4 border-b border-gray-300">
<div class="w-full p-4 md:p-8 flex items-center gap-x-8">
<img class="w-24 md:w-32 border-2 border-blue-500 rounded-full shadow-blue-500 shadow select-none" src={
user.ImageUrl } />
<div class="">
<h1 class="text-md md:text-2xl font-semibold">{ user.Name }</h1>
<p class="text-xs md:text-sm">{ user.Email }</p>
</div>
</div>
</section>
}
templ logoutSection() {
<section class="w-full flex flex-col justify-center items-center py-8 border-t border-gray-300">
<button
class="border border-red-500 text-red-500 w-9/10 md:w-1/3 py-2 rounded-lg hover:cursor-pointer hover:bg-red-100 duration-300">
Logout
</button>
</section>
}
templ ProfilePage(user domain.User) {
@components.Navbar(" profile")
<div class="w-full h-screen flex justify-center">
<div
class="mx-2 md:mx-0 w-full md:w-1/2 md:pt-14 border-l border-r border-gray-300 bg-white flex flex-col justify-between">
@userDetailsSection(user)
@logoutSection()
</div>
</div>
}

View File

@ -9,8 +9,9 @@ import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "github.com/haydenhargreaves/Potion/internal/templates/components"
import "github.com/haydenhargreaves/Potion/internal/domain/user"
func ProfilePage() templ.Component {
func userDetailsSection(user domain.User) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
@ -31,7 +32,121 @@ func ProfilePage() templ.Component {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = components.Navbar("profile").Render(ctx, templ_7745c5c3_Buffer)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<section class=\"w-full flex flex-col justify-center my-8 py-4 border-b border-gray-300\"><div class=\"w-full p-4 md:p-8 flex items-center gap-x-8\"><img class=\"w-24 md:w-32 border-2 border-blue-500 rounded-full shadow-blue-500 shadow select-none\" src=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(
user.ImageUrl)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 10, Col: 19}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\"><div class=\"\"><h1 class=\"text-md md:text-2xl font-semibold\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(user.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 12, Col: 63}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</h1><p class=\"text-xs md:text-sm\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(user.Email)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 13, Col: 48}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</p></div></div></section>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
func logoutSection() templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var5 := templ.GetChildren(ctx)
if templ_7745c5c3_Var5 == nil {
templ_7745c5c3_Var5 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<section class=\"w-full flex flex-col justify-center items-center py-8 border-t border-gray-300\"><button class=\"border border-red-500 text-red-500 w-9/10 md:w-1/3 py-2 rounded-lg hover:cursor-pointer hover:bg-red-100 duration-300\">Logout</button></section>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
func ProfilePage(user domain.User) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var6 := templ.GetChildren(ctx)
if templ_7745c5c3_Var6 == nil {
templ_7745c5c3_Var6 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = components.Navbar(" profile").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<div class=\"w-full h-screen flex justify-center\"><div class=\"mx-2 md:mx-0 w-full md:w-1/2 md:pt-14 border-l border-r border-gray-300 bg-white flex flex-col justify-between\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = userDetailsSection(user).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = logoutSection().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}

View File

@ -7,8 +7,10 @@
'Noto Color Emoji';
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New',
monospace;
--color-red-100: oklch(93.6% 0.032 17.717);
--color-red-200: oklch(88.5% 0.062 18.334);
--color-red-400: oklch(70.4% 0.191 22.216);
--color-red-500: oklch(63.7% 0.237 25.331);
--color-blue-50: oklch(97% 0.014 254.604);
--color-blue-100: oklch(93.2% 0.032 255.585);
--color-blue-200: oklch(88.2% 0.059 254.128);
--color-blue-300: oklch(80.9% 0.105 251.813);
@ -16,19 +18,15 @@
--color-blue-500: oklch(62.3% 0.214 259.815);
--color-blue-600: oklch(54.6% 0.245 262.881);
--color-blue-700: oklch(48.8% 0.243 264.376);
--color-blue-800: oklch(42.4% 0.199 265.638);
--color-purple-100: oklch(94.6% 0.033 307.174);
--color-purple-600: oklch(55.8% 0.288 302.321);
--color-gray-50: oklch(98.5% 0.002 247.839);
--color-gray-100: oklch(96.7% 0.003 264.542);
--color-gray-200: oklch(92.8% 0.006 264.531);
--color-gray-300: oklch(87.2% 0.01 258.338);
--color-gray-400: oklch(70.7% 0.022 261.325);
--color-gray-500: oklch(55.1% 0.027 264.364);
--color-gray-600: oklch(44.6% 0.03 256.802);
--color-gray-700: oklch(37.3% 0.034 259.733);
--color-gray-800: oklch(27.8% 0.033 256.848);
--color-black: #000;
--color-white: #fff;
--spacing: 0.25rem;
--container-xl: 36rem;
@ -207,6 +205,9 @@
}
}
@layer utilities {
.pointer-events-none {
pointer-events: none;
}
.absolute {
position: absolute;
}
@ -249,8 +250,8 @@
.mx-4 {
margin-inline: calc(var(--spacing) * 4);
}
.my-1 {
margin-block: calc(var(--spacing) * 1);
.mx-8 {
margin-inline: calc(var(--spacing) * 8);
}
.my-2 {
margin-block: calc(var(--spacing) * 2);
@ -261,6 +262,9 @@
.my-8 {
margin-block: calc(var(--spacing) * 8);
}
.my-auto {
margin-block: auto;
}
.mt-2 {
margin-top: calc(var(--spacing) * 2);
}
@ -276,12 +280,12 @@
.mt-16 {
margin-top: calc(var(--spacing) * 16);
}
.mt-auto {
margin-top: auto;
}
.mb-1 {
margin-bottom: calc(var(--spacing) * 1);
}
.mb-2 {
margin-bottom: calc(var(--spacing) * 2);
}
.mb-6 {
margin-bottom: calc(var(--spacing) * 6);
}
@ -333,9 +337,6 @@
.h-6 {
height: calc(var(--spacing) * 6);
}
.h-24 {
height: calc(var(--spacing) * 24);
}
.h-auto {
height: auto;
}
@ -348,6 +349,9 @@
.h-screen {
height: 100vh;
}
.w-1\/3 {
width: calc(1/3 * 100%);
}
.w-3 {
width: calc(var(--spacing) * 3);
}
@ -369,6 +373,12 @@
.w-9\/10 {
width: calc(9/10 * 100%);
}
.w-24 {
width: calc(var(--spacing) * 24);
}
.w-28 {
width: calc(var(--spacing) * 28);
}
.w-32 {
width: calc(var(--spacing) * 32);
}
@ -445,15 +455,6 @@
.gap-1 {
gap: calc(var(--spacing) * 1);
}
.gap-2 {
gap: calc(var(--spacing) * 2);
}
.gap-3 {
gap: calc(var(--spacing) * 3);
}
.gap-4 {
gap: calc(var(--spacing) * 4);
}
.gap-8 {
gap: calc(var(--spacing) * 8);
}
@ -463,6 +464,12 @@
.gap-x-4 {
column-gap: calc(var(--spacing) * 4);
}
.gap-x-8 {
column-gap: calc(var(--spacing) * 8);
}
.gap-x-16 {
column-gap: calc(var(--spacing) * 16);
}
.overflow-hidden {
overflow: hidden;
}
@ -485,6 +492,18 @@
border-style: var(--tw-border-style);
border-width: 1px;
}
.border-1 {
border-style: var(--tw-border-style);
border-width: 1px;
}
.border-2 {
border-style: var(--tw-border-style);
border-width: 2px;
}
.border-t {
border-top-style: var(--tw-border-style);
border-top-width: 1px;
}
.border-r {
border-right-style: var(--tw-border-style);
border-right-width: 1px;
@ -510,11 +529,8 @@
.border-gray-300 {
border-color: var(--color-gray-300);
}
.border-gray-400 {
border-color: var(--color-gray-400);
}
.border-gray-500 {
border-color: var(--color-gray-500);
.border-red-400 {
border-color: var(--color-red-400);
}
.border-red-500 {
border-color: var(--color-red-500);
@ -522,12 +538,6 @@
.border-white {
border-color: var(--color-white);
}
.bg-blue-500 {
background-color: var(--color-blue-500);
}
.bg-gray-50 {
background-color: var(--color-gray-50);
}
.bg-gray-100 {
background-color: var(--color-gray-100);
}
@ -567,6 +577,9 @@
.p-4 {
padding: calc(var(--spacing) * 4);
}
.p-8 {
padding: calc(var(--spacing) * 8);
}
.px-1 {
padding-inline: calc(var(--spacing) * 1);
}
@ -576,9 +589,6 @@
.px-4 {
padding-inline: calc(var(--spacing) * 4);
}
.px-6 {
padding-inline: calc(var(--spacing) * 6);
}
.px-8 {
padding-inline: calc(var(--spacing) * 8);
}
@ -588,9 +598,6 @@
.py-1 {
padding-block: calc(var(--spacing) * 1);
}
.py-1\.5 {
padding-block: calc(var(--spacing) * 1.5);
}
.py-2 {
padding-block: calc(var(--spacing) * 2);
}
@ -672,21 +679,12 @@
.whitespace-nowrap {
white-space: nowrap;
}
.text-black {
color: var(--color-black);
}
.text-blue-500 {
color: var(--color-blue-500);
}
.text-gray-300 {
color: var(--color-gray-300);
}
.text-gray-400 {
color: var(--color-gray-400);
}
.text-gray-500 {
color: var(--color-gray-500);
}
.text-gray-600 {
color: var(--color-gray-600);
}
@ -696,6 +694,9 @@
.text-gray-800 {
color: var(--color-gray-800);
}
.text-red-400 {
color: var(--color-red-400);
}
.text-red-500 {
color: var(--color-red-500);
}
@ -708,6 +709,10 @@
.underline {
text-decoration-line: underline;
}
.shadow {
--tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
.shadow-2xs {
--tw-shadow: 0 1px var(--tw-shadow-color, rgb(0 0 0 / 0.05));
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
@ -726,6 +731,12 @@
--tw-shadow-color: color-mix(in oklab, var(--color-blue-300) var(--tw-shadow-alpha), transparent);
}
}
.shadow-blue-500 {
--tw-shadow-color: oklch(62.3% 0.214 259.815);
@supports (color: color-mix(in lab, red, red)) {
--tw-shadow-color: color-mix(in oklab, var(--color-blue-500) var(--tw-shadow-alpha), transparent);
}
}
.shadow-blue-700 {
--tw-shadow-color: oklch(48.8% 0.243 264.376);
@supports (color: color-mix(in lab, red, red)) {
@ -742,10 +753,6 @@
outline-style: var(--tw-outline-style);
outline-width: 1px;
}
.outline-2 {
outline-style: var(--tw-outline-style);
outline-width: 2px;
}
.filter {
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
}
@ -794,20 +801,6 @@
}
}
}
.hover\:border-blue-500 {
&:hover {
@media (hover: hover) {
border-color: var(--color-blue-500);
}
}
}
.hover\:bg-blue-600 {
&:hover {
@media (hover: hover) {
background-color: var(--color-blue-600);
}
}
}
.hover\:bg-gray-50 {
&:hover {
@media (hover: hover) {
@ -815,6 +808,20 @@
}
}
}
.hover\:bg-red-100 {
&:hover {
@media (hover: hover) {
background-color: var(--color-red-100);
}
}
}
.hover\:bg-red-200 {
&:hover {
@media (hover: hover) {
background-color: var(--color-red-200);
}
}
}
.hover\:text-blue-400 {
&:hover {
@media (hover: hover) {
@ -838,24 +845,6 @@
}
}
}
.hover\:shadow-sm {
&:hover {
@media (hover: hover) {
--tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
}
}
.hover\:shadow-blue-300 {
&:hover {
@media (hover: hover) {
--tw-shadow-color: oklch(80.9% 0.105 251.813);
@supports (color: color-mix(in lab, red, red)) {
--tw-shadow-color: color-mix(in oklab, var(--color-blue-300) var(--tw-shadow-alpha), transparent);
}
}
}
}
.hover\:ring-blue-700 {
&:hover {
@media (hover: hover) {
@ -863,46 +852,16 @@
}
}
}
.hover\:outline-2 {
&:hover {
@media (hover: hover) {
outline-style: var(--tw-outline-style);
outline-width: 2px;
}
}
}
.hover\:outline-blue-500 {
&:hover {
@media (hover: hover) {
outline-color: var(--color-blue-500);
}
}
}
.focus\:bg-blue-100 {
&:focus {
background-color: var(--color-blue-100);
}
}
.focus\:bg-blue-200 {
&:focus {
background-color: var(--color-blue-200);
}
}
.focus\:bg-blue-300 {
&:focus {
background-color: var(--color-blue-300);
}
}
.focus\:bg-gray-50 {
&:focus {
background-color: var(--color-gray-50);
}
}
.focus\:text-white {
&:focus {
color: var(--color-white);
}
}
.focus\:ring-2 {
&:focus {
--tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
@ -924,12 +883,6 @@
}
}
}
.focus\:outline-1 {
&:focus {
outline-style: var(--tw-outline-style);
outline-width: 1px;
}
}
.focus\:outline-2 {
&:focus {
outline-style: var(--tw-outline-style);
@ -1004,6 +957,11 @@
width: calc(1/2 * 100%);
}
}
.md\:w-1\/3 {
@media (width >= 48rem) {
width: calc(1/3 * 100%);
}
}
.md\:w-2\/3 {
@media (width >= 48rem) {
width: calc(2/3 * 100%);
@ -1014,11 +972,21 @@
width: calc(2/5 * 100%);
}
}
.md\:w-32 {
@media (width >= 48rem) {
width: calc(var(--spacing) * 32);
}
}
.md\:w-48 {
@media (width >= 48rem) {
width: calc(var(--spacing) * 48);
}
}
.md\:p-8 {
@media (width >= 48rem) {
padding: calc(var(--spacing) * 8);
}
}
.md\:px-44 {
@media (width >= 48rem) {
padding-inline: calc(var(--spacing) * 44);
@ -1052,6 +1020,18 @@
line-height: var(--tw-leading, var(--text-lg--line-height));
}
}
.md\:text-sm {
@media (width >= 48rem) {
font-size: var(--text-sm);
line-height: var(--tw-leading, var(--text-sm--line-height));
}
}
.md\:text-xl {
@media (width >= 48rem) {
font-size: var(--text-xl);
line-height: var(--tw-leading, var(--text-xl--line-height));
}
}
.lg\:flex {
@media (width >= 64rem) {
display: flex;