fix: place hours and courses under schedule name (#388)

* fix(header): bottom-aligned the schedule name + hours/courses in calendar

* feat: updated font style in header and dropdown

* fix: new hour/course styling per discussion

i love having 80 different ideas, hopefully after this there's like maybe a tiny commit left to do before this is done..

* feat(header): added icons to cal header

WORK IN PROGRESS

* style: updated layout of header and main popup

* fix: updated font and spacing for header and popup

* fix: updated cal + popup style details
- schedule title is now in normal casing w/ colon removed
- last updated on is now entirely deleted from everywhere
- hour and course numbers now h3 in calendar ONLY

* refactor: changed size for calendar header

* refactor: changed ut-black to theme-black

* refactor: remove hiding on small window sizes

* refactor: reduced spacing in popup

* refactor: updated unocss for small-caps configuration

* style: changed variant + className order

* fix: readded update time text

* style: auto formatter, unused imports, capitalization

---------

Co-authored-by: Razboy20 <razboy20@gmail.com>
Co-authored-by: Samuel Gunter <sgunter@utexas.edu>
Co-authored-by: doprz <52579214+doprz@users.noreply.github.com>
This commit is contained in:
Warith Rahman
2024-11-21 20:56:56 -06:00
committed by GitHub
parent 7dbffc6eef
commit 7dd93690d6
9 changed files with 76 additions and 44 deletions

View File

@@ -59,9 +59,11 @@
"@commitlint/types": "^19.5.0", "@commitlint/types": "^19.5.0",
"@crxjs/vite-plugin": "2.0.0-beta.21", "@crxjs/vite-plugin": "2.0.0-beta.21",
"@iconify-json/bi": "^1.2.1", "@iconify-json/bi": "^1.2.1",
"@iconify-json/ic": "^1.2.1",
"@iconify-json/iconoir": "^1.2.4", "@iconify-json/iconoir": "^1.2.4",
"@iconify-json/material-symbols": "^1.2.6", "@iconify-json/material-symbols": "^1.2.6",
"@iconify-json/ri": "^1.2.3", "@iconify-json/ri": "^1.2.3",
"@iconify-json/streamline": "^1.2.1",
"@semantic-release/exec": "^6.0.3", "@semantic-release/exec": "^6.0.3",
"@sentry/types": "^8.38.0", "@sentry/types": "^8.38.0",
"@storybook/addon-designs": "^8.0.4", "@storybook/addon-designs": "^8.0.4",

21
pnpm-lock.yaml generated
View File

@@ -110,6 +110,9 @@ importers:
'@iconify-json/bi': '@iconify-json/bi':
specifier: ^1.2.1 specifier: ^1.2.1
version: 1.2.1 version: 1.2.1
'@iconify-json/ic':
specifier: ^1.2.1
version: 1.2.1
'@iconify-json/iconoir': '@iconify-json/iconoir':
specifier: ^1.2.4 specifier: ^1.2.4
version: 1.2.4 version: 1.2.4
@@ -119,6 +122,9 @@ importers:
'@iconify-json/ri': '@iconify-json/ri':
specifier: ^1.2.3 specifier: ^1.2.3
version: 1.2.3 version: 1.2.3
'@iconify-json/streamline':
specifier: ^1.2.1
version: 1.2.1
'@semantic-release/exec': '@semantic-release/exec':
specifier: ^6.0.3 specifier: ^6.0.3
version: 6.0.3(semantic-release@24.2.0(typescript@5.6.3)) version: 6.0.3(semantic-release@24.2.0(typescript@5.6.3))
@@ -1053,6 +1059,9 @@ packages:
'@iconify-json/bi@1.2.1': '@iconify-json/bi@1.2.1':
resolution: {integrity: sha512-wsIWb6bcnBkfN8/2puIIE2ul6NYVjclbE/nI7JZsPnfzBamd3NuRFstXQH9Ckkbrw9eiBTNKwHbH90w3UE5QIg==} resolution: {integrity: sha512-wsIWb6bcnBkfN8/2puIIE2ul6NYVjclbE/nI7JZsPnfzBamd3NuRFstXQH9Ckkbrw9eiBTNKwHbH90w3UE5QIg==}
'@iconify-json/ic@1.2.1':
resolution: {integrity: sha512-UjL/bjJP/T5EV881+hTzcfTKVo0KEUjhnMiJcLtPzNgPtU2KZZmRx8BSKKR61H4CN/5FTEbyawGyG0aEt3SwGQ==}
'@iconify-json/iconoir@1.2.4': '@iconify-json/iconoir@1.2.4':
resolution: {integrity: sha512-PILwyd8to0DFnMdT0s1RogIT+PRbh0THfvFxi94zobIRpsx/It/slFJHH6bslzXZLPRMSBebNwjqwQt5FvWlSQ==} resolution: {integrity: sha512-PILwyd8to0DFnMdT0s1RogIT+PRbh0THfvFxi94zobIRpsx/It/slFJHH6bslzXZLPRMSBebNwjqwQt5FvWlSQ==}
@@ -1062,6 +1071,9 @@ packages:
'@iconify-json/ri@1.2.3': '@iconify-json/ri@1.2.3':
resolution: {integrity: sha512-UVKofd5xkSevGd5K01pvO4NWsu+2C9spu+GxnMZUYymUiaWmpCAxtd22MFSpm6MGf0MP4GCwhDCo1Q8L8oZ9wg==} resolution: {integrity: sha512-UVKofd5xkSevGd5K01pvO4NWsu+2C9spu+GxnMZUYymUiaWmpCAxtd22MFSpm6MGf0MP4GCwhDCo1Q8L8oZ9wg==}
'@iconify-json/streamline@1.2.1':
resolution: {integrity: sha512-hqNodkjyIHBymkFY3zMip0F/D5yw4qXgwMJCaTF3zlbpQMgNJhY3D2ikTFTDVcTHfCSd6EX6enKXj4Rvu+5hnw==}
'@iconify/types@2.0.0': '@iconify/types@2.0.0':
resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
@@ -5725,7 +5737,6 @@ packages:
engines: {node: '>=0.6.0', teleport: '>=0.2.0'} engines: {node: '>=0.6.0', teleport: '>=0.2.0'}
deprecated: |- deprecated: |-
You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other. You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.
(For a CapTP with native promises, see @endo/eventual-send and @endo/captp) (For a CapTP with native promises, see @endo/eventual-send and @endo/captp)
queue-microtask@1.2.3: queue-microtask@1.2.3:
@@ -7535,6 +7546,10 @@ snapshots:
dependencies: dependencies:
'@iconify/types': 2.0.0 '@iconify/types': 2.0.0
'@iconify-json/ic@1.2.1':
dependencies:
'@iconify/types': 2.0.0
'@iconify-json/iconoir@1.2.4': '@iconify-json/iconoir@1.2.4':
dependencies: dependencies:
'@iconify/types': 2.0.0 '@iconify/types': 2.0.0
@@ -7547,6 +7562,10 @@ snapshots:
dependencies: dependencies:
'@iconify/types': 2.0.0 '@iconify/types': 2.0.0
'@iconify-json/streamline@1.2.1':
dependencies:
'@iconify/types': 2.0.0
'@iconify/types@2.0.0': {} '@iconify/types@2.0.0': {}
'@iconify/utils@2.1.33': '@iconify/utils@2.1.33':

View File

@@ -1,5 +1,5 @@
import type { Meta, StoryObj } from '@storybook/react'; import type { Meta, StoryObj } from '@storybook/react';
import CalendarHeader from '@views/components/calendar/CalenderHeader'; import CalendarHeader from '@views/components/calendar/CalendarHeader';
const meta = { const meta = {
title: 'Components/Calendar/CalendarHeader', title: 'Components/Calendar/CalendarHeader',

View File

@@ -2,8 +2,8 @@ import type { CalendarTabMessages } from '@shared/messages/CalendarMessages';
import type { Course } from '@shared/types/Course'; import type { Course } from '@shared/types/Course';
import CalendarBottomBar from '@views/components/calendar/CalendarBottomBar'; import CalendarBottomBar from '@views/components/calendar/CalendarBottomBar';
import CalendarGrid from '@views/components/calendar/CalendarGrid'; import CalendarGrid from '@views/components/calendar/CalendarGrid';
import CalendarHeader from '@views/components/calendar/CalendarHeader';
import { CalendarSchedules } from '@views/components/calendar/CalendarSchedules'; import { CalendarSchedules } from '@views/components/calendar/CalendarSchedules';
import CalendarHeader from '@views/components/calendar/CalenderHeader';
import ImportantLinks from '@views/components/calendar/ImportantLinks'; import ImportantLinks from '@views/components/calendar/ImportantLinks';
import Divider from '@views/components/common/Divider'; import Divider from '@views/components/common/Divider';
import CourseCatalogInjectedPopup from '@views/components/injected/CourseCatalogInjectedPopup/CourseCatalogInjectedPopup'; import CourseCatalogInjectedPopup from '@views/components/injected/CourseCatalogInjectedPopup/CourseCatalogInjectedPopup';

View File

@@ -4,9 +4,7 @@ import CourseStatus from '@views/components/common/CourseStatus';
import Divider from '@views/components/common/Divider'; import Divider from '@views/components/common/Divider';
import { LargeLogo } from '@views/components/common/LogoIcon'; import { LargeLogo } from '@views/components/common/LogoIcon';
import ScheduleTotalHoursAndCourses from '@views/components/common/ScheduleTotalHoursAndCourses'; import ScheduleTotalHoursAndCourses from '@views/components/common/ScheduleTotalHoursAndCourses';
import Text from '@views/components/common/Text/Text';
import useSchedules from '@views/hooks/useSchedules'; import useSchedules from '@views/hooks/useSchedules';
import { getUpdatedAtDateTimeString } from '@views/lib/getUpdatedAtDateTimeString';
import { openTabFromContentScript } from '@views/lib/openNewTabFromContentScript'; import { openTabFromContentScript } from '@views/lib/openNewTabFromContentScript';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
@@ -33,7 +31,7 @@ interface CalendarHeaderProps {
*/ */
export default function CalendarHeader({ onSidebarToggle }: CalendarHeaderProps): JSX.Element { export default function CalendarHeader({ onSidebarToggle }: CalendarHeaderProps): JSX.Element {
const [enableCourseStatusChips, setEnableCourseStatusChips] = useState<boolean>(false); const [enableCourseStatusChips, setEnableCourseStatusChips] = useState<boolean>(false);
const [enableDataRefreshing, setEnableDataRefreshing] = useState<boolean>(false); const [_enableDataRefreshing, setEnableDataRefreshing] = useState<boolean>(false);
const [activeSchedule] = useSchedules(); const [activeSchedule] = useSchedules();
@@ -76,16 +74,6 @@ export default function CalendarHeader({ onSidebarToggle }: CalendarHeaderProps)
totalHours={activeSchedule.hours} totalHours={activeSchedule.hours}
totalCourses={activeSchedule.courses.length} totalCourses={activeSchedule.courses.length}
/> />
{enableDataRefreshing && (
<div className='flex items-center gap-1 screenshot:hidden'>
<Text variant='mini' className='text-nowrap text-ut-gray font-normal!'>
LAST UPDATED: {getUpdatedAtDateTimeString(activeSchedule.updatedAt)}
</Text>
{/* <button className='inline-block h-4 w-4 bg-transparent p-0 btn'>
<RefreshIcon className='h-4 w-4 animate-duration-800 text-ut-black' />
</button> */}
</div>
)}
</div> </div>
<div className='hidden flex-row items-center justify-end gap-6 screenshot:hidden lg:flex'> <div className='hidden flex-row items-center justify-end gap-6 screenshot:hidden lg:flex'>
{enableCourseStatusChips && ( {enableCourseStatusChips && (
@@ -98,7 +86,7 @@ export default function CalendarHeader({ onSidebarToggle }: CalendarHeaderProps)
{/* <Button variant='single' icon={UndoIcon} color='ut-black' /> {/* <Button variant='single' icon={UndoIcon} color='ut-black' />
<Button variant='single' icon={RedoIcon} color='ut-black' /> */} <Button variant='single' icon={RedoIcon} color='ut-black' /> */}
<Button variant='single' icon={SettingsIcon} color='ut-black' onClick={handleOpenOptions} /> <Button variant='single' icon={SettingsIcon} color='theme-black' onClick={handleOpenOptions} />
</div> </div>
</div> </div>
); );

View File

@@ -27,17 +27,23 @@ export default function ScheduleDropdown(props: ScheduleDropdownProps) {
<> <>
<DisclosureButton className='w-full flex items-center border-none bg-transparent px-3.5 py-2.5 text-left'> <DisclosureButton className='w-full flex items-center border-none bg-transparent px-3.5 py-2.5 text-left'>
<div className='flex-1'> <div className='flex-1'>
<Text as='div' variant='h4' className='mb-1 w-100% text-ut-burntorange'> <Text as='div' variant='h3' className='w-100% text-ut-burntorange normal-case!'>
{(activeSchedule ? activeSchedule.name : 'Schedule').toUpperCase()}: {activeSchedule ? activeSchedule.name : 'Schedule'}
</Text> </Text>
<p className='-mb-0.5'> <div className='flex gap-2.5 text-theme-black leading-[75%]!'>
<Text variant='h3' className='text-theme-black leading-[75%]!'> <div className='flex gap-1.25'>
{activeSchedule ? activeSchedule.hours : 0} HOURS <Text variant='h4'>{activeSchedule ? activeSchedule.hours : 0}</Text>
</Text> <Text variant='h4' className='font-all-small-caps!'>
<Text variant='h4' className='ml-2.5 text-ut-black leading-[75%]!'> {activeSchedule.hours === 1 ? 'HOUR' : 'HOURS'}
{activeSchedule ? activeSchedule.courses.length : 0} Courses </Text>
</Text> </div>
</p> <div className='flex gap-1.25'>
<Text variant='h4'>{activeSchedule ? activeSchedule.courses.length : 0}</Text>
<Text variant='h4' className='font-all-small-caps!'>
{activeSchedule.courses.length === 1 ? 'COURSE' : 'COURSES'}
</Text>
</div>
</div>
</div> </div>
<Text className='text-ut-burntorange text-2xl! font-normal!'> <Text className='text-ut-burntorange text-2xl! font-normal!'>
{open ? <DropdownArrowDown /> : <DropdownArrowUp />} {open ? <DropdownArrowDown /> : <DropdownArrowUp />}

View File

@@ -24,16 +24,36 @@ export default function ScheduleTotalHoursAndCourses({
totalCourses, totalCourses,
}: ScheduleTotalHoursAndCoursesProps): JSX.Element { }: ScheduleTotalHoursAndCoursesProps): JSX.Element {
return ( return (
<div className='min-w-full w-0 flex items-center gap-2.5 whitespace-nowrap'> <div className='min-w-full w-0 items-center whitespace-nowrap'>
<Text className='truncate text-ut-burntorange uppercase' variant='h1' as='span'> <Text className='truncate text-ut-burntorange normal-case!' variant='h1' as='span'>
{`${scheduleName}: `} {scheduleName}
</Text>
<Text variant='h3' as='div' className='flex flex-row items-center gap-2 text-theme-black'>
{totalHours} {totalHours === 1 ? 'Hour' : 'Hours'}
<Text variant='h4' as='span' className='hidden capitalize screenshot:inline sm:inline'>
{totalCourses} {totalCourses === 1 ? 'Course' : 'Courses'}
</Text>
</Text> </Text>
<div className='flex flex-row items-center gap-2.5 text-theme-black'>
<div className='flex flex-row items-center gap-1.25 text-theme-black'>
<Text variant='h3' as='span' className='capitalize screenshot:inline sm:inline'>
{totalHours}
</Text>
<Text
variant='h3'
as='span'
className='capitalize screenshot:inline sm:inline font-all-small-caps!'
>
{totalHours === 1 ? 'HOUR' : 'HOURS'}
</Text>
</div>
<div className='flex flex-row items-center gap-1.25 text-theme-black'>
<Text variant='h3' as='span' className='capitalize screenshot:inline sm:inline'>
{totalCourses}
</Text>
<Text
variant='h3'
as='span'
className='capitalize screenshot:inline sm:inline font-all-small-caps!'
>
{totalCourses === 1 ? 'COURSE' : 'COURSES'}
</Text>
</div>
</div>
</div> </div>
); );
} }

View File

@@ -3,7 +3,6 @@ import { addCourseByURL } from '@pages/background/lib/addCourseByURL';
import { deleteAllSchedules } from '@pages/background/lib/deleteSchedule'; import { deleteAllSchedules } from '@pages/background/lib/deleteSchedule';
import exportSchedule from '@pages/background/lib/exportSchedule'; import exportSchedule from '@pages/background/lib/exportSchedule';
import importSchedule from '@pages/background/lib/importSchedule'; import importSchedule from '@pages/background/lib/importSchedule';
import { background } from '@shared/messages';
import { initSettings, OptionsStore } from '@shared/storage/OptionsStore'; import { initSettings, OptionsStore } from '@shared/storage/OptionsStore';
import { UserScheduleStore } from '@shared/storage/UserScheduleStore'; import { UserScheduleStore } from '@shared/storage/UserScheduleStore';
import { downloadBlob } from '@shared/util/downloadBlob'; import { downloadBlob } from '@shared/util/downloadBlob';
@@ -23,7 +22,6 @@ import useSchedules from '@views/hooks/useSchedules';
// import getCourseTableRows from '@views/lib/getCourseTableRows'; // import getCourseTableRows from '@views/lib/getCourseTableRows';
import { GitHubStatsService, LONGHORN_DEVELOPERS_ADMINS, LONGHORN_DEVELOPERS_SWE } from '@views/lib/getGitHubStats'; import { GitHubStatsService, LONGHORN_DEVELOPERS_ADMINS, LONGHORN_DEVELOPERS_SWE } from '@views/lib/getGitHubStats';
// import { SiteSupport } from '@views/lib/getSiteSupport'; // import { SiteSupport } from '@views/lib/getSiteSupport';
import { getUpdatedAtDateTimeString } from '@views/lib/getUpdatedAtDateTimeString';
import clsx from 'clsx'; import clsx from 'clsx';
import React, { useCallback, useEffect, useState } from 'react'; import React, { useCallback, useEffect, useState } from 'react';
@@ -454,11 +452,6 @@ export default function Settings(): JSX.Element {
</div> </div>
{DISPLAY_PREVIEWS && ( {DISPLAY_PREVIEWS && (
<Preview> <Preview>
<div className='inline-flex items-center self-center gap-1'>
<Text variant='small' className='text-ut-gray !font-normal'>
LAST UPDATED: {getUpdatedAtDateTimeString(activeSchedule.updatedAt)}
</Text>
</div>
<Text <Text
variant='h2-course' variant='h2-course'
className={clsx('text-center text-theme-red !font-normal', { className={clsx('text-center text-theme-red !font-normal', {

View File

@@ -10,7 +10,10 @@ export default defineConfig({
rules: [ rules: [
[ [
'btn-transition', 'btn-transition',
{ transition: 'color 180ms ease-in, border-color 150ms ease-in, background-color 150ms ease-in, box-shadow 200ms ease-in, transform 50ms ease-in' } {
transition:
'color 180ms ease-in, border-color 150ms ease-in, background-color 150ms ease-in, box-shadow 200ms ease-in, transform 50ms ease-in',
},
], ],
[ [
'ring-offset-0', 'ring-offset-0',
@@ -18,6 +21,7 @@ export default defineConfig({
'--un-ring-offset-width': '0px', '--un-ring-offset-width': '0px',
}, },
], ],
['font-all-small-caps', { 'font-variant-caps': 'all-small-caps' }],
], ],
shortcuts: { shortcuts: {
focusable: 'outline-none ring-blue-500/50 dark:ring-blue-400/60 ring-0 focus-visible:ring-4', focusable: 'outline-none ring-blue-500/50 dark:ring-blue-400/60 ring-0 focus-visible:ring-4',